line and there is a paren at the first or last non-whitespace position
on the line, or when point is at the end of a line and there is a
paren at the last non-whitespace position on the line.
+
+@item
+@vindex show-paren-context-when-offscreen
+@code{show-paren-context-when-offscreen}, when non-@code{nil}, shows
+some context in the echo area when point is in a closing delimiter and
+the opening delimiter is offscreen. The context is usually the line
+that contains the opening delimiter, except if the opening delimiter
+is on its own line, in which case the context includes the previous
+nonblank line.
@end itemize
@cindex Electric Pair mode
Customize this option to limit the amount of entries in the menu
"Edit->Paste from Kill Menu". The default is 60.
+** show-paren-mode
+
++++
+*** New user option 'show-paren-context-when-offscreen'.
+When non-nil, if the point is in a closing delimiter and the opening
+delimiter is offscreen, shows some context around the opening
+delimiter in the echo area.
+
\f
* Changes in Specialized Modes and Packages in Emacs 29.1
;; it undesirable to print eldoc messages right this instant.
(defun eldoc-display-message-no-interference-p ()
"Return nil if displaying a message would cause interference."
- (not (or executing-kbd-macro (bound-and-true-p edebug-active))))
+ (not (or executing-kbd-macro
+ (bound-and-true-p edebug-active)
+ ;; The following configuration shows "Matches..." in the
+ ;; echo area when point is after a closing bracket, which
+ ;; conflicts with eldoc.
+ (and show-paren-context-when-offscreen
+ (not (pos-visible-in-window-p
+ (overlay-end show-paren--overlay)))))))
\f
(defvar eldoc-documentation-functions nil
its position."
:type 'boolean)
+(defcustom show-paren-context-when-offscreen nil
+ "If non-nil, show context in the echo area when the openparen is offscreen.
+The context is usually the line that contains the openparen,
+except if the openparen is on its own line, in which case the
+context includes the previous nonblank line."
+ :type 'boolean
+ :version "29.1")
+
(defvar show-paren--idle-timer nil)
(defvar show-paren--overlay
(let ((ol (make-overlay (point) (point) nil t))) (delete-overlay ol) ol)
(current-buffer))
(move-overlay show-paren--overlay
there-beg there-end (current-buffer)))
+ ;; If `show-paren-open-line-when-offscreen' is t and point
+ ;; is at a close paren, show the line that contains the
+ ;; openparen in the echo area.
+ (let ((openparen (min here-beg there-beg)))
+ (if (and show-paren-context-when-offscreen
+ (< there-beg here-beg)
+ (not (pos-visible-in-window-p openparen)))
+ (let ((open-paren-line-string
+ (blink-paren-open-paren-line-string openparen))
+ (message-log-max nil))
+ (minibuffer-message
+ "Matches %s"
+ (substring-no-properties open-paren-line-string)))))
;; Always set the overlay face, since it varies.
(overlay-put show-paren--overlay 'priority show-paren-priority)
(overlay-put show-paren--overlay 'face face))))))
(current-buffer))
(sit-for blink-matching-delay))
(delete-overlay blink-matching--overlay)))))
- (t
- (let ((open-paren-line-string
- (save-excursion
- (goto-char blinkpos)
- ;; Show what precedes the open in its line, if anything.
- (cond
- ((save-excursion (skip-chars-backward " \t") (not (bolp)))
- (buffer-substring (line-beginning-position)
- (1+ blinkpos)))
- ;; Show what follows the open in its line, if anything.
- ((save-excursion
- (forward-char 1)
- (skip-chars-forward " \t")
- (not (eolp)))
- (buffer-substring blinkpos
- (line-end-position)))
- ;; Otherwise show the previous nonblank line,
- ;; if there is one.
- ((save-excursion (skip-chars-backward "\n \t") (not (bobp)))
- (concat
- (buffer-substring (progn
- (skip-chars-backward "\n \t")
- (line-beginning-position))
- (progn (end-of-line)
- (skip-chars-backward " \t")
- (point)))
- ;; Replace the newline and other whitespace with `...'.
- "..."
- (buffer-substring blinkpos (1+ blinkpos))))
- ;; There is nothing to show except the char itself.
- (t (buffer-substring blinkpos (1+ blinkpos)))))))
- (minibuffer-message
- "Matches %s"
- (substring-no-properties open-paren-line-string))))))))
+ ((not show-paren-context-when-offscreen)
+ (minibuffer-message
+ "Matches %s"
+ (substring-no-properties
+ (blink-paren-open-paren-line-string blinkpos))))))))
+
+(defun blink-paren-open-paren-line-string (pos)
+ "Return the line string that contains the openparen at POS."
+ (save-excursion
+ (goto-char pos)
+ ;; Show what precedes the open in its line, if anything.
+ (cond
+ ((save-excursion (skip-chars-backward " \t") (not (bolp)))
+ (buffer-substring (line-beginning-position)
+ (1+ pos)))
+ ;; Show what follows the open in its line, if anything.
+ ((save-excursion
+ (forward-char 1)
+ (skip-chars-forward " \t")
+ (not (eolp)))
+ (buffer-substring pos
+ (line-end-position)))
+ ;; Otherwise show the previous nonblank line,
+ ;; if there is one.
+ ((save-excursion (skip-chars-backward "\n \t") (not (bobp)))
+ (concat
+ (buffer-substring (progn
+ (skip-chars-backward "\n \t")
+ (line-beginning-position))
+ (progn (end-of-line)
+ (skip-chars-backward " \t")
+ (point)))
+ ;; Replace the newline and other whitespace with `...'.
+ "..."
+ (buffer-substring pos (1+ pos))))
+ ;; There is nothing to show except the char itself.
+ (t (buffer-substring pos (1+ pos))))))
(defvar blink-paren-function 'blink-matching-open
"Function called, if non-nil, whenever a close parenthesis is inserted.
(- (point-max) 1) (point-max)
nil)))))
+(ert-deftest paren-tests-open-paren-line ()
+ (cl-flet ((open-paren-line ()
+ (let* ((data (show-paren--default))
+ (here-beg (nth 0 data))
+ (there-beg (nth 2 data)))
+ (blink-paren-open-paren-line-string
+ (min here-beg there-beg)))))
+ ;; Lisp-like
+ (with-temp-buffer
+ (insert "(defun foo ()
+ (dummy))")
+ (goto-char (point-max))
+ (should (string= "(defun foo ()" (open-paren-line))))
+
+ ;; C-like
+ (with-temp-buffer
+ (insert "int foo() {
+ int blah;
+ }")
+ (goto-char (point-max))
+ (should (string= "int foo() {" (open-paren-line))))
+
+ ;; C-like with hanging {
+ (with-temp-buffer
+ (insert "int foo()
+ {
+ int blah;
+ }")
+ (goto-char (point-max))
+ (should (string= "int foo()...{" (open-paren-line))))))
+
(provide 'paren-tests)
;;; paren-tests.el ends here