Skip to content

Commit 9a490fc

Browse files
authored
Change code area navigation (#1090)
* Removed CodeArea selectWord using BreakIterator * Override CodeArea navigation with RegEx implementation * Updated regex to include symbols
1 parent 3552a27 commit 9a490fc

1 file changed

Lines changed: 73 additions & 28 deletions

File tree

richtextfx/src/main/java/org/fxmisc/richtext/CodeArea.java

Lines changed: 73 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package org.fxmisc.richtext;
22

3-
import java.text.BreakIterator;
43
import java.util.Collection;
4+
import java.util.regex.Matcher;
5+
import java.util.regex.Pattern;
56

67
import javafx.beans.NamedArg;
78
import org.fxmisc.richtext.model.EditableStyledDocument;
@@ -52,50 +53,94 @@ public CodeArea(@NamedArg("text") String text) {
5253
// position the caret at the beginning
5354
selectRange(0, 0);
5455
}
55-
56-
@Override // to select words containing underscores
57-
public void selectWord()
56+
57+
protected Pattern WORD_PATTERN = Pattern.compile( "\\w+" );
58+
protected Pattern WORD_OR_SYMBOL = Pattern.compile(
59+
"([\\W&&[^\\h]]{2}" // Any two non-word characters (excluding white spaces), matches like:
60+
// != <= >= == += -= *= -- ++ () [] <> && || // /* */
61+
+"|\\w*)" // Zero or more word characters [a-zA-Z_0-9]
62+
+"\\h*" // Both cases above include any trailing white space
63+
);
64+
65+
/**
66+
* Skips ONLY 1 number of word boundaries backwards.
67+
* @param n is ignored !
68+
*/
69+
@Override
70+
public void wordBreaksBackwards(int n, SelectionPolicy selectionPolicy)
5871
{
5972
if ( getLength() == 0 ) return;
6073

6174
CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
6275
int paragraph = csb.getParagraphIndex();
6376
int position = csb.getColumnPosition();
64-
65-
String paragraphText = getText( paragraph );
66-
BreakIterator breakIterator = BreakIterator.getWordInstance( getLocale() );
67-
breakIterator.setText( paragraphText );
77+
int prevWord = 0;
6878

69-
breakIterator.preceding( position );
70-
int start = breakIterator.current();
79+
if ( position == 0 ) {
80+
prevWord = getParagraph( --paragraph ).length();
81+
moveTo( paragraph, prevWord, selectionPolicy );
82+
return;
83+
}
84+
85+
Matcher m = WORD_OR_SYMBOL.matcher( getText( paragraph ) );
7186

72-
while ( start > 0 && paragraphText.charAt( start-1 ) == '_' )
87+
while ( m.find() )
7388
{
74-
if ( --start > 0 && ! breakIterator.isBoundary( start-1 ) )
75-
{
76-
breakIterator.preceding( start );
77-
start = breakIterator.current();
89+
if ( m.start() == position ) {
90+
moveTo( paragraph, prevWord, selectionPolicy );
91+
break;
92+
}
93+
if ( (prevWord = m.end()) >= position ) {
94+
moveTo( paragraph, m.start(), selectionPolicy );
95+
break;
7896
}
7997
}
98+
}
99+
100+
/**
101+
* Skips ONLY 1 number of word boundaries forward.
102+
* @param n is ignored !
103+
*/
104+
@Override
105+
public void wordBreaksForwards(int n, SelectionPolicy selectionPolicy)
106+
{
107+
if ( getLength() == 0 ) return;
108+
109+
CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
110+
int paragraph = csb.getParagraphIndex();
111+
int position = csb.getColumnPosition();
80112

81-
breakIterator.following( position );
82-
int end = breakIterator.current();
83-
int len = paragraphText.length();
113+
Matcher m = WORD_OR_SYMBOL.matcher( getText( paragraph ) );
84114

85-
while ( end < len && paragraphText.charAt( end ) == '_' )
115+
while ( m.find() )
86116
{
87-
if ( ++end < len && ! breakIterator.isBoundary( end+1 ) )
88-
{
89-
breakIterator.following( end );
90-
end = breakIterator.current();
117+
if ( m.start() > position ) {
118+
moveTo( paragraph, m.start(), selectionPolicy );
119+
break;
91120
}
92-
// For some reason single digits aren't picked up so ....
93-
else if ( Character.isDigit( paragraphText.charAt( end ) ) )
94-
{
95-
end++;
121+
if ( m.hitEnd() ) {
122+
moveTo( paragraph+1, 0, selectionPolicy );
96123
}
97124
}
125+
}
126+
127+
@Override
128+
public void selectWord()
129+
{
130+
if ( getLength() == 0 ) return;
131+
132+
CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
133+
int paragraph = csb.getParagraphIndex();
134+
int position = csb.getColumnPosition();
98135

99-
csb.selectRange( paragraph, start, paragraph, end );
136+
Matcher m = WORD_PATTERN.matcher( getText( paragraph ) );
137+
138+
while ( m.find() )
139+
{
140+
if ( m.end() > position ) {
141+
csb.selectRange( paragraph, m.start(), paragraph, m.end() );
142+
return;
143+
}
144+
}
100145
}
101146
}

0 commit comments

Comments
 (0)