all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Kelly Dean <kelly@prtime.org>
To: emacs-devel@gnu.org
Subject: [PATCH] Push mark before jumping to new location for xref
Date: Tue, 17 Feb 2015 02:21:48 +0000	[thread overview]
Message-ID: <TndkaLkWg5ktpgQRxnvWNqPk9sH1YpkjgEpZpU1uFNL@local> (raw)

[-- Attachment #1: Type: text/plain, Size: 1446 bytes --]

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?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: xref-push-mark-24.4.patch --]
[-- Type: text/x-diff, Size: 5713 bytes --]

--- 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	other threads:[~2015-02-17  2:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=TndkaLkWg5ktpgQRxnvWNqPk9sH1YpkjgEpZpU1uFNL@local \
    --to=kelly@prtime.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.