From d48e07aaed0baf81baf377a9f2745678c9a5d41b Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Wed, 21 Feb 2018 23:30:18 +0200 Subject: [PATCH] * lisp/simple.el (next-error-find-buffer-function): New defcustom. (next-error-last-buffer): Make variable buffer-local. (next-error-buffer-on-selected-frame): New function. (next-error-find-buffer): Use next-error-find-buffer-function at the first step instead of ad-hoc logic of using one window on the selected frame. (next-error, next-error-internal): Set default value of next-error-last-buffer. Display message with the name of last next-error buffer. (next-error-select-buffer): New command. (Bug#20489) --- etc/NEWS | 7 ++++++ lisp/simple.el | 65 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 8db638e5ed5..848b66d20d7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -203,6 +203,13 @@ styles as configured by the variable 'completion-styles'. These macros are analogue to 'let' and 'let*', but create bindings that are evaluated lazily. +** next-error + +*** New customizable variable next-error-find-buffer-function +defines the logic of finding a next-error capable buffer. +It has an option to use a single such buffer on selected frame, or +by default use the last buffer that navigated to the current buffer. + ** Eshell --- diff --git a/lisp/simple.el b/lisp/simple.el index 0c54c8f2926..2101cfe8333 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -121,6 +121,7 @@ If non-nil, the value is passed directly to `recenter'." A buffer becomes most recent when its compilation, grep, or similar mode is started, or when it is used with \\[next-error] or \\[compile-goto-error].") +(make-variable-buffer-local 'next-error-last-buffer) (defvar next-error-function nil "Function to use to find the next error in the current buffer. @@ -169,6 +170,31 @@ rejected, and the function returns nil." (and extra-test-inclusive (funcall extra-test-inclusive)))))) +(defcustom next-error-find-buffer-function nil + "Function called to find a `next-error' capable buffer." + :type '(choice (const :tag "Single next-error capable buffer on selected frame" + next-error-buffer-on-selected-frame) + (const :tag "No default" nil) + (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) + "Return a single visible next-error buffer on the selected frame." + (let ((window-buffers + (delete-dups + (delq nil (mapcar (lambda (w) + (if (next-error-buffer-p + (window-buffer w) + avoid-current + extra-test-inclusive extra-test-exclusive) + (window-buffer w))) + (window-list)))))) + (if (eq (length window-buffers) 1) + (car window-buffers)))) + (defun next-error-find-buffer (&optional avoid-current extra-test-inclusive extra-test-exclusive) @@ -185,18 +211,11 @@ The function EXTRA-TEST-EXCLUSIVE, if non-nil, is called in each buffer that would normally be considered usable. If it returns nil, that buffer is rejected." (or - ;; 1. If one window on the selected frame displays such buffer, return it. - (let ((window-buffers - (delete-dups - (delq nil (mapcar (lambda (w) - (if (next-error-buffer-p - (window-buffer w) - avoid-current - extra-test-inclusive extra-test-exclusive) - (window-buffer w))) - (window-list)))))) - (if (eq (length window-buffers) 1) - (car window-buffers))) + ;; 1. If a customizable function returns a buffer, use it. + (when next-error-find-buffer-function + (funcall next-error-find-buffer-function avoid-current + extra-test-inclusive + extra-test-exclusive)) ;; 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 @@ -261,11 +280,20 @@ To control which errors are matched, customize the variable (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" + (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))))) (defun next-error-internal () @@ -273,13 +301,26 @@ To control which errors are matched, customize the variable (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)))) +(defun next-error-select-buffer (buffer) + "Select a `next-error' capable buffer and set it as the last used." + (interactive + (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)) + (defalias 'goto-next-locus 'next-error) (defalias 'next-match 'next-error) -- 2.39.2