This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 95126 - Matching bracket should be locateable with cursor on either side of bracket
Summary: Matching bracket should be locateable with cursor on either side of bracket
Status: NEW
Alias: None
Product: editor
Classification: Unclassified
Component: Code folding (show other bugs)
Version: 5.x
Hardware: All All
: P2 blocker with 4 votes (vote)
Assignee: Svata Dedic
URL:
Keywords:
: 56622 66037 (view as bug list)
Depends on: 91893
Blocks:
  Show dependency tree
 
Reported: 2007-02-09 19:04 UTC by _ wadechandler
Modified: 2013-01-31 16:19 UTC (History)
4 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments
cvs diff -u (9.16 KB, patch)
2007-05-01 04:28 UTC, err
Details | Diff
patch update for goto match fix for AFTER case (9.41 KB, patch)
2007-05-01 16:02 UTC, err
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description _ wadechandler 2007-02-09 19:04:10 UTC
Currently the editor does not find the matching bracket if the cursor is like this:
|{ or |}

but only finds the matching bracket when it is setup like this:

{| or }|

It doesn't make sense to not show it both ways unless brackets are beside
brackets.  Most code will not be like this, but instead will have good
formatting.  The times it is not can be checked for a bracket immediately
before, so in the case of:
{|{ or }|}

then is it very easy to give the information for the bracket to the left of the
cursor (as what happens now), but for most general use cases there will always
be white space between brackets like:
1. { |{ 
or 
2. }| }

so in the above cases #1 is finding the matching bracket for the bracket on the
right, and #2 is finding the matching bracket for the bracket on the left.
Comment 1 err 2007-02-09 19:52:32 UTC
If I get appropriate buy in and approval (I still need to learn the process),
I'm hoping to make an api compatible change to org.netbeans.editor.ext.ExtCaret,
and submit a patch, so the caret can be programmed to highlight either the
matching brace of the character before the caret (the current behavior) or the
character after the caret. I will use this for jVi and switch between these two
caret modes. The current behavior is for vi input mode, the new behavior is for
command mode where you see a block cursor sitting on the character after the caret.

You are asking for a third mode that highlights the match for either before or
after the caret. Again if there is approval, I could probably put this third
mode into the caret as well. Getting the default editors to use and/or provide a
user option to turn it on, is another issue entirely.
Comment 2 _ gsporar 2007-02-09 20:22:38 UTC
Several comments (the first one being the most important):

1. I do *not* claim to know the correct answer, here....  :-)

2. Wade, I agree that the current behavior for bracket matching is sometimes
inconvenient.  In general I support what you are suggesting, but...

3. The current approach is consistent with the way that highlighting of a
matching parenthesis works.  And I see some value to that.  Since you only list
brackets in your description, I am assuming you want the highlighting of
matching parentheses to stay the same.  I'm not sure if an inconsistency between
the way that the two of them are highlighted is a big deal or not.

4. FWIW, IntelliJ IDEA takes a different approach for highlighting.  The
highlight works when the cursor is positioned at either:

|{

or

}|

So in other words, the cursor has to be "on the outside" of the block.  This
also holds true for the way it does parenthesis matching.

5. FWIW, Eclipse and JEdit work the same way that NetBeans does.
Comment 3 ptoye 2007-02-09 21:36:24 UTC
Basically, anything which makes the typist's job easier is to be commended, and,
for braces, this is a good one. As you point out, there's little chance of
ambiguity.

But for other types of bracket, this isn't the case. What about 

if (|(a+b)==c)

(where the | represents the cursor)?

Or 2dArray[x]|[y] ?
Or (long)|(int1+int2) ?

At least the current mechanism is consistent across all types of matching bracket.

I have a feeling that it would end up more confusing than useful and
(reluctantly) am withholding my vote, at least until this conversation manages
to convince me otherwise.
Comment 4 _ wadechandler 2007-02-10 01:15:45 UTC
That would be great.  I'll see what I can do with the NB Dream Team and see if I
can get any comments.  I submitted this issue to the group for comment.  Thanks.
Comment 5 _ wadechandler 2007-02-10 01:18:37 UTC
I only saw errs comments.  I'll read these others and comment more...sorry.
Comment 6 _ wadechandler 2007-02-10 01:32:02 UTC
>if (|(a+b)==c)
Well, we are talking about productivity improvements.  For instance, in this example
if ((|a+b)==c)
if ((a+b|)==c)
if ((a+b)|==c)
if ((a+b)==c|)
if ((a+b)==c)|

All work as expected in general, with the case you present being something where
it has to work the way I suggested.  The case you present would have to work as
it currently does, thus if the cursor is in between two then the way it works
now is an acceptable default with most cases working out for better performance
while you work.

>2dArray[x]|[y] ?
2dArray|[x][y]
2dArray[x|][y]
2dArray[x][|y]
2dArray[x][y]|

Again, more work as expected than not, and having a valid working scenario for
the few operations with ambiguity would be a well know solution once someone
uses it.  I believe the gain in performance out weighs the first couple of
"huhs" someone will have the first time they see it work.  New introductions are
always a little stutter step, but in this case I believe to an experienced coder
it would be an easy thing to figure out.

>(long)|(int1+int2) ?
Again
(|long)(int1+int2)
|(long)(int1+int2)
(long)(|int1+int2)
(long)(int1+int2|)
(long)(int1+int2)|

All work
Comment 7 _ wadechandler 2007-02-10 01:41:20 UTC
>3. The current approach is consistent with the way that highlighting of a
>matching parenthesis works.  And I see some value to that.  Since you only list
>brackets in your description, I am assuming you want the highlighting of
>matching parentheses to stay the same.  I'm not sure if an inconsistency between
>the way that the two of them are highlighted is a big deal or not.
I sort of screwed up.  It would be nice for this to work with all matching
patterns.  Even <p><b>My name is Wade Chandler</b></p> could benefit...  See my
other comment about other java code features.

>5. FWIW, Eclipse and JEdit work the same way that NetBeans does.
Not trying to be a smarty...just, that if Eclipse asked you to jump off a bridge
would you. :-P...yes I was being a smarty.  Anyways, I think it is a gain in
productivity, and that is the main point.  It would be a little different than
some IDEs, but some others work this way.  It would also work in a lot of cases
except for the times you have |(((((stackedoperators|) but usually|) you have
separation at the end|) and in between|) (the |'s are all the cases which work,
with the others falling back to the default operation).
Comment 8 d0gf 2007-02-10 03:09:30 UTC
I agree with comments from Peter and Gregg. I'm occasionaly coding some
javascript in GEdit, and it has this "feature" that makes me "wtf" and thank
NetBeans devs that there is no such "feature" in NB every time I write something
like "if ((line = in.readLine()) != null)".
Comment 9 _ wadechandler 2007-02-10 06:17:08 UTC
I'm really not seeing how
"if ((line = in.readLine()) != null)"
and this issue would cause a problem or confusion.  For instance this particular
case if you were walking from either side would be ( {(} or {)} means
highlighted and | is the cursor ):

"if {(}(line = in.readLine()) != null)|"

if {(}(line = in.readLine()) != null|)

"if ({(}line = in.readLine())| != null)"

"if ((line = in.readLine{(})|) != null)"

"if ((line = in.readLine(|{)}) != null)"

if ((line = in.readLine|({)}) != null)

"if ((|line = in.readLine(){)} != null)"

"if (|(line = in.readLine()) != null{)}"

if |((line = in.readLine()) != null{)}

All of the quoted lines of code work exactly like they do currently with the
mentioned idea.  The three lines which work differently seem obvious what is to
occur.  So, not trying to be smart, but is there something more complicated than
this which you are doing on one line which can be examined?  Does GEdit work
differently then the above mentioned walking of the highlighter?  Try something
like the following which is a common place left side highlighting would come in
handy:

========while(something){
============if(something){
================if(something){
====================//do some work work work....
====================//do some work work work....
====================//do some work work work....
================} else{
====================//do some work work work....
====================//do some work work work....
====================if(thisIsHappening){
========================//do some work work work....
========================//do some work work work....
====================}else if(thisState){
========================//do some work work work....
========================//do some work work work....
====================}//this one was added by mistake
================}else{
====================//do some work work work....
================}
================//do some work work work....
============}
============//do some work work work....
========} else{
============//do some work work work....
============//do some work work work....
========}
========//do some work work work....
====}

Now, if you walk up from the bottom, which side of the bracket are you on?  I
walk up on the left because of the layout of the brackets and the fact I can
walk straight up the bracket side (left). I can hit HOME and jump to the front
of the line and watch the highlighting, and if I need to jump up to a match I
still have to hit CTRL-{, but that is a different issue in IZ (an issue about a
marker for the highlighted match in the annotation line).  With the current
highlighting method if the line jumps over to the right or left I then have to 
to hit HOME, and then I have to arrow one right.  If it worked both ways it
would work for any way anyone uses the editor, and I have yet to see a case
where the situation with grouped matches which would not fail over the default
easily enough.  

I suppose I'm having a hard time seeing the confusion is all I'm getting at,
that with the above use case. The other issue, for me, is when I actually need
to track down match problems which span pages and the cursor is already to the
left of a bracket. I find myself hitting CTRL-{ and then going "oh yeah, I have
to be to the left of the bracket" which is on a line by itself. I know a couple
other developers who do this, and they had the same thought...Why does it force
you to be to the right? ... literally have heard those words come out of
developers mouths.

Anyways, that is all I can say on it. I really hate having to think about where
to place a cursor just to find a matching bracket or any match really. Mainly I
do not have to use it too often, and when I do it just is annoying.  The times
when you have many (()) (() ..... ) then it will technically work like it does
now except on the outside boundries and standalone match patterns it will work
on both sides.
Comment 10 _ wadechandler 2007-02-11 01:55:24 UTC
Really the way this would work it would not be a lot more work than happens now:
currently:
1) If to the right of a match pattern
2) scan direction of match to find the match (obviously a little more going on)
3) end

if implemented:
scenario 1
1)If to the right of a match pattern
2)scan direction of match to find the match
3)end

or

1)If to the left of a match pattern and no match anti-*/pattern also to the
right of the cursor then #2 else scenario 1
2)scan direction of match to find the match
3)end

If there is much objection this could be a setting for the editor in options,
where it can use the right, left, or both sides for pattern matching.  Because
getting it to work other than modules using it really isn't a lot more work as
what is happening now...just an extra step to determine the starting point and
direction.
Comment 11 _ wadechandler 2007-02-11 01:57:54 UTC
Well, really just an extra step to tell if to the left vs. the right...starting
point and direction are already being figured.
Comment 12 jxt 2007-02-12 13:41:29 UTC
I *like* the idea. Back in October 2005, I filed an RFE as issue 66037 
entitled "Make ^[ smarter". There have been ZERO comments on it. My idea was 
that if the cursor is ANYWHERE in whitespace before or after a brace, then it 
is obvious what ^[ should do. As it is now, I'm forevermore having to 
press "Home" and then right arrow to position the cursor after a closing curly 
brace, just so I can press ^[ to find the matching opening brace. ARGHHH. 
Wouldn't it be so much easier (on the user, that is) to have ^[ find the 
opening brace without having to press the arrow keys to position the 
cursor "just right". To repeat, if the "find the matching brace" action is 
unambiguous, then just do the right thing. For example, if a code block ends 
like this:

        code
        code
 |  }
}

and the cursore is positioned as shown, then it's OBVIOUS which opening brace 
(not shown) should match the one on the line the cursor is on. So pressing 
the "find match" key ^[ should jump to that corresponding opening brace. VIM 
does it this way. Why not NetBeans? Sure, there may be some pathological 
examples in which it's not immediately clear what to do. I really don't worry 
too much about encountering such patholgies in my everyday coding. It's the 
common things that I worry about. And in any case, the rule that "if it's 
unambiguous, do the right thing" should cover even the pathologies. I'm voting 
FOR this issue. Thanks.
Comment 13 _ wadechandler 2007-02-12 14:25:00 UTC
Yes, another variation.  I like this idea as well.  This makes it even more
usable for this special case.  Multiple languages use curly brackets/braces for
code blocks, and there may very well be ones which use other things, and
definitely ones which will be using BASIC match patterns "end", so this would
make perfect sense for those type match patterns.  I like that as well, as it
just makes it simpler.  White space and on the same line then do this.
Comment 14 ptoye 2007-02-14 15:56:24 UTC
Wade,

As far as code brackets are concerned, I'm with you all the way as long as you
restrict the "cursor proximity" test to being on the same line on the grounds
that it's unusual (but by no means unknown) coding practice to have two adjacent
braces on the same line. Also, code brackets, unlike other types of bracket,
commonly span pages of text; you allude to this in your 2nd note from 10th Feb.

But I would suggest that if you extend this intelligent behaviour to round and
square brackets, ambiguities as to exactly which bracket should be taken as
"active" (by the proximity of the cursor) need to be sorted out in a way which
is compatible with current practice (i.e. in cases of ambiguity, the preceding
bracket is the "active" one. So (using your symbolism) the case has to be 
(|(a+b)*c{)} and not (|(a+b{)}*c).

However, the ctrl-[ action should be symmetric in that two applications should
get you back to the original position, or you can get lost. Now there's a problem:

|((a+b)*c) and hit ctrl-[. You finish up with ((a+b)*c)|. Hit ctrl-[ again and
you get (|(a+b)*c) which has the cursor in a different place from where you
started, which is a bit counter-intuitive, at least to my simple mind. You'd
have to remember where the last ctrl-[ came from, which I suspect will be a PITA
for the programmer.
Comment 15 _ wadechandler 2007-02-14 21:32:37 UTC
>But I would suggest that if you extend this intelligent behaviour to round and
>square brackets, ambiguities as to exactly which bracket should be taken as
>"active" (by the proximity of the cursor) need to be sorted out in a way which
>is compatible with current practice (i.e. in cases of ambiguity, the preceding
>bracket is the "active" one. So (using your symbolism) the case has to be 
>(|(a+b)*c{)} and not (|(a+b{)}*c).
This what I'm advocating.  The "default" during ambiguity will be the current
way it works now.

>However, the ctrl-[ action should be symmetric in that two applications should
>get you back to the original position, or you can get lost. Now there's a >problem:
>
>|((a+b)*c) and hit ctrl-[. You finish up with ((a+b)*c)|. Hit ctrl-[ again and
>you get (|(a+b)*c) which has the cursor in a different place from where you
>started, which is a bit counter-intuitive, at least to my simple mind. You'd
>have to remember where the last ctrl-[ came from, which I suspect will be a >PITA
>for the programmer.

Well the complete scenario for this "|((a+b)*c)" is this(have to have the
highlighting in there):
1) Cursor to the left of first paren: |((a+b)*c{)}
2) CTRL-[
3) Cursor to the right of the right paren with left paren highlighted: {(}(a+b)*c)|
4) CTRL-[
5) Cursor to the right of the left paren with correct pattern highlighted:
(|(a+b)*c{)}

Would that help with the confusion?  However, having to track it would mean
setting a "mode" of sorts and then once any other key than a match finder is hit
or the mouse clicks any where other than the current cursor location then it
would be broken out of, so it should not be that big of a deal to handle I don't
imagine.  Sounds simple enough.
Comment 16 err 2007-02-14 22:36:22 UTC
> |((a+b)*c) and hit ctrl-[. You finish up with ((a+b)*c)|. Hit ctrl-[ again
> and you get (|(a+b)*c) which has the cursor in a different place from
> where you started, which is a bit counter-intuitive

This may be a bit count-intuitive, but it doesn't seem that confusing. I think
trying to solve it would lead to even worse confusion and ugly implementation
code. I would expect ^[ to *always* take me to the same place, independent of
how I got there. 
It seems that in the example
    1)    |((a+b)*c{)}
    2) CTRL-[
    3)    {(}(a+b)*c)|
    4) CTRL-[
    5)    (|(a+b)*c{)}
you are proposing
   5a)    |((a+b)*c{)}
which is the same as 1). But if I am in state 3) and I move the caret one space
to the left and one space to the right and then hit ^[, I would not go to 5a)
but to 5). I find that confusing, it should be obvious where the caret goes
simply by looking at the screen.

How about highlighting both the destination and the source of the matching brackets?
Comment 17 Miloslav Metelka 2007-02-27 14:15:07 UTC
> How about highlighting both the destination and the source of the matching
brackets?

+1 from me. Even though for large blocks the matching brace would not be visible
(some editors display a tooltip with the matching brace and some context around it).
Comment 18 err 2007-04-27 10:00:40 UTC
I have just posted "new matchBrace features for NB6" to nbdev with a discussion
of how this might be implemented.
Comment 19 _ sandipchitale 2007-04-28 06:11:14 UTC
See this old RFE:

http://www.netbeans.org/issues/show_bug.cgi?id=56622
Comment 20 err 2007-05-01 04:25:08 UTC
Attaching patch braceMatch01.diff, based on todays sources, which takes care of
1, 2 and 3. This handles jVi requirements and covers most of the stuff discussed
in this issue. I'm unsure of coding and/or doc stuff, so let me know. Still need
to adress 4, which is more work.

1 - jVi minimal requirement is trivial, no compatibility impact, add
ExtCaret.[set|get]BraceMatchOffset(int)
2 - For consistency, trivial modification to ExtKit.MatchBraceAction so it uses
ExtCaret.getBraceMatchOffset()
3 - Issue 95126 can be addressed with small change to ExtCaret and ExtKit; more
optimal solutions exist

Not yet done:

4 - Support for highlighting both destination and source of match can be done
with no API changes. ExtSyntaxSupport and subclasses can provide the needed data
if/when they want to. 
Comment 21 err 2007-05-01 04:28:41 UTC
Created attachment 41994 [details]
cvs diff -u
Comment 22 err 2007-05-01 16:02:09 UTC
Created attachment 42012 [details]
patch update for goto match fix for AFTER case
Comment 23 err 2007-05-01 16:09:14 UTC
braceMatch02.diff handles MATCH_BRACE_AFTER case correctly for MatchBraceAction;
caret should end up 'on' the character. This is the one used only for jVi
command mode. Problem was obscured by (now unneeded) workaround code in jVi.
Comment 24 Vitezslav Stejskal 2007-05-02 06:52:10 UTC
I've merged the 02 patch to trunk. Thanks for the patch. I am not sure how long
lifespan this patch will have though. We are still hoping to have the new braces
matching SPI ready for 6.0 and I'm not sure if we will be able to bridge
EK.setMatchBraceOffset to it.


Checking in libsrc/org/netbeans/editor/ext/ExtCaret.java;
/cvs/editor/libsrc/org/netbeans/editor/ext/ExtCaret.java,v  <--  ExtCaret.java
new revision: 1.48; previous revision: 1.47
done
Checking in libsrc/org/netbeans/editor/ext/ExtKit.java;
/cvs/editor/libsrc/org/netbeans/editor/ext/ExtKit.java,v  <--  ExtKit.java
new revision: 1.72; previous revision: 1.71
done
Checking in lib/arch.xml;
/cvs/editor/lib/arch.xml,v  <--  arch.xml
new revision: 1.6; previous revision: 1.5
done
Checking in lib/manifest.mf;
/cvs/editor/lib/manifest.mf,v  <--  manifest.mf
new revision: 1.13; previous revision: 1.12
done
Checking in lib/apichanges.xml;
/cvs/editor/lib/apichanges.xml,v  <--  apichanges.xml
new revision: 1.6; previous revision: 1.5
done
Checking in lib/nbproject/project.properties;
/cvs/editor/lib/nbproject/project.properties,v  <--  project.properties
new revision: 1.18; previous revision: 1.17
done
Comment 25 Vitezslav Stejskal 2007-05-02 12:55:54 UTC
The issue #91893 is tracking the progress on the new SPI, feel free to CC,
comment and review when we have something.
Comment 26 kirillkh 2007-05-02 15:30:17 UTC
I didn't have the patience to read all the comments, so sorry if this has been
brought up. I would like to have an option to switch the editor to the old
behavior, i.e. always highlighting only on (| and )|. I am very used to this way
of highlighting and simply don't want to change the habits. I'm sure there are
many other people in similar position.
Comment 27 _ sandipchitale 2007-05-02 15:43:23 UTC
> How about highlighting both the destination and the source of the matching
brackets?

I use an emacs package in which you can exactly specify in which situations 
the matched extent is highlighted:

( ) never
( ) always
  [ ] if match - color (face in emacs parlance) _____
  [ ] if mismatch color (face in emacs parlance) _____ 

I use a very light (smoke white) background in case of 'if match' and very 
light salmon in case of 'if mismatch'.

Helps easily see complicated if conditiuon or if the code block is within the 
page or runs below bottom of the page etc.
Comment 28 err 2007-05-02 15:54:30 UTC
There is no option to revert to original behavior. Since the match brace code is
in flux, it probably doesn't make sense to provide a UI to change the behavior
at this time.

I don't know what the SOP is. I can check for a system property to specify this.
If this would be appropriate, what are naming conventions?
Comment 29 jxt 2007-05-02 17:36:50 UTC
All this recent activity, particularly the code, is too complicated for me. I 
would just like to reiterate my request that the Ctrl-[ behavior to find the 
matching brace work with the cursor on either side of the "current" brace and, 
more to the point, with *whitespace between the brace and cursor*. I fear that 
all the activity has been to address just highlighting the matching brace but 
has overlooked the Ctrl-[ behavior. Frankly, I only sometimes pay any 
attention to the highlighted match, but I do use Ctrl-[ a lot. Having Ctrl-[ 
behave in a friendlier manner would be a big improvement, IMO. The point is 
that in code like this:

     {
     ...
|    }

pressing Ctrl-[ to find the opening brace should work with the cursor ANYWHERE 
on the line shown instead of only when the cursor is positioned after the 
closing brace.

Gilding the lily a bit, it would be even better for Ctrl-[ to work anywhere on 
the line, *even with non-code comments present*!. So, for example

     {
     ...
     } // some comment |
     <some additional code>

Here, it is obvious to the reader, but perhaps not the NetBeans editor, that 
pressing Ctrl-[ should still go to the opening brace. There is simply no other 
reasonable place that Ctrl-[ should jump to, so why not make Ctrl-[ always "do 
the right thing" instead of nothing at all in such a case?

Thanks.
Comment 30 err 2007-05-02 18:00:39 UTC
> ...request that the Ctrl-[ behavior to find the 
> matching brace work with the cursor on either side of the "current" brace
 
The patch just added to the trunk behaves as you request.

> and, more to the point, with *whitespace between the brace and cursor*.

Being a vim/jvi user, I certainly agree with this request. But since I use jvi I
don't entirely feel your pain; except for in an xml file where I would want
^[ (or jvi's %) at the beginning of the following line
    this is an <b>example</b> of fancy "brace" matching
to move the cursor to the "</b>"

As issue #91893 develops, I'm hoping it becomes clear how this feature can be
added to NB so that jvi can use it.
Comment 31 _ wadechandler 2007-05-02 18:15:44 UTC
Thanks for your work on this E. Hopefully the new SPI will not be too hard to
work with for migrating this to it.
Comment 32 Vitezslav Stejskal 2007-05-03 00:02:01 UTC
> I can check for a system property to specify this. If this would
> be appropriate, what are naming conventions?

No conventions really, except of making it as unambiguous as possible. It could
be something like 'org-netbeans-editor-BraceMatchingStyle" with case insensitive
values BEFORE, AFTER, EITHER_SIDE. I personally don't think we need it though.
The change was subtle and it should not be hard to adapt to it. I would much
rather see an official UI similar to what Sandip mentioned. 

As for the new SPI we are trying to make sure that all the usecases mentioned
here will be implementable. However, it does not mean that they all will be
implemented or in what timeframe. The primary goal for the new SPI is to replace
the old Syntax-based one and allow future enhancements in this area.
Comment 33 Vitezslav Stejskal 2007-05-10 06:55:06 UTC
*** Issue 56622 has been marked as a duplicate of this issue. ***
Comment 34 Vitezslav Stejskal 2007-05-10 06:56:24 UTC
*** Issue 66037 has been marked as a duplicate of this issue. ***
Comment 35 err 2009-12-26 13:02:38 UTC
This can be closed, unless its open for implementing a UI.

The editor brace matching infrastructure supports requested features. Note that the brace matching behavior is programmed by setting properties on the JTextComponent as described in http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-bracesmatching/overview-summary.html . In particular, take a look at
    Usecase 3. - Different search scenarios