Get TextRange of the current word at caret

258 Views Asked by At

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);
}

Capture

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

0

There are 0 best solutions below