(((This is a bug)) since the first day) I join Notepad++
-
Please use Ctrl+B to detect what is wrong.
Correct:
( (Here is a bug) since the ( (first day) ) I joined Notepad++ ( ( (and found ( (and reported
for version 7.6) ), but it gets no corrections) for version 7.8) ) and (I could not find my post any more) ).Errors:
((Here is a bug) since the ((first day)) I joined Notepad++ (((and found ((and reported
for version 7.6)), but it gets no corrections) for version 7.8)) and (I could not find my post any more)).My temporary solution is adding a space between any contiguous ‘(’ or ‘)’.
-
@W-TX said in (((This is a bug)) since the first day) I join Notepad++:
(I could not find my post any more) ).
Not all that difficult: https://community.notepad-plus-plus.org/topic/17676/control-b-does-not-work-correctly-why
-
@Alan-Kilborn Thank you.
-
@W-TX Even though on the first day I used Notepad++ I found the Control+b bug, it is the most efficient text editor, second to none!
-
Hello, @w-tx, @alan-kilborn and All,
The default
CTRL + Bbehavior is-
If caret is, either, right before or right after a starting parenthesis
(aCtrl + Baction moves the caret right before its matched ending parenthesis) -
If caret is, either, right before or right after an ending parenthesis
)aCtrl + Baction moves the caret right before its matched starting parenthesis(
Anyone easily understands that, in case of jointed parentheses
((, or))or, even,)(there’s a problem becauseCtrl + Boperates, both, if you place the caret before of after a parenthesis :-((Logically, the correct behaviour should be :
-
If caret is, either, right after a starting parenthesis
(aCtrl + Baction moves the caret right before its matched ending parenthesis) -
If caret is, either, right before an ending parenthesis
)aCtrl + Baction moves the caret right after its matched starting parenthesis(
Now, I found a work-around to get a logical behavior ;-)) As you know, regular expressions are my beloved hobby ;-)). So, using a resursive regex construction solves the wrong behavior of
Ctrl + B, in case of consecutive parentheses !First, I’m going to explain the regex. This surely will seem a bit tricky to some people but don’t panic ! In the second part of this post, I will discuss of some very practical combinations with the regex and some keyboard actions to simulate the correct
Ctrl + Bbehaviour ;-))
The magic search regex is :
(?x) \( ( [^()]+ | (?0) )* \)What’s that means :
-
First, the
(?x)in-line modifier forces the regex engine to ignore any space character and new-line chars in the regex and, incidentally, to add comments -
Then, the part
\(looks for a literal starting parenthesis(, because of the escaped form -
Similarly, at the end, the
\)part searches for a literal ending parenthesis), for the same reason -
Between this two parentheses, the part
( [^()]+ | (?0) )*represents a group, possibly empty, due to the*quantifier, which may be repeated as many as possible, containing two alternatives :-
The part
[^()]+which grasps any non-null range of characters, different from parentheses(and) -
The part
(?0)which is a recursive call to the entire regex pattern
-
How this recursion process works ?
Let suppose, the MAIN part of the regex ( SPACES are supposed to be IGNORED ) - The regex \( ( [^()]+ | (?0) )* \) is SIMILAR to : ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯ \______________ =(?0) _____________|_______________ - the regex \( ( [^()]+ | \( ( [^()]+ | (?0) )* \) )* \) which is, itself, SIMILAR to : ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯ \_______________ = (?0) _____________|_______________ - the regex \( ( [^()]+ | \( ( [^()]+ | \( ( [^()]+ | (?0) )* \) )* \) )* \) which is, itself, SIMILAR to : and so on ...Now, we can still improve our regex, by using :
-
A non-capturing group, as we don’t need group
1contents -
A possessive quantifier, in order that the range of allowed characters will be treated as an atomic range of chars, where backtracking is forbidden. We can do that because, in PCRE regexes, any recursion call is treated in an atomic way, anyway !
So our magic final regex is :
(?x) \( (?: [^()]++ | (?0) )* \)
In order to assign a shortcut to our regex, here are two macros, which you’ll have to insert in the
<Macros>....</Macros>section of you activeshortcuts.xmlconfiguration file. They allow search of well-balanced blocks of parentheses in downwards (ALT + Bshortcut ) and backward direction (Alt + Shift + Bshortcut ) with the wrap-around behavior<Macro name="Regex_Forward" Ctrl="no" Alt="yes" Shift="no" Key="66"> <!-- ALT + B shortcut --> <Action type="3" message="1700" wParam="0" lParam="0" sParam="" /> <Action type="3" message="1601" wParam="0" lParam="0" sParam="(?x) \( (?: [^()]++ | (?0) )* \)" /> <Action type="3" message="1625" wParam="0" lParam="2" sParam="" /> <!-- REGULAR expression search mode --> <Action type="3" message="1702" wParam="0" lParam="768" sParam="" /> <!-- DOWNWARD search --> <Action type="3" message="1701" wParam="0" lParam="1" sParam="" /> <!-- Hit on the FIND NEXT button --> </Macro> <Macro name="Regex_Backward" Ctrl="no" Alt="yes" Shift="yes" Key="66"> <!-- ALT + SHIFT + B shortcut --> <Action type="3" message="1700" wParam="0" lParam="0" sParam="" /> <!-- INITIALIZATION --> <Action type="3" message="1601" wParam="0" lParam="0" sParam="(?x) \( (?: [^()]++ | (?0) )* \)" /> <Action type="3" message="1625" wParam="0" lParam="2" sParam="" /> <!-- REGULAR expression search mode --> <Action type="3" message="1702" wParam="0" lParam="256" sParam="" /> <!-- BACKWARD search --> <Action type="3" message="1701" wParam="0" lParam="1" sParam="" /> <!-- Hit on the FIND NEXT button --> </Macro>If, for testing, you don’t want to use a macro, here is an alternate method :
-
Open the Find dialog
-
Type in the regex
(?x) \( (?: [^()]++ | (?0) )* \), in the Find what: zone -
Untick the
Backwardoption, if necessary -
Select the
Regular expressionsearch mode -
Hit the
Find Nextbutton -
Whatever the result, close the Find dialog with the
ESCkey -
Open one of your code files, containing some parentheses
=> Now, from caret position :
-
Any hit on the
F3shortcut, will select the next well-balanced block of parentheses -
Any hit on the
Shift + F3shortcut, will select the previous well-balanced block of parentheses
Practical example :
Let’s assume the simple text, below. Note that I wrote it in a single line for readability, but this text could be displayed in several lines, either !
123(456(()7890)12(345((678)((901)2(34567)890(12345)678)90123456((7890(12345)67))8901)2345))6789 >< >< >< 3rd 2nd 1st-
Move the caret to the
"1st"position, so between the0digit and the( -
Hit the
F3key :
=> The
(12345)block, with its parentheses, is selected. As you can see, this operation is similar to theCtrl + Alt +B( Select All Between Matching Braces ).-
At this point, you may, either :
-
Hit the
Ctrl + Cshortcut, if you need to copy that well-balanced block of parentheses somewhere else -
Hit the
Rightarrow key to suppress selection and place the caret right after the ending) -
Hit the
Leftarrow key to suppress selection and place the caret right before the starting( -
You may, instead, hit the
CTRL + Bshortcut for the similar above operation !
-
Now, let’s try some searches, in both directions :
-
Move the caret to the
"2nd"position, so between the)and the9digit- Hit the
F3key
- Hit the
=> You’ll notice that the regex finds the next largest well-balanced block, which is
((7890(12345)67))- Hit the
Shift + F3shortcut to search in backward direction
=> The inner block
(7890(12345)67)is selected, as expected- Hit, again, the
Shift + F3shortcut
=> The inner block
(12345)is then selected- Hit, again, the
Shift + F3shortcut
This time, as no more inner block exists, it jumps back to previous largest block
((901)2(34567)890(12345)678)At this point,
3possibilities :- If you hit the
F3key
=> you’ll get the
((7890(12345)67))block again- If you’ll hit, successively, on the
rightthen theleftkey and, finally, theShift + F3shortcut
=> The closest inner block, near the end of present block, is selected
(12345)- If you’ll hit, successively, on the
leftthen therightkey and, finally, theF3shortcut
=> The closest inner block, near the start of present block, is selected
(901)After a while , I’m quite sure you’ll get acquainted, very quickly, to this regex behaviour !
-
Now, move the caret to the
"3rd"position, so between the two starting parentheses(( -
Hit the
F3key
=> As expected, it selects the empty block
()- Hit the
F3key again,
=> This time, the regex selects the penultimate largest block of my example, so the well-balanced block :
(345((678)((901)2(34567)890(12345)678)90123456((7890(12345)67))8901)2345)
To end with, may be you could also give it a try to :
-
The regex
\((?:[^()]++|(?0))*\K\)which only matches the ending matched parenthesis) -
The regex
\((?:[^()]++|(?0))*\)\Kwhich matches the zero-length position, right after the ending matched parenthesis)
Best Regards,
guy038
P.S. :
Of course, this recursive regex can be used with an other couple of delimiters, which could be, for instance :
-
{and}=> The recursive regex would be(?x) \{ (?: [^{}]++ | (?0) )* \} -
[and]=> The recursive regex would be(?x) \[ (?: [^][]++ | (?0) )* \] -
<and>=> The recursive regex would be(?x) < (?: [^<>]++ | (?0) )* >
-
-
This is the patch I prepared for myself 4 (or more) years ago.
Initially I tried to contribute it into Notepad++ main repository but after giving up I started maintaining my own build. Still using it based on ver 6.7.8.2. -
Managed to dig the ticket I posted on sourceforge.
-
@gstavi said in (((This is a bug)) since the first day) I join Notepad++:
Managed to dig the ticket I posted on sourceforge.
In the linked ticket, @donho said:
The current behaviour is preferable comparing with the one you suggested.
He is perhaps unique in liking the behavior! :-( Of course, deciding you like the behavior is much easier than doing something to change it. :-)