1

I'm working on an extension for VSCode where I'd like to grow the cursor/caret into a selection limited to one word.

What's the best way to grow the selection to the whole word (such as foo_bar) including underscores, but no other symbols?

Double clicking words in the text editor works exactly as what I'm trying to achieve through code (it selects beyond underscores), but to my knowledge there's no command that produces the same behavior.

Closest thing I know is the "Expand Selection" command (AKA editor.action.smartSelect.expand).

Expand Selection, however, if executed once will stop at underscores, and if executed again, then it will select the whole word. That's good, but... it can be executed any number of times and then it will start selecting spaces, other symbols, lines, etc.

Maybe the best option is to use this Expand Selection command once, and check somehow in the code if there are underscores next to the current selection?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Yogensia
  • 23
  • 5
  • 1
    Possible duplicate of [Set selection range in the Visual Studio Code document](https://stackoverflow.com/questions/47250698/set-selection-range-in-the-visual-studio-code-document) – Gama11 Jun 18 '19 at 16:12
  • After further inspection I've found another way of getting the word at cursor, in this case without modifying the selection, which can also be useful: ```let word = editor.document.getWordRangeAtPosition(editor.selection.active);``` – Yogensia Jun 18 '19 at 22:53

2 Answers2

6

I wrote this out before seeing you already sort of answered your question, but since it might help beginners I'll still post it.

You can do this using executeCommand(), but that may be just a hack and a roundabout way of accomplishing what you want. (It's what I did when first writing an extension because I didn't understand or know where to look in the API). If your end goal is to select the word for the user then the hack might be fine (but may have side effects, like messing with the user's find items), but if it's just a way to get the word for use in your code then it's the wrong way to go about it. Since you already know the user can use smartSelect, I assume you want the latter.

You should use getWordRangeAtPosition() using the current selection start or end, and a regex that overrides the default wordbreak:

const range = document.getWordRangeAtPosition(
    vscode.window.activeTextEditor.selection.active,
    /\S+/
);

if (range) {
    // then you can get the word that's there:
    const word = document.getText(range); // get the word at the range

    // or modify the selection if that's really your goal:
    vscode.window.activeTextEditor.selection = new vscode.Selection(range.start, range.end);
}

That's an overly simple regex that treats any run of non-space characters as a word which will work for your example, but probably needs to be refined to eliminate punctuation.

aamarks
  • 942
  • 10
  • 17
  • How would you do something like that from a Language Server extension ? see this question - https://stackoverflow.com/questions/67163731/how-to-get-current-text-symbol-when-implementing-go-to-definition – Mauricio Gracia Gutierrez Apr 24 '21 at 16:17
1
vscode.commands.executeCommand('editor.action.addSelectionToNextFindMatch');
Alex
  • 59,571
  • 22
  • 137
  • 126
  • I never noticed `.addSelectionToNextFindMatch` can be used without an initial selection, and the result of using it that way is exactly what I was looking for, thanks. – Yogensia Jun 18 '19 at 20:13