From: Juri Linkov <juri@linkov.net>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: next-error use cases
Date: Fri, 13 Apr 2018 22:48:59 +0300 [thread overview]
Message-ID: <87d0z2anv8.fsf@mail.linkov.net> (raw)
In-Reply-To: <83y3hr5z35.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 13 Apr 2018 10:45:34 +0300")
[-- Attachment #1: Type: text/plain, Size: 1497 bytes --]
>> 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 ago,
>> 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 ‘C-c C-c’
>> that sets next-error-last-buffer in next-error-internal among other things.
>
> 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* already do.
Here is the final tested patch with these changes:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: next-error.2.patch --]
[-- Type: text/x-diff, Size: 12070 bytes --]
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))
\f
(defface match
'((((class color) (min-colors 88) (background light))
next prev parent reply other threads:[~2018-04-13 19:48 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-07 21:47 next-error use cases Juri Linkov
2018-04-08 13:48 ` Eli Zaretskii
2018-04-08 19:56 ` Juri Linkov
2018-04-08 20:26 ` Clément Pit-Claudel
2018-04-08 20:35 ` Dmitry Gutov
2018-04-10 4:19 ` Stephen Leake
2018-04-10 14:28 ` Drew Adams
2018-04-09 2:24 ` Eli Zaretskii
2018-04-08 20:36 ` Dmitry Gutov
2018-04-09 14:48 ` Eli Zaretskii
2018-04-09 18:44 ` Charles A. Roelli
2018-04-09 20:47 ` Juri Linkov
2018-04-10 4:24 ` Stephen Leake
2018-04-10 20:06 ` Juri Linkov
[not found] ` <86woxe1l0l.fsf@stephe-leake.org>
2018-04-11 7:29 ` Dmitry Gutov
2018-04-11 20:46 ` Juri Linkov
2018-04-12 15:31 ` Stephen Leake
2018-04-12 15:25 ` Stephen Leake
2018-04-12 16:51 ` Dmitry Gutov
2018-04-13 16:22 ` Stephen Leake
2018-04-13 16:26 ` Dmitry Gutov
2018-04-10 23:06 ` Dmitry Gutov
2018-04-12 20:27 ` Juri Linkov
2018-04-13 7:45 ` Eli Zaretskii
2018-04-13 19:48 ` Juri Linkov [this message]
2020-05-19 1:10 ` Dmitry Gutov
2020-05-19 22:12 ` Juri Linkov
2020-05-21 1:57 ` Dmitry Gutov
2020-05-21 20:33 ` Vladimir Sedach
2020-05-21 21:02 ` Stefan Monnier
2020-05-21 21:53 ` Dmitry Gutov
2020-05-21 22:06 ` Juri Linkov
2020-05-21 22:49 ` Dmitry Gutov
2020-05-22 1:31 ` Clément Pit-Claudel
2020-05-22 19:10 ` Vladimir Sedach
2020-05-23 1:22 ` Clément Pit-Claudel
2020-05-23 1:27 ` Dmitry Gutov
[not found] ` <b386929f-4412-860d-343f-a728d6d7e816@gmail.com>
[not found] ` <c6c941bb-a160-f767-b266-6a17f4b4c2ca@yandex.ru>
[not found] ` <152f1200-a2d0-e137-418f-18ceb14fbbe3@gmail.com>
2020-05-23 15:29 ` Drew Adams
2020-05-24 1:36 ` Dmitry Gutov
2020-05-24 1:41 ` Clément Pit-Claudel
2020-05-24 14:25 ` Dmitry Gutov
2020-05-22 23:50 ` Dmitry Gutov
2020-05-23 1:25 ` Clément Pit-Claudel
2020-05-23 1:29 ` Dmitry Gutov
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=87d0z2anv8.fsf@mail.linkov.net \
--to=juri@linkov.net \
--cc=eliz@gnu.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.