diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi index 0462f1925b7..56cc321866d 100644 --- a/doc/emacs/programs.texi +++ b/doc/emacs/programs.texi @@ -1056,6 +1056,13 @@ 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. + +@item +@vindex show-paren-not-in-comments-or-strings +If the value of @code{show-paren-not-in-comments-or-strings} is +@code{all}, delimiters inside comments and strings will not be +highlighted. Otherwise if the value is set to @code{on-mismatch}, the +mismatched delimiters inside comments will not be highlighted. @end itemize @cindex Electric Pair mode diff --git a/etc/NEWS b/etc/NEWS index b054827a678..1c65e2b1ad3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -483,6 +483,13 @@ setting is an alternative to 'help-at-pt-display-when-idle'. Customize this to nil to disable starting new asynchronous native compilations while AC power is not connected. +** New user option 'show-paren-not-in-comments-or-strings' +This option tells show-paren not to highlight the parens that are inside +a comment or string. If set to 'all', do not highlight the parens that +are inside comments or strings. If set to 'on-mismatch', the parens +mismatched inside comments will not be highlighted. If set to nil (the +default), highlight the parens wherever they are. + * Editing Changes in Emacs 31.1 diff --git a/lisp/paren.el b/lisp/paren.el index 9d7f131e043..986576a8e1d 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -110,6 +110,19 @@ On non-graphical frames, the context is shown in the echo area." (const :tag "In child-frame" child-frame)) :version "29.1") +(defcustom show-paren-not-in-comments-or-strings nil + "Do not highlight the paren that are inside a comment or string. +If set to `all', do not highlight the paren that are inside comments +or strings. +If set to `on-mismatch', the paren mismatched inside comments will not be +highlighted. +If set to nil (by default), highlight the paren wherever it is." + :type '(choice + (const :tag "Never highlight" all) + (const :tag "Don't highlight when mismatched" on-mismatch) + (const :tag "Always highlight" nil)) + :version "31.1") + (defvar show-paren--idle-timer nil) (defvar show-paren--overlay (let ((ol (make-overlay (point) (point) nil t))) (delete-overlay ol) ol) @@ -450,88 +463,97 @@ It is the default value of `show-paren-data-function'." (setq show-paren--last-pos (point))) ;; Found something to highlight. - (let* ((here-beg (nth 0 data)) - (here-end (nth 1 data)) - (there-beg (nth 2 data)) - (there-end (nth 3 data)) - (mismatch (nth 4 data)) - (highlight-expression - (or (eq show-paren-style 'expression) - (and there-beg - (eq show-paren-style 'mixed) - (let ((closest (if (< there-beg here-beg) - (1- there-end) (1+ there-beg)))) - (not (pos-visible-in-window-p closest)))))) - (face - (cond - (mismatch - (if show-paren-ring-bell-on-mismatch - (beep)) - 'show-paren-mismatch) - (highlight-expression 'show-paren-match-expression) - (t 'show-paren-match)))) - ;; - ;; If matching backwards, highlight the closeparen - ;; before point as well as its matching open. - ;; If matching forward, and the openparen is unbalanced, - ;; highlight the paren at point to indicate misbalance. - ;; Otherwise, turn off any such highlighting. - (if (or (not here-beg) - (and (not show-paren-highlight-openparen) - (> here-end (point)) - (<= here-beg (point)) - (integerp there-beg))) - (delete-overlay show-paren--overlay-1) - (move-overlay show-paren--overlay-1 - here-beg here-end (current-buffer)) - ;; Always set the overlay face, since it varies. - (overlay-put show-paren--overlay-1 'priority show-paren-priority) - (overlay-put show-paren--overlay-1 'face face)) - ;; - ;; Turn on highlighting for the matching paren, if found. - ;; If it's an unmatched paren, turn off any such highlighting. - (if (not there-beg) - (delete-overlay show-paren--overlay) - (if highlight-expression - (move-overlay show-paren--overlay - (if (< there-beg here-beg) here-end here-beg) - (if (< there-beg here-beg) there-beg there-end) - (current-buffer)) - (move-overlay show-paren--overlay - there-beg there-end (current-buffer))) - ;; If `show-paren-context-when-offscreen' is non-nil and - ;; point is at a closing paren, show the context around the - ;; opening paren. - (let ((openparen (min here-beg there-beg))) - (when (and show-paren-context-when-offscreen - (not (eql show-paren--last-pos (point))) - (< there-beg here-beg) - ;; Either OPENPAREN position is fully visible... - (not (or (pos-visible-in-window-p openparen) - (let ((dfh4 (* 0.25 (default-font-height))) - (part - (pos-visible-in-window-p openparen - nil t))) - ;; ...or partially visible, and the - ;; invisible part is less than 1/4th - ;; of the default font height - (and (>= (length part) 4) - (< (nth 2 part) dfh4) - (< (nth 3 part) dfh4)))))) - (let ((context (blink-paren-open-paren-line-string - openparen)) - (message-log-max nil)) + (catch 'sp-exit + (let* ((here-beg (nth 0 data)) + (here-end (nth 1 data)) + (there-beg (nth 2 data)) + (there-end (nth 3 data)) + (mismatch (nth 4 data)) + (highlight-expression + (or (eq show-paren-style 'expression) + (and there-beg + (eq show-paren-style 'mixed) + (let ((closest (if (< there-beg here-beg) + (1- there-end) (1+ there-beg)))) + (not (pos-visible-in-window-p closest)))))) + (face (cond - ((eq show-paren-context-when-offscreen 'child-frame) - (show-paren--show-context-in-child-frame context)) - ((eq show-paren-context-when-offscreen 'overlay) - (show-paren--show-context-in-overlay context)) - (show-paren-context-when-offscreen - (minibuffer-message "Matches %s" context)))))) - (setq show-paren--last-pos (point)) - ;; Always set the overlay face, since it varies. - (overlay-put show-paren--overlay 'priority show-paren-priority) - (overlay-put show-paren--overlay 'face face)))))) + (mismatch + (if (and (eq show-paren-not-in-comments-or-strings 'on-mismatch) + (save-excursion + (syntax-ppss-context (syntax-ppss here-beg)))) + (throw 'sp-exit nil)) + (if show-paren-ring-bell-on-mismatch + (beep)) + 'show-paren-mismatch) + (highlight-expression 'show-paren-match-expression) + (t 'show-paren-match)))) + (if (and (eq show-paren-not-in-comments-or-strings 'all) + (save-excursion + (syntax-ppss-context (syntax-ppss here-beg)))) + (throw 'sp-exit nil)) + ;; + ;; If matching backwards, highlight the closeparen + ;; before point as well as its matching open. + ;; If matching forward, and the openparen is unbalanced, + ;; highlight the paren at point to indicate misbalance. + ;; Otherwise, turn off any such highlighting. + (if (or (not here-beg) + (and (not show-paren-highlight-openparen) + (> here-end (point)) + (<= here-beg (point)) + (integerp there-beg))) + (delete-overlay show-paren--overlay-1) + (move-overlay show-paren--overlay-1 + here-beg here-end (current-buffer)) + ;; Always set the overlay face, since it varies. + (overlay-put show-paren--overlay-1 'priority show-paren-priority) + (overlay-put show-paren--overlay-1 'face face)) + ;; + ;; Turn on highlighting for the matching paren, if found. + ;; If it's an unmatched paren, turn off any such highlighting. + (if (not there-beg) + (delete-overlay show-paren--overlay) + (if highlight-expression + (move-overlay show-paren--overlay + (if (< there-beg here-beg) here-end here-beg) + (if (< there-beg here-beg) there-beg there-end) + (current-buffer)) + (move-overlay show-paren--overlay + there-beg there-end (current-buffer))) + ;; If `show-paren-context-when-offscreen' is non-nil and + ;; point is at a closing paren, show the context around the + ;; opening paren. + (let ((openparen (min here-beg there-beg))) + (when (and show-paren-context-when-offscreen + (not (eql show-paren--last-pos (point))) + (< there-beg here-beg) + ;; Either OPENPAREN position is fully visible... + (not (or (pos-visible-in-window-p openparen) + (let ((dfh4 (* 0.25 (default-font-height))) + (part + (pos-visible-in-window-p openparen + nil t))) + ;; ...or partially visible, and the + ;; invisible part is less than 1/4th + ;; of the default font height + (and (>= (length part) 4) + (< (nth 2 part) dfh4) + (< (nth 3 part) dfh4)))))) + (let ((context (blink-paren-open-paren-line-string + openparen)) + (message-log-max nil)) + (cond + ((eq show-paren-context-when-offscreen 'child-frame) + (show-paren--show-context-in-child-frame context)) + ((eq show-paren-context-when-offscreen 'overlay) + (show-paren--show-context-in-overlay context)) + (show-paren-context-when-offscreen + (minibuffer-message "Matches %s" context)))))) + (setq show-paren--last-pos (point)) + ;; Always set the overlay face, since it varies. + (overlay-put show-paren--overlay 'priority show-paren-priority) + (overlay-put show-paren--overlay 'face face))))))) (provide 'paren)