I am new to WPF and currently I am studying to create a Sublime Text that has syntax highlighting. I come to a challenge in figuring out the TextRange of word at current caret position (Not include symbols e.g: for( will return the whole word instead of for only). More over because already solutions are checking the whole file which could be reduce the performance considerably. Are there any solution for this problems thank you! Below is my code
private TextRange getCurrentWordRange()
{
List<string> spaces = new List<string> { " ", "\t" ,";","(", ")", "=" };
List<string> symbols=new List<string>{};
TextPointer current = richTextBox.CaretPosition;
TextPointer start = current, end = current;
//Traverse to get the start of word
while (start.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text)
{
TextRange textRange = new TextRange(start.GetPositionAtOffset(-1), start); // get the textRange of the previous start
if (spaces.Any(token => textRange.Text.Contains(token))) // check if textRange.Text has token that inside spaces
break;
else
start = start.GetPositionAtOffset(-1);
}
//Traverse to get the end of word
while(end.GetPointerContext(LogicalDirection.Forward)==TextPointerContext.Text)
{
TextRange textRange = new TextRange(end,end.GetPositionAtOffset(1)); // get the textRange of the next start
if (spaces.Any(token => textRange.Text.Contains(token)))
break;
else
end = end.GetPositionAtOffset(1);
}
return new TextRange(start,end);
}
EDIT Fortunately, I rethink and writing the below code that might be success in the case. Hope anyone can check if it is correct. Thank you.
private TextRange getCurrentWordRange()
{
List<string> spaces = new List<string> { " ", "\t" };
List<string> symbols = new List<string> { ";", "(", ")", "=", "<", ">", "\"", ",", ".", "[", "]", ":" };
TextPointer current = richTextBox.CaretPosition;
TextPointer start = current, end = current;
TextRange backward;
TextRange forward;
// check if start and end are not the Content.Start and Content.End
if (start.GetPositionAtOffset(-1) == null)
backward = new TextRange(start, start);
else
backward = new TextRange(start.GetPositionAtOffset(-1), start);
if (end.GetPositionAtOffset(1) == null)
forward = new TextRange(end, end);
else
forward = new TextRange(end, end.GetPositionAtOffset(1));
while (!spaces.Contains(backward.Text) && start.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text && !symbols.Contains(backward.Text))
{
start = start.GetPositionAtOffset(-1);
backward = new TextRange(start, start.GetPositionAtOffset(-1));
}
while (!spaces.Contains(forward.Text) && end.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text && !symbols.Contains(forward.Text))
{
end = end.GetPositionAtOffset(1);
forward = new TextRange(end, end.GetPositionAtOffset(1));
}
// if between start and end is "" then consider add a left adjacent or right adjacent symbol for further development
if (new TextRange(start, end).Text == "")
{
if (symbols.Contains(backward.Text))
{
start = start.GetPositionAtOffset(-1);
}
else if (symbols.Contains(forward.Text))
{
end = end.GetPositionAtOffset(-1);
}
}
return new TextRange(start, end);
}
I created a TextChanged Event for RTB then perform few functions to check and highlight keyword It work great with @Jackdaw solution but stuck at that case again