aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Hahn <erik_hahn@gmx.de>2019-05-19 18:23:03 +0200
committerEivind Fonn <evfonn@gmail.com>2020-08-16 09:19:48 +0200
commitcc6324bfd214211fe0259290b322dccfbdcf447f (patch)
treedbd508e80cebde5cf1a14ca83f81dd391f48cc78
parent9f13907efa5db98d137c8ff5f22500018c57e56d (diff)
Treat all commands that change the buffer as jump commands
All commands that change the current buffer are jump commands. This was previously implemented using advices, but this did not catch all all applicable commands: find-file, for example, was ignored. Instead, use the post-command-hook to check if a command changed the buffer.
-rw-r--r--evil-jumps.el51
-rw-r--r--evil-tests.el17
2 files changed, 52 insertions, 16 deletions
diff --git a/evil-jumps.el b/evil-jumps.el
index a9c910a..c45e593 100644
--- a/evil-jumps.el
+++ b/evil-jumps.el
@@ -66,6 +66,10 @@
(defvar evil--jumps-jumping nil)
+(defvar evil--jumps-jumping-backward nil
+ "Set by `evil--jump-backward', used and cleared in the
+`post-command-hook' by `evil--jump-handle-buffer-crossing'")
+
(eval-when-compile (defvar evil--jumps-debug nil))
(defvar evil--jumps-buffer-targets "\\*\\(new\\|scratch\\)\\*"
@@ -79,7 +83,8 @@
(cl-defstruct evil-jumps-struct
ring
- (idx -1))
+ (idx -1)
+ previous-pos)
;; Is inlining this really worth it?
(defsubst evil--jumps-message (format &rest args)
@@ -237,6 +242,7 @@ POS defaults to point."
(evil--jumps-push))))
(defun evil--jump-backward (count)
+ (setq evil--jumps-jumping-backward t)
(let ((count (or count 1)))
(evil-motion-loop (nil count)
(let* ((struct (evil--jumps-get-current))
@@ -272,6 +278,7 @@ POS defaults to point."
(let* ((source-jump-struct (evil--jumps-get-current existing-window))
(source-list (evil--jumps-get-jumps source-jump-struct)))
(when (= (ring-length (evil--jumps-get-jumps target-jump-struct)) 0)
+ (setf (evil-jumps-struct-previous-pos target-jump-struct) (evil-jumps-struct-previous-pos source-jump-struct))
(setf (evil-jumps-struct-idx target-jump-struct) (evil-jumps-struct-idx source-jump-struct))
(setf (evil-jumps-struct-ring target-jump-struct) (ring-copy source-list)))))))
;; delete obsolete windows
@@ -282,20 +289,31 @@ POS defaults to point."
evil--jumps-window-jumps)))
(defun evil--jump-hook (&optional command)
- "Set jump point if COMMAND has a non-nil :jump property."
+ "`pre-command-hook' for evil-jumps.
+Set jump point if COMMAND has a non-nil `:jump' property. Otherwise,
+save the current position in case the command being executed will
+change the current buffer."
(setq command (or command this-command))
- (when (evil-get-command-property command :jump)
- (evil-set-jump)))
-
-(defadvice switch-to-buffer (before evil-jumps activate)
- (evil-set-jump))
-
-(defadvice split-window-internal (before evil-jumps activate)
- (evil-set-jump))
-
-(eval-after-load 'etags
- '(defadvice find-tag-noselect (before evil-jumps activate)
- (evil-set-jump)))
+ (if (evil-get-command-property command :jump)
+ (evil-set-jump)
+ (setf (evil-jumps-struct-previous-pos (evil--jumps-get-current))
+ (point-marker))))
+
+(defun evil--jump-handle-buffer-crossing ()
+ (let ((jumping-backward evil--jumps-jumping-backward))
+ (setq evil--jumps-jumping-backward nil)
+ (dolist (frame (frame-list))
+ (dolist (window (window-list frame))
+ (let* ((struct (evil--jumps-get-current window))
+ (previous-pos (evil-jumps-struct-previous-pos struct)))
+ (when previous-pos
+ (setf (evil-jumps-struct-previous-pos struct) nil)
+ (if (and (not jumping-backward)
+ (let ((previous-buffer (marker-buffer previous-pos)))
+ (and previous-buffer
+ (not (eq previous-buffer (window-buffer window))))))
+ (evil-set-jump previous-pos)
+ (set-marker previous-pos nil))))))))
(if (bound-and-true-p savehist-loaded)
(evil--jumps-savehist-load)
@@ -305,11 +323,14 @@ POS defaults to point."
(if evil-local-mode
(progn
(add-hook 'pre-command-hook #'evil--jump-hook nil t)
+ (add-hook 'post-command-hook #'evil--jump-handle-buffer-crossing nil t)
(add-hook 'next-error-hook #'evil-set-jump nil t)
(add-hook 'window-configuration-change-hook #'evil--jumps-window-configuration-hook nil t))
(remove-hook 'pre-command-hook #'evil--jump-hook t)
+ (remove-hook 'post-command-hook #'evil--jump-handle-buffer-crossing t)
(remove-hook 'next-error-hook #'evil-set-jump t)
- (remove-hook 'window-configuration-change-hook #'evil--jumps-window-configuration-hook t)))
+ (remove-hook 'window-configuration-change-hook #'evil--jumps-window-configuration-hook t)
+ (evil--jump-handle-buffer-crossing)))
(add-hook 'evil-local-mode-hook #'evil--jumps-install-or-uninstall)
diff --git a/evil-tests.el b/evil-tests.el
index dba07ce..37aecdc 100644
--- a/evil-tests.el
+++ b/evil-tests.el
@@ -8265,7 +8265,22 @@ maybe we need one line more with some text\n")
("\C-o")
"z [z] z z z z z z"
("3\C-i") ;; even after jumping forward 3 times it can't get past the 3rd z
- "z z [z] z z z z z"))))
+ "z z [z] z z z z z"))
+ (ert-info ("Jump across files")
+ (let ((temp-file (make-temp-file "evil-test-")))
+ (unwind-protect
+ (evil-test-buffer
+ "[z] z z z z z z"
+ ("\M-x" "find-file" [return] temp-file [return] "inew buffer" [escape])
+ "new buffe[r]"
+ ("\C-o")
+ "[z] z z z z z z"
+ ("\C-i")
+ "new buffe[r]")
+ (delete-file temp-file)
+ (with-current-buffer (get-file-buffer temp-file)
+ (set-buffer-modified-p nil))
+ (kill-buffer (get-file-buffer temp-file)))))))
(ert-deftest evil-test-jump-buffers ()
:tags '(evil jums)