From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: Re: next-error use cases Date: Fri, 13 Apr 2018 22:48:59 +0300 Organization: LINKOV.NET Message-ID: <87d0z2anv8.fsf@mail.linkov.net> References: <87zi2esn7l.fsf@mail.linkov.net> <87r2nknpaz.fsf@mail.linkov.net> <83y3hr5z35.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1523649009 6571 195.159.176.226 (13 Apr 2018 19:50:09 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 13 Apr 2018 19:50:09 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (x86_64-pc-linux-gnu) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Apr 13 21:50:05 2018 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1f74hw-0001WC-Oc for ged-emacs-devel@m.gmane.org; Fri, 13 Apr 2018 21:50:05 +0200 Original-Received: from localhost ([::1]:49568 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f74k1-0000TR-To for ged-emacs-devel@m.gmane.org; Fri, 13 Apr 2018 15:52:13 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54205) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f74js-0000SG-Uf for emacs-devel@gnu.org; Fri, 13 Apr 2018 15:52:06 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f74jr-00059a-1O for emacs-devel@gnu.org; Fri, 13 Apr 2018 15:52:04 -0400 Original-Received: from sub3.mail.dreamhost.com ([69.163.253.7]:37195 helo=homiemail-a17.g.dreamhost.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f74jl-00051z-5X; Fri, 13 Apr 2018 15:51:57 -0400 Original-Received: from homiemail-a17.g.dreamhost.com (localhost [127.0.0.1]) by homiemail-a17.g.dreamhost.com (Postfix) with ESMTP id 7CC5B2B2076; Fri, 13 Apr 2018 12:51:54 -0700 (PDT) Original-Received: from localhost.linkov.net (m91-129-105-236.cust.tele2.ee [91.129.105.236]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: jurta@jurta.org) by homiemail-a17.g.dreamhost.com (Postfix) with ESMTPSA id 0DCBA2B206E; Fri, 13 Apr 2018 12:51:52 -0700 (PDT) In-Reply-To: <83y3hr5z35.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 13 Apr 2018 10:45:34 +0300") X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 69.163.253.7 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:224558 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable >> Since we removed the rule of visibility of next-error-function buffers >> as a criteria for deciding what navigation to use for next-error, >> so e.g. next-error in *Occur* or *Diff* that is the current buffer >> and a single visible buffer on the frame will still use the last next-= error >> buffer that might be e.g. *compilation* or *grep* buffer buried long a= go, >> now we need to support the same way to switch next-error navigation as >> already is possible in *compilation* and *grep* by typing RET or =E2=80= =98C-c C-c=E2=80=99 >> that sets next-error-last-buffer in next-error-internal among other th= ings. > > Sorry, I don't understand what kind of solution are you proposing in > user terms. Can you please describe what the user should do under the > proposed solution in various cases, such as if they need to invoke > navigation in the current Occur buffer or in a Compilation/Grep > buffer, either shown or not shown? I propose to set the global value of next-error-last-buffer after typing one of the following keybindings in the corresponding buffers: in *xref* xref-goto-xref: RET in *Diff* diff-goto-source: RET, C-c C-c, o in ChangeLogs change-log-goto-source: C-c C-c in *Occur* occur-mode-goto-occurrence: RET, C-c C-c, occur-mode-goto-occurrence-other-window: o occur-mode-display-occurrence: C-o IOW, doing the same what RET and C-c C-c in *compilation* and *grep* alre= ady do. Here is the final tested patch with these changes: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=next-error.2.patch diff --git a/lisp/simple.el b/lisp/simple.el index efe5406..272905e 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -122,11 +122,13 @@ next-error-last-buffer similar mode is started, or when it is used with \\[next-error] or \\[compile-goto-error].") -;; next-error-last-buffer is made buffer-local to keep the reference +(defvar next-error-buffer nil + "The buffer-local value of the most recent `next-error' buffer.") +;; next-error-buffer is made buffer-local to keep the reference ;; to the parent buffer used to navigate to the current buffer, so the ;; next call of next-buffer will use the same parent buffer to ;; continue navigation from it. -(make-variable-buffer-local 'next-error-last-buffer) +(make-variable-buffer-local 'next-error-buffer) (defvar next-error-function nil "Function to use to find the next error in the current buffer. @@ -184,6 +186,15 @@ next-error-find-buffer-function :group 'next-error :version "27.1") +(defcustom next-error-found-function #'ignore + "Function called when a next locus is found and displayed. +Function is called with two arguments: a FROM-BUFFER buffer +from which next-error navigated, and a target buffer TO-BUFFER." + :type '(choice (const :tag "No default" ignore) + (function :tag "Other function")) + :group 'next-error + :version "27.1") + (defun next-error-buffer-on-selected-frame (&optional avoid-current extra-test-inclusive extra-test-exclusive) @@ -220,6 +231,14 @@ next-error-find-buffer (funcall next-error-find-buffer-function avoid-current extra-test-inclusive extra-test-exclusive) + ;; 1a. If next-error-buffer has no buffer-local value + ;; (i.e. never navigated to the current buffer from another), + ;; and the current buffer is a `next-error' capable buffer, + ;; use it unconditionally, so next-error will always use it. + (if (and (not (local-variable-p 'next-error-buffer)) + (next-error-buffer-p (current-buffer) avoid-current + extra-test-inclusive extra-test-exclusive)) + (current-buffer)) ;; 2. If next-error-last-buffer is an acceptable buffer, use that. (if (and next-error-last-buffer (next-error-buffer-p next-error-last-buffer avoid-current @@ -284,37 +303,35 @@ next-error (when buffer ;; We know here that next-error-function is a valid symbol we can funcall (with-current-buffer buffer - ;; Allow next-error to be used from the next-error capable buffer. - (setq next-error-last-buffer buffer) (funcall next-error-function (prefix-numeric-value arg) reset) - ;; Override possible change of next-error-last-buffer in next-error-function - (setq next-error-last-buffer buffer) - (setq-default next-error-last-buffer buffer) - (when next-error-recenter - (recenter next-error-recenter)) - (message "%s error from %s" + (next-error-found buffer (current-buffer)) + (message "%s locus from %s" (cond (reset "First") ((eq (prefix-numeric-value arg) 0) "Current") ((< (prefix-numeric-value arg) 0) "Previous") (t "Next")) - next-error-last-buffer) - (run-hooks 'next-error-hook))))) + next-error-last-buffer))))) (defun next-error-internal () "Visit the source code corresponding to the `next-error' message at point." (let ((buffer (current-buffer))) ;; We know here that next-error-function is a valid symbol we can funcall - (with-current-buffer buffer - ;; Allow next-error to be used from the next-error capable buffer. - (setq next-error-last-buffer buffer) - (funcall next-error-function 0 nil) - ;; Override possible change of next-error-last-buffer in next-error-function - (setq next-error-last-buffer buffer) - (setq-default next-error-last-buffer buffer) - (when next-error-recenter - (recenter next-error-recenter)) - (message "Current error from %s" next-error-last-buffer) - (run-hooks 'next-error-hook)))) + (funcall next-error-function 0 nil) + (next-error-found buffer (current-buffer)) + (message "Current locus from %s" next-error-last-buffer))) + +(defun next-error-found (&optional from-buffer to-buffer) + "Function to call when the next locus is found and displayed. +FROM-BUFFER is a buffer from which next-error navigated, +and TO-BUFFER is a target buffer." + (setq next-error-last-buffer (or from-buffer (current-buffer))) + (when to-buffer + (with-current-buffer to-buffer + (setq next-error-buffer from-buffer))) + (when next-error-recenter + (recenter next-error-recenter)) + (funcall next-error-found-function from-buffer to-buffer) + (run-hooks 'next-error-hook)) (defun next-error-select-buffer (buffer) "Select a `next-error' capable buffer and set it as the last used." @@ -322,8 +339,7 @@ next-error-select-buffer (list (get-buffer (read-buffer "Select next-error buffer: " nil nil (lambda (b) (next-error-buffer-p (cdr b))))))) - (setq next-error-last-buffer buffer) - (setq-default next-error-last-buffer buffer)) + (setq next-error-last-buffer buffer)) (defalias 'goto-next-locus 'next-error) (defalias 'next-match 'next-error) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 5a9a7a9..9a437b6 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -540,9 +540,11 @@ xref-goto-xref Non-interactively, non-nil QUIT means to first quit the *xref* buffer." (interactive) - (let ((xref (or (xref--item-at-point) + (let ((buffer (current-buffer)) + (xref (or (xref--item-at-point) (user-error "No reference at point")))) - (xref--show-location (xref-item-location xref) (if quit 'quit t)))) + (xref--show-location (xref-item-location xref) (if quit 'quit t)) + (next-error-found buffer (current-buffer)))) (defun xref-quit-and-goto-xref () "Quit *xref* buffer, then jump to xref on current line." diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el index 175c82f..d423706 100644 --- a/lisp/vc/add-log.el +++ b/lisp/vc/add-log.el @@ -471,6 +471,11 @@ change-log-goto-source comma-separated list. If no suitable tag can be found nearby, try to visit the file for the change under `point' instead." (interactive) + (let ((buffer (current-buffer))) + (change-log-goto-source-internal) + (next-error-found buffer (current-buffer)))) + +(defun change-log-goto-source-internal () (if (and (eq last-command 'change-log-goto-source) change-log-find-tail) (setq change-log-find-tail @@ -539,7 +545,7 @@ change-log-next-error ;; if we found a place to visit... (when (looking-at change-log-file-names-re) (let (change-log-find-window) - (change-log-goto-source) + (change-log-goto-source-internal) (when change-log-find-window ;; Select window displaying source file. (select-window change-log-find-window))))) @@ -1067,8 +1073,7 @@ change-log-mode (set (make-local-variable 'end-of-defun-function) 'change-log-end-of-defun) ;; next-error function glue - (setq next-error-function 'change-log-next-error) - (setq next-error-last-buffer (current-buffer))) + (setq next-error-function 'change-log-next-error)) (defun change-log-next-buffer (&optional buffer wrap) "Return the next buffer in the series of ChangeLog file buffers. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index ef13f55..1e2fbb9 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -1874,11 +1874,13 @@ diff-goto-source ;; the old location, and else to the new (i.e. as if reverting). ;; This is a convenient detail when using smerge-diff. (if event (posn-set-point (event-end event))) - (let ((rev (not (save-excursion (beginning-of-line) (looking-at "[-<]"))))) + (let ((buffer (when event (current-buffer))) + (rev (not (save-excursion (beginning-of-line) (looking-at "[-<]"))))) (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,switched) (diff-find-source-location other-file rev))) (pop-to-buffer buf) (goto-char (+ (car pos) (cdr src))) + (when buffer (next-error-found buffer (current-buffer))) (diff-hunk-status-msg line-offset (diff-xor rev switched) t)))) diff --git a/lisp/replace.el b/lisp/replace.el index 4916cb1..5835c9c 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1192,7 +1194,8 @@ 'occur-mode-mouse-goto (defun occur-mode-goto-occurrence (&optional event) "Go to the occurrence on the current line." (interactive (list last-nonmenu-event)) - (let ((pos + (let ((buffer (when event (current-buffer))) + (pos (if (null event) ;; Actually `event-end' works correctly with a nil argument as ;; well, so we could dispense with this test, but let's not @@ -1204,26 +1207,31 @@ occur-mode-goto-occurrence (occur-mode-find-occurrence)))))) (pop-to-buffer (marker-buffer pos)) (goto-char pos) + (when buffer (next-error-found buffer (current-buffer))) (run-hooks 'occur-mode-find-occurrence-hook))) (defun occur-mode-goto-occurrence-other-window () "Go to the occurrence the current line describes, in another window." (interactive) - (let ((pos (occur-mode-find-occurrence))) + (let ((buffer (current-buffer)) + (pos (occur-mode-find-occurrence))) (switch-to-buffer-other-window (marker-buffer pos)) (goto-char pos) + (next-error-found buffer (current-buffer)) (run-hooks 'occur-mode-find-occurrence-hook))) (defun occur-mode-display-occurrence () "Display in another window the occurrence the current line describes." (interactive) - (let ((pos (occur-mode-find-occurrence)) + (let ((buffer (current-buffer)) + (pos (occur-mode-find-occurrence)) window) (setq window (display-buffer (marker-buffer pos) t)) ;; This is the way to set point in the proper window. (save-selected-window (select-window window) (goto-char pos) + (next-error-found buffer (current-buffer)) (run-hooks 'occur-mode-find-occurrence-hook)))) (defun occur-find-match (n search message) @@ -1254,28 +1262,20 @@ occur-next-error Compatibility function for \\[next-error] invocations." (interactive "p") ;; we need to run occur-find-match from within the Occur buffer - (with-current-buffer - ;; Choose the buffer and make it current. - (if (next-error-buffer-p (current-buffer)) - (current-buffer) - (next-error-find-buffer nil nil - (lambda () - (eq major-mode 'occur-mode)))) - - (goto-char (cond (reset (point-min)) - ((< argp 0) (line-beginning-position)) - ((> argp 0) (line-end-position)) - ((point)))) - (occur-find-match - (abs argp) - (if (> 0 argp) - #'previous-single-property-change - #'next-single-property-change) - "No more matches") - ;; In case the *Occur* buffer is visible in a nonselected window. - (let ((win (get-buffer-window (current-buffer) t))) - (if win (set-window-point win (point)))) - (occur-mode-goto-occurrence))) + (goto-char (cond (reset (point-min)) + ((< argp 0) (line-beginning-position)) + ((> argp 0) (line-end-position)) + ((point)))) + (occur-find-match + (abs argp) + (if (> 0 argp) + #'previous-single-property-change + #'next-single-property-change) + "No more matches") + ;; In case the *Occur* buffer is visible in a nonselected window. + (let ((win (get-buffer-window (current-buffer) t))) + (if win (set-window-point win (point)))) + (occur-mode-goto-occurrence)) (defface match '((((class color) (min-colors 88) (background light)) --=-=-=--