Skip to content

Commit

Permalink
Change code area navigation (#1090)
Browse files Browse the repository at this point in the history
* Removed CodeArea selectWord using BreakIterator
* Override CodeArea navigation with RegEx implementation
* Updated regex to include symbols
  • Loading branch information
Jugen authored Feb 24, 2022
1 parent 3552a27 commit 9a490fc
Showing 1 changed file with 73 additions and 28 deletions.
101 changes: 73 additions & 28 deletions richtextfx/src/main/java/org/fxmisc/richtext/CodeArea.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.fxmisc.richtext;

import java.text.BreakIterator;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javafx.beans.NamedArg;
import org.fxmisc.richtext.model.EditableStyledDocument;
Expand Down Expand Up @@ -52,50 +53,94 @@ public CodeArea(@NamedArg("text") String text) {
// position the caret at the beginning
selectRange(0, 0);
}

@Override // to select words containing underscores
public void selectWord()

protected Pattern WORD_PATTERN = Pattern.compile( "\\w+" );
protected Pattern WORD_OR_SYMBOL = Pattern.compile(
"([\\W&&[^\\h]]{2}" // Any two non-word characters (excluding white spaces), matches like:
// != <= >= == += -= *= -- ++ () [] <> && || // /* */
+"|\\w*)" // Zero or more word characters [a-zA-Z_0-9]
+"\\h*" // Both cases above include any trailing white space
);

/**
* Skips ONLY 1 number of word boundaries backwards.
* @param n is ignored !
*/
@Override
public void wordBreaksBackwards(int n, SelectionPolicy selectionPolicy)
{
if ( getLength() == 0 ) return;

CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
int paragraph = csb.getParagraphIndex();
int position = csb.getColumnPosition();

String paragraphText = getText( paragraph );
BreakIterator breakIterator = BreakIterator.getWordInstance( getLocale() );
breakIterator.setText( paragraphText );
int prevWord = 0;

breakIterator.preceding( position );
int start = breakIterator.current();
if ( position == 0 ) {
prevWord = getParagraph( --paragraph ).length();
moveTo( paragraph, prevWord, selectionPolicy );
return;
}

Matcher m = WORD_OR_SYMBOL.matcher( getText( paragraph ) );

while ( start > 0 && paragraphText.charAt( start-1 ) == '_' )
while ( m.find() )
{
if ( --start > 0 && ! breakIterator.isBoundary( start-1 ) )
{
breakIterator.preceding( start );
start = breakIterator.current();
if ( m.start() == position ) {
moveTo( paragraph, prevWord, selectionPolicy );
break;
}
if ( (prevWord = m.end()) >= position ) {
moveTo( paragraph, m.start(), selectionPolicy );
break;
}
}
}

/**
* Skips ONLY 1 number of word boundaries forward.
* @param n is ignored !
*/
@Override
public void wordBreaksForwards(int n, SelectionPolicy selectionPolicy)
{
if ( getLength() == 0 ) return;

CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
int paragraph = csb.getParagraphIndex();
int position = csb.getColumnPosition();

breakIterator.following( position );
int end = breakIterator.current();
int len = paragraphText.length();
Matcher m = WORD_OR_SYMBOL.matcher( getText( paragraph ) );

while ( end < len && paragraphText.charAt( end ) == '_' )
while ( m.find() )
{
if ( ++end < len && ! breakIterator.isBoundary( end+1 ) )
{
breakIterator.following( end );
end = breakIterator.current();
if ( m.start() > position ) {
moveTo( paragraph, m.start(), selectionPolicy );
break;
}
// For some reason single digits aren't picked up so ....
else if ( Character.isDigit( paragraphText.charAt( end ) ) )
{
end++;
if ( m.hitEnd() ) {
moveTo( paragraph+1, 0, selectionPolicy );
}
}
}

@Override
public void selectWord()
{
if ( getLength() == 0 ) return;

CaretSelectionBind<?,?,?> csb = getCaretSelectionBind();
int paragraph = csb.getParagraphIndex();
int position = csb.getColumnPosition();

csb.selectRange( paragraph, start, paragraph, end );
Matcher m = WORD_PATTERN.matcher( getText( paragraph ) );

while ( m.find() )
{
if ( m.end() > position ) {
csb.selectRange( paragraph, m.start(), paragraph, m.end() );
return;
}
}
}
}

0 comments on commit 9a490fc

Please sign in to comment.