emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Push mark before jumping to new location for xref


From: Kelly Dean
Subject: [PATCH] Push mark before jumping to new location for xref
Date: Tue, 17 Feb 2015 02:21:48 +0000

When following a link in the help page for a function or variable to open the 
source code file, and the file is already open, Emacs moves point in that 
buffer, but it doesn't push the mark first, so the user loses his previous 
place. It should push the mark first.

The find-tag command does push the mark, but it's too trigger-happy: it pushes 
the mark even if the file was _not_ already open. Since the mark ring is for 
the user's use to keep track of where he was in the buffer, the extraneous push 
leaves the user later wondering whether that file had already been open for 
some reason, or whether Emacs was just being sloppy. This affects me when I 
look at several xref targets in the same files; if Emacs is fixed to avoid the 
extraneous push, then I can just try to go to the previous mark, and if it says 
there's no mark set, I immediately know that I looked at no other targets in 
the current buffer.

The attached patch solves both issues. It pushes the mark for both help xref 
and find-tag if the buffer is already open, and it avoids pushing otherwise. 
(Applies to 24.4; not updated for trunk yet.)

I posted an earlier version of this patch in 2012, but it was poorly designed, 
incomplete, and buggy, and was therefore ignored.

Maybe this updated version will be considered poorly designed too, because it 
still uses a dynamic variable as an implicit return value. But if not this way, 
then what other practical solution is there?

--- lisp/files.el
+++ lisp/files.el
@@ -1816,12 +1816,15 @@
 If a buffer exists visiting FILENAME, return that one, but
 verify that the file has not changed since visited or saved.
 The buffer is not selected, just returned to the caller.
+If a buffer exists visiting FILENAME, and the dynamic variable
+buffer-preexisted is bound, set it to t.
 Optional second arg NOWARN non-nil means suppress any warning messages.
 Optional third arg RAWFILE non-nil means the file is read literally.
 Optional fourth arg WILDCARDS non-nil means do wildcard processing
 and visit all the matching files.  When wildcards are actually
 used and expanded, return a list of buffers that are visiting
 the various files."
+  (defvar buffer-preexisted) ; Tell byte compiler about free dynamic var
   (setq filename
        (abbreviate-file-name
         (expand-file-name filename)))
@@ -1981,6 +1984,8 @@
                      (error (if rawfile "File already visited non-literally"
                               "File already visited literally"))))))
              ;; Return the buffer we are using.
+             (if (boundp 'buffer-preexisted)
+                 (setq buffer-preexisted t))
              buf)
          ;; Create a new buffer.
          (setq buf (create-file-buffer filename))
--- lisp/emacs-lisp/find-func.el
+++ lisp/emacs-lisp/find-func.el
@@ -212,6 +212,7 @@
                      (indirect-function
                       (find-function-advised-original fun-or-var)))))
   (with-current-buffer (find-file-noselect file)
+    (save-excursion
     (goto-char (point-min))
     (unless (re-search-forward
             (if type
@@ -223,7 +224,7 @@
                       "\""))
             nil t)
       (error "Can't find source for %s" fun-or-var))
-    (cons (current-buffer) (match-beginning 0))))
+      (cons (current-buffer) (match-beginning 0)))))
 
 ;;;###autoload
 (defun find-library (library)
@@ -283,6 +284,7 @@
     (let* ((filename (find-library-name library))
           (regexp-symbol (cdr (assq type find-function-regexp-alist))))
       (with-current-buffer (find-file-noselect filename)
+       (save-excursion
        (let ((regexp (format (symbol-value regexp-symbol)
                              ;; Entry for ` (backquote) macro in loaddefs.el,
                              ;; (defalias (quote \`)..., has a \ but
@@ -310,7 +312,7 @@
                (progn
                  (beginning-of-line)
                  (cons (current-buffer) (point)))
-             (cons (current-buffer) nil))))))))
+               (cons (current-buffer) nil)))))))))
 
 ;;;###autoload
 (defun find-function-noselect (function &optional lisp-only)
--- lisp/help-mode.el
+++ lisp/help-mode.el
@@ -198,11 +198,16 @@
                           (help-C-file-name (indirect-function fun) 'fun)))
                   ;; Don't use find-function-noselect because it follows
                   ;; aliases (which fails for built-in functions).
-                  (let ((location
+                  (defvar buffer-preexisted)
+                  (let* (buffer-preexisted
+                        (location
                          (find-function-search-for-symbol fun nil file)))
                     (pop-to-buffer (car location))
                     (if (cdr location)
-                        (goto-char (cdr location))
+                        (progn (if (and (/= (cdr location) (point))
+                                        buffer-preexisted)
+                                   (push-mark))
+                         (goto-char (cdr location)))
                       (message "Unable to find location in file"))))
   'help-echo (purecopy "mouse-2, RET: find function's definition"))
 
@@ -211,8 +216,11 @@
   'help-function (lambda (fun file)
                   (setq file (locate-library file t))
                   (if (and file (file-readable-p file))
-                      (progn
+                      (defvar buffer-preexisted)
+                      (let* ((buffer-preexisted
+                              (find-buffer-visiting file)))
                         (pop-to-buffer (find-file-noselect file))
+                        (if buffer-preexisted (push-mark))
                         (goto-char (point-min))
                         (if (re-search-forward
                              (format "^[ \t]*(\\(cl-\\)?define-compiler-macro[ 
\t]+%s"
@@ -227,10 +235,15 @@
   'help-function (lambda (var &optional file)
                   (when (eq file 'C-source)
                     (setq file (help-C-file-name var 'var)))
-                  (let ((location (find-variable-noselect var file)))
+                  (defvar buffer-preexisted)
+                  (let* (buffer-preexisted
+                        (location (find-variable-noselect var file)))
                     (pop-to-buffer (car location))
                     (if (cdr location)
-                      (goto-char (cdr location))
+                        (progn (if (and (/= (cdr location) (point))
+                                        buffer-preexisted)
+                                   (push-mark))
+                         (goto-char (cdr location)))
                       (message "Unable to find location in file"))))
   'help-echo (purecopy "mouse-2, RET: find variable's definition"))
 
--- lisp/progmodes/etags.el
+++ lisp/progmodes/etags.el
@@ -1171,9 +1171,11 @@
 
       ;; Get the local value in the tags table buffer before switching buffers.
       (setq goto-func goto-tag-location-function)
+      (defvar buffer-preexisted)
+      (let (buffer-preexisted)
       (tag-find-file-of-tag-noselect file)
       (widen)
-      (push-mark)
+       (if buffer-preexisted (push-mark)))
       (funcall goto-func tag-info)
 
       ;; Return the buffer where the tag was found.
@@ -1183,6 +1185,7 @@
   "Find the right line in the specified FILE."
   ;; If interested in compressed-files, search files with extensions.
   ;; Otherwise, search only the real file.
+  (defvar buffer-preexisted) ; Tell byte compiler about free dynamic var
   (let* ((buffer-search-extensions (if auto-compression-mode
                                       tags-compression-info-list
                                     '("")))
@@ -1198,6 +1201,8 @@
     (while (and (not the-buffer) buffer-search-extensions)
       (setq the-buffer (find-buffer-visiting (concat file (car 
buffer-search-extensions))))
       (setq buffer-search-extensions (cdr buffer-search-extensions)))
+    (if (and the-buffer (boundp 'buffer-preexisted))
+       (setq buffer-preexisted t))
     ;; if found a buffer but file modified, ensure we re-read !
     (if (and the-buffer (not (verify-visited-file-modtime the-buffer)))
        (find-file-noselect (buffer-file-name the-buffer)))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]