Question
Here is my keymap. The second re-map works fine. ctrl+x
works as cursorDown. But I can’t get it to select the next item in a suggestion. It just exits the dropdown and moves the cursor. As if the first mapping does not exist. This seems like it should work. Am I missing some magic?
// Place your key bindings in this file to override the defaults
[
{
"key":"ctrl+x",
"command": "selectNextSuggestion",
"when": "suggestWidgetMultipleSuggestions && suggestWidgetVisible && textInputFocus"
},
{
"key":"ctrl+x",
"command": "cursorMove",
"args": {
"to":"down",
"by": "line",
"value": 1,
},
"when": "textInputFocus"
},
]
The when
clause looks to be exactly the same as downArrow
for the same command.
I’m running version 1.76.2 on linux. Fresh install. No extensions, no other keys mapped, no settings changed.
ANSWER
The issue you are encountering is due to a conflict between the when
clauses of your two key bindings. Specifically, the when
clause for your first key binding, which selects the next suggestion, is more specific than the when
clause for the default key binding that also selects the next suggestion. As a result, your key binding is overriding the default key binding, and instead of selecting the next suggestion, it is executing the cursorMove
command.
To understand why this is happening, it’s important to understand how the when
clause works. The when
clause is a condition that determines when a key binding is applicable. It consists of one or more expressions that evaluate to true or false. If all of the expressions evaluate to true, then the key binding is applicable. If any of the expressions evaluate to false, then the key binding is not applicable.
In your case, both of your key bindings have the same key (ctrl+x
), which means that they will both be triggered when you press that key. However, they have different when
clauses, which means that only one of them will actually be executed. The key binding that is executed is determined by the specificity of the when
clause. If one when
clause is more specific than the other, then that key binding will take precedence.
In your original key bindings, the when
clause for your first key binding was "when": "suggestWidgetMultipleSuggestions && suggestWidgetVisible && textInputFocus"
. This means that the key binding is applicable when all of the following conditions are true:
- There are multiple suggestions available in the suggestion widget (
suggestWidgetMultipleSuggestions
) - The suggestion widget is visible (
suggestWidgetVisible
) - The text input field has focus (
textInputFocus
)
The when
clause for your second key binding was "when": "textInputFocus"
. This means that the key binding is applicable when the text input field has focus, regardless of whether the suggestion widget is visible or how many suggestions are available.
The when
clause for the default key binding that selects the next suggestion is "when": "suggestWidgetVisible && !suggestWidgetMultipleSuggestions && !editorReadonly"
. This means that the key binding is applicable when all of the following conditions are true:
- The suggestion widget is visible (
suggestWidgetVisible
) - There is only one suggestion available in the suggestion widget (
!suggestWidgetMultipleSuggestions
) - The editor is not in readonly mode (
!editorReadonly
)
As you can see, the when
clause for your first key binding is more specific than the when
clause for the default key binding, because it includes an additional condition (suggestWidgetMultipleSuggestions
). This means that your key binding will take precedence over the default key binding when there are multiple suggestions available in the suggestion widget.
To fix this issue, you can modify the when
clause for your first key binding to match the when
clause for the default key binding. Here is the updated key binding:
{
"key": "ctrl+x",
"command": "selectNextSuggestion",
"when": "suggestWidgetVisible && !suggestWidgetMultipleSuggestions && textInputFocus"
},
{
"key": "ctrl+x",
"command": "cursorMove",
"args": {
"to": "down",
"by": "line",
"value": 1
},
"when": "textInputFocus"
}
With this updated key binding, pressing ctrl+x
will select the next suggestion when there are multiple suggestions available, and move the cursor down by one line when there is only one suggestion or no suggestions available.
addition to the explanation of the when
clauses, it’s also worth mentioning how to debug key bindings in VS Code.
One way to do this is to use the Developer: Open Keyboard Shortcuts command, which can be accessed from the Command Palette (Ctrl+Shift+P
on Windows and Linux, Cmd+Shift+P
on macOS) by typing “Open Keyboard Shortcuts” and selecting the command from the list. This command will open a new window with a searchable list of all the key bindings in VS Code.
To debug a key binding, you can search for it in the list and click on it to see its details. This will show you the key combination, the command that it is bound to, and the when
clause that determines when the key binding is applicable. You can also use the Filter Keybindings input field at the top of the window to filter the list by key combination or command name.
If you are still having issues with your key binding, you can try disabling other extensions or changing other settings that might be conflicting with it. You can also try resetting your key bindings to the default settings by clicking the Reset button at the bottom of the Developer: Open Keyboard Shortcuts window.
In conclusion, the issue you are encountering with your key bindings is due to a conflict between the when
clauses of your two key bindings. By modifying the when
clause of your first key binding to match the when
clause of the default key binding, you can ensure that both key bindings work as expected. Debugging key bindings in VS Code can be a helpful tool for resolving issues with key bindings, and resetting your key bindings to the default settings can be a useful troubleshooting step if you are still having issues