emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Proposed extension of show-paren-mode: Highlight parens when point i


From: Alan Mackenzie
Subject: Re: Proposed extension of show-paren-mode: Highlight parens when point is in L or R margin.
Date: Sun, 12 Oct 2014 10:04:16 +0000
User-agent: Mutt/1.5.21 (2010-09-15)

Hi, Stefan.

On Sun, Oct 12, 2014 at 12:12:12AM -0400, Stefan Monnier wrote:
> > So: If point is in the LH margin of the code, highlight the first paren
> > on the line and its match, or failing that, the last paren on the line
> > with its match.

> Related ideas:
> - show matching paren when point is right after the open paren or right
>   before the close paren.  (see
>   
> http://stackoverflow.com/questions/25648067/emacs-matching-parenthesis-when-cursor-is-on-closing-parenthesis
>   for a 5-liner which does that).

> - show matching paren, when there's only whitespace between point and
>   the open/close paren.

Maybe for later!

> This second idea is a superset of the one you suggest.  I personally
> don't use show-paren-mode because I find it distracting, so maybe
> a superset would be too distracting.

> > Then again, why not do the same if point is in a line comment?

> Sorry, I don't know what "in a line comment" means.

In a comment which extends to EOL, e.g. "//..." in C++, or ";..." in
Lisp.

> As for your patch, I'd rather see the new code moved to a new function.

Done.

> See more detailed comments below.


> > + (defcustom show-paren-when-point-in-margin nil

> Please don't call it "margin".

OK.  It's now called "periphery".

[ .... ]

> It's not at all clear to me why there has to be so many different cases
> (IOW we'd need a comment that explains why we need such complexity).

I've condensed these cases into a new function (see amended patch below).

[ .... ]

> This is a code duplication.  Please move it to a separate helper function.

No it's not.  It appears just once, after my patch is applied.

Here's the amended version, incorporating suggestions from you, Eli, and
David.




=== modified file 'lisp/paren.el'
*** lisp/paren.el       2014-02-10 01:34:22 +0000
--- lisp/paren.el       2014-10-12 09:46:33 +0000
***************
*** 72,77 ****
--- 72,85 ----
    :group 'paren-showing
    :version "20.3")
  
+ (defcustom show-paren-when-point-in-periphery nil
+   "If non-nil, show parens when point is in the line's periphery.
+ The periphery is either the whitespace at the beginning of a
+ line, or a comment \(or whitespace) at the end of a line."
+   :type 'boolean
+   :group 'paren-showing
+   :version "25.1")
+ 
  (define-obsolete-face-alias 'show-paren-match-face 'show-paren-match "22.1")
  
  (define-obsolete-face-alias 'show-paren-mismatch-face
***************
*** 112,117 ****
--- 120,138 ----
      (delete-overlay show-paren--overlay)
      (delete-overlay show-paren--overlay-1)))
  
+ (defun show-paren--categorize-paren (pos)
+   "Determine whether the character after POS has paren syntax,
+ and if so, return a cons (DIR . OUTSIDE).  For an open paren, DIR
+ is 1 and OUTSIDE is the position before the paren.  For a close
+ paren, DIR is -1 and OUTSIDE is the position after the paren.  If
+ the character isn't a paren, return nil."
+   (cond
+    ((eq (syntax-class (syntax-after pos)) 4)
+     (cons 1 pos))
+    ((eq (syntax-class (syntax-after pos)) 5)
+     (cons -1 (1+ pos)))
+    (t nil)))
+ 
  (defvar show-paren-data-function #'show-paren--default
    "Function to find the opener/closer at point and its match.
  The function is called with no argument and should return either nil
***************
*** 120,141 ****
  Where HERE-BEG..HERE-END is expected to be around point.")
  
  (defun show-paren--default ()
!   (let* ((oldpos (point))
!          (dir (cond ((eq (syntax-class (syntax-after (1- (point)))) 5) -1)
!                     ((eq (syntax-class (syntax-after (point)))      4) 1)))
!          (unescaped
!           (when dir
!             ;; Verify an even number of quoting characters precede the paren.
!             ;; Follow the same logic as in `blink-matching-open'.
!             (= (if (= dir -1) 1 0)
!                (logand 1 (- (point)
!                             (save-excursion
!                               (if (= dir -1) (forward-char -1))
!                               (skip-syntax-backward "/\\")
!                               (point)))))))
!          (here-beg (if (eq dir 1) (point) (1- (point))))
!          (here-end (if (eq dir 1) (1+ (point)) (point)))
!          pos mismatch)
      ;;
      ;; Find the other end of the sexp.
      (when unescaped
--- 141,190 ----
  Where HERE-BEG..HERE-END is expected to be around point.")
  
  (defun show-paren--default ()
!   (let* ((ind-pos (save-excursion (back-to-indentation) (point)))
!        (bol-pos (save-excursion (beginning-of-line) (point)))
!        (eol-pos (save-excursion (end-of-line)
!                                 (let ((s (syntax-ppss)))
!                                   (if (nth 4 s)
!                                       (goto-char (max (nth 8 s)
!                                                       (point-min))))
!                                   (skip-chars-backward " \t"))
!                                 (point)))
!        (oldpos (point))
!        dir paren-details unescaped pos mismatch here-beg here-end)
!     (cond
!      ;; Point is at a paren.
!      ((eq (syntax-class (syntax-after (1- (point)))) 5)
!       (setq dir -1))
!      ((eq (syntax-class (syntax-after (point))) 4)
!       (setq dir 1))
!      ;; Point is in the WS before the code.
!      ((and show-paren-when-point-in-periphery
!          (< (point) ind-pos))
!       (setq paren-details
!           (or (show-paren--categorize-paren ind-pos)
!               (show-paren--categorize-paren (1- eol-pos)))))
!      ;; Point is in a comment or whitespace after the code.
!      ((and show-paren-when-point-in-periphery
!          (>= (point) eol-pos))
!       (setq paren-details
!           (or (show-paren--categorize-paren (1- eol-pos))
!               (show-paren--categorize-paren ind-pos)))))
!     (when paren-details
!       (setq dir (car paren-details)
!           oldpos (cdr paren-details)))
! 
!     (when dir
!       (setq unescaped
!           (= (if (= dir -1) 1 0)
!              (logand 1 (- oldpos
!                           (save-excursion
!                             (goto-char oldpos)
!                             (if (= dir -1) (backward-char))
!                             (skip-syntax-backward "/\\")
!                             (point)))))))
!     (setq here-beg (if (eq dir 1) oldpos (1- oldpos))
!           here-end (if (eq dir 1) (1+ oldpos) oldpos))
      ;;
      ;; Find the other end of the sexp.
      (when unescaped
***************
*** 149,155 ****
            ;; Scan across one sexp within that range.
            ;; Errors or nil mean there is a mismatch.
            (condition-case ()
!               (setq pos (scan-sexps (point) dir))
              (error (setq pos t mismatch t)))
            ;; Move back the other way and verify we get back to the
            ;; starting point.  If not, these two parens don't really match.
--- 198,204 ----
            ;; Scan across one sexp within that range.
            ;; Errors or nil mean there is a mismatch.
            (condition-case ()
!               (setq pos (scan-sexps oldpos dir))
              (error (setq pos t mismatch t)))
            ;; Move back the other way and verify we get back to the
            ;; starting point.  If not, these two parens don't really match.
***************
*** 157,163 ****
            ;; or one is inside a comment.
            (when (integerp pos)
              (unless (condition-case ()
!                         (eq (point) (scan-sexps pos (- dir)))
                        (error nil))
                (setq pos nil)))
            ;; If found a "matching" paren, see if it is the right
--- 206,212 ----
            ;; or one is inside a comment.
            (when (integerp pos)
              (unless (condition-case ()
!                         (eq oldpos (scan-sexps pos (- dir)))
                        (error nil))
                (setq pos nil)))
            ;; If found a "matching" paren, see if it is the right
***************
*** 215,221 ****
          ;; Otherwise, turn off any such highlighting.
          (if (or (not here-beg)
                  (and (not show-paren-highlight-openparen)
!                      (> here-end (point))
                       (integerp there-beg)))
              (delete-overlay show-paren--overlay-1)
            (move-overlay show-paren--overlay-1
--- 264,270 ----
          ;; Otherwise, turn off any such highlighting.
          (if (or (not here-beg)
                  (and (not show-paren-highlight-openparen)
!                    (= here-beg (point))
                       (integerp there-beg)))
              (delete-overlay show-paren--overlay-1)
            (move-overlay show-paren--overlay-1



>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]