-(defsubst next-error-buffer-p (buffer &optional extra-test)
- "Test if BUFFER is a next-error capable buffer."
- (with-current-buffer buffer
- (or (and extra-test (funcall extra-test))
- next-error-function)))
-
-;; Return a next-error capable buffer according to the following rules:
-;; 1. If the current buffer is a next-error capable buffer, return it.
-;; 2. If one window on the selected frame displays such buffer, return it.
-;; 3. If next-error-last-buffer is set to a live buffer, use that.
-;; 4. Otherwise, look for a next-error capable buffer in a buffer list.
-;; 5. Signal an error if there are none.
-(defun next-error-find-buffer (&optional other-buffer extra-test)
- (if (and (not other-buffer)
- (next-error-buffer-p (current-buffer) extra-test))
- ;; The current buffer is a next-error capable buffer.
- (current-buffer)
- (or
- (let ((window-buffers
- (delete-dups
- (delq nil
- (mapcar (lambda (w)
- (and (next-error-buffer-p (window-buffer w) extra-test)
- (window-buffer w)))
- (window-list))))))
- (if other-buffer
- (setq window-buffers (delq (current-buffer) window-buffers)))
- (if (eq (length window-buffers) 1)
- (car window-buffers)))
- (if (and next-error-last-buffer (buffer-name next-error-last-buffer)
- (next-error-buffer-p next-error-last-buffer extra-test)
- (or (not other-buffer) (not (eq next-error-last-buffer
- (current-buffer)))))
- next-error-last-buffer
- (let ((buffers (buffer-list)))
- (while (and buffers (or (not (next-error-buffer-p (car buffers) extra-test))
- (and other-buffer
- (eq (car buffers) (current-buffer)))))
- (setq buffers (cdr buffers)))
- (if buffers
- (car buffers)
- (or (and other-buffer
- (next-error-buffer-p (current-buffer) extra-test)
- ;; The current buffer is a next-error capable buffer.
- (progn
- (if other-buffer
- (message "This is the only next-error capable buffer."))
- (current-buffer)))
- (error "No next-error capable buffer found!"))))))))
-
-(defun next-error (arg &optional reset)
+(defsubst next-error-buffer-p (buffer
+ &optional avoid-current
+ extra-test-inclusive
+ extra-test-exclusive)
+ "Test if BUFFER is a next-error capable buffer.
+
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffer
+that normally would not qualify. If it returns t, the buffer
+in question is treated as usable.
+
+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."
+ (and (buffer-name buffer) ;First make sure it's live.
+ (not (and avoid-current (eq buffer (current-buffer))))
+ (with-current-buffer buffer
+ (if next-error-function ; This is the normal test.
+ ;; Optionally reject some buffers.
+ (if extra-test-exclusive
+ (funcall extra-test-exclusive)
+ t)
+ ;; Optionally accept some other buffers.
+ (and extra-test-inclusive
+ (funcall extra-test-inclusive))))))
+
+(defun next-error-find-buffer (&optional avoid-current
+ extra-test-inclusive
+ extra-test-exclusive)
+ "Return a next-error capable buffer.
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffers
+that normally would not qualify. If it returns t, the buffer
+in question is treated as usable.
+
+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)))
+ ;; 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
+ extra-test-inclusive extra-test-exclusive))
+ next-error-last-buffer)
+ ;; 3. If the current buffer is acceptable, choose it.
+ (if (next-error-buffer-p (current-buffer) avoid-current
+ extra-test-inclusive extra-test-exclusive)
+ (current-buffer))
+ ;; 4. Look for any acceptable buffer.
+ (let ((buffers (buffer-list)))
+ (while (and buffers
+ (not (next-error-buffer-p
+ (car buffers) avoid-current
+ extra-test-inclusive extra-test-exclusive)))
+ (setq buffers (cdr buffers)))
+ (car buffers))
+ ;; 5. Use the current buffer as a last resort if it qualifies,
+ ;; even despite AVOID-CURRENT.
+ (and avoid-current
+ (next-error-buffer-p (current-buffer) nil
+ extra-test-inclusive extra-test-exclusive)
+ (progn
+ (message "This is the only next-error capable buffer")
+ (current-buffer)))
+ ;; 6. Give up.
+ (error "No next-error capable buffer found")))
+
+(defun next-error (&optional arg reset)