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: Stefan Monnier
Subject: Re: Proposed extension of show-paren-mode: Highlight parens when point is in L or R margin.
Date: Thu, 16 Oct 2014 13:40:22 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4.50 (gnu/linux)

> I've been trying this out the past few days, and it seems having a
> closing paren at EOL shown when point is in LH periphery is quite useful.

I think for

  (defun foo
  <1>  blabla
  <2>  blilbi)
  <3>

I'd prefer we highlight the matching parens when we're at <3> than when
we're at <2>.  Would that be "about as useful", you think?

Otherwise it seems way too weird/ad-hoc to hardcode it, so make
it dependent on a config var.

Another option is to highlight the "nearest surrounding parens", in
which case we'd highlight the parens above both in cases <1> and <2>
(plus various others), but this is probably too intrusive.

> What is still there is an open paren direcly left of point flashing just
> after you've typed it (e.g. with M-:).  This irritates somewhat, and
> maybe this should come out, too.

Let's keep it for now.

>> And of course, it gets you an ambiguity for
>> (defun foo ()
>> (bar))
>> ^
>> |
>> point
> The nearest eligible paren to point currently takes priority.

Define "nearest".  Can the user mentally compute this "nearest" as well
(e.g. does it depend on "invisible" trailing whitespace, or does it
depend on "invisible" differences between spaces and tabs)?

I think giving precedence always in the same direction (when there are
separating spaces on both sides) is a simpler choice for the user.

> As I said above, currently I've got that for point in RH periphery, but
> not LH periphery.

OK (tho please make it conditional on some config variable: doesn't have
to be a defcustom for now, and you can use whichever default you like).

> I've refactored the code somewhat, too.  I've now got
> show-paren--locate-near-paren, as promised, but I've put the "not
> escaped" test into this defun, too.  That way, if there're two candidate
> parens, as in
>     ?\)<point>)
> , the code doesn't just give up when the first candidate is found to be
> escaped.  I've also renamed variables from "oldpos" to "outside", since
> the original name had become somewhat obscure.  show-paren--default has
> become a little shorter.

Sounds good, thanks.  See comments below.

> A question: show-paren--default returns a list containe here-beg,
> here-end, there-beg, and there-end, four positions.  Couldn't we just
> return two of these t?here-beg (renamed just to t?here), saving a bit of
> messing around, or are there circumstances where here-end might not be
> (1+ here-beg)?

show-paren--default will never return something else, but other
functions can, such as SMIE's when matching paired keywords like "begin
... end".

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

Maybe a shorter name would be `show-paren-when-nearby'.
But let's not wait for an agreement here.

> +  "If non-nil, show parens when point is in the line's periphery.
> +The periphery is at the beginning or end of a line or in any
> +whitespace there."
> +  :type 'boolean
> +  :group 'paren-showing
> +  :version "25.1")

":group 'paren-showing" is redundant.

> -(defvar show-paren-highlight-openparen t
> +(defcustom show-paren-highlight-openparen t
>    "Non-nil turns on openparen highlighting when matching forward.")

Add a ":type 'boolean".

> +(defun show-paren--unescaped-p (p-cons)
> +  "Is the paren in P-CONS unescaped?  If so return P-CONS, else nil.
> +P-CONS is either nil or a cons (DIR . OUTSIDE) where DIR is 1 for
> +an open paren, -1 for a close paren, and OUTSIDE is the buffer
> +position of the outside of the paren."
> +  (when p-cons
> +    (save-excursion
> +      (goto-char (cdr p-cons))
> +      (if (= (car p-cons) -1) (backward-char))
> +      (when (= (logand (skip-syntax-backward "/\\") 1) 0)
> +     p-cons))))

Functions that end in "-p" should only return a boolean (i.e. the return
value doesn't have to be "t or nil" but the non-nil value should have no
other meaning than being non-nil and the callers shouldn't rely on it
being anything in particular other than "non-nil").

I know we sadly don't always follow this principle (e.g. `framep'), but
let's try not to make things worse.

> +     ((and (eq (car before) -1) (show-paren--unescaped-p before)))
> +     ((and (eq (car after) 1) (show-paren--unescaped-p after)))

So, here I recommend you explicitly return `before' and `after' since
the code otherwise looks weird since it seems to return a boolean when
a pair is expected.

> +     ;; Point is immediately inside a paren.
> +     ((show-paren--unescaped-p before))
> +     ((show-paren--unescaped-p after))

This should be controlled by a config var since it's new behavior.
AFAIK we can (re)use show-paren-when-point-in-periphery just fine.

BTW, maybe the "unescaped" check could be folded into
show-paren--categorize-paren.

> -Where HERE-BEG..HERE-END is expected to be around point.")
> +Where HERE-BEG..HERE-END is expected to be around the paren.")

I think "near point" is closer to the original intention than "around
the paren", especially since it might not be a parenthesis.  Also since
we shouldn't expect it to be around point, the additional patch below is
probably needed.

Other than that, feel free to install it,


        Stefan


=== modified file 'lisp/paren.el'
--- lisp/paren.el       2014-02-10 01:34:22 +0000
+++ lisp/paren.el       2014-10-16 17:36:28 +0000
@@ -216,6 +216,7 @@
         (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




reply via email to

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