I'd like to map a keybinding for a specific language mode. Specifically, I'd like to map j to gj, as shown in the README, but only for Markdown.
I've tried a couple variants of the when clause using, for example, resourceLangId == markdown, but since that's used for mappings (and not settings) it doesn't seem to be an option.
Is what I'm trying to do even possible? I have several custom filetype mappings in Vim and would like to carry that approach over to VSCode.
I was trying to do something like that also, but still no success...
Here is what I've tried:
...
{
"before": ["<leader>", "t"],
"after": [],
"commands": [
{
"command": "extension.runFileOnRspec",
"when": "editorLangId == 'ruby'"
}
]
},
...
Any luck on this, @tjstankus?
Cheers
Nope, not supported and I can't imagine this to be added to ROADMAP anytime soon. In regards to @luisrpp suggestion, the when clause is not supported as we extensions can't retrieve those context variables from VSCode.
@jpoon you can get the file name though right? This would allow for people to have ftdetect style bindings. It is surprising this would not be on the roadmap for a vim emulator.
@jpoon Does this mean the following can also not be supported?
// in settings.json
"[latex]": {
"vim.normalModeKeyBindings": [
{
"before": [
"<leader>",
"o"
],
"commands": [
"latex-structure.focus"
]
},
]
},
Adding this gives a warning: _Unknown Identifier. Use language identifiers_ with respect to the normalModeKeyBindings identifier.
Although language-specific settings would be ideal for me, I tried to work around it by adding workspace settings to overwrite/extend the user settings (since in my case a workspace contains 1 language only). The following doesn't work either though:
// in workspace settings.json
"settings": {
"vim.normalModeKeyBindings": [
{
"before": [
"<leader>",
"o"
],
"commands": [
"latex-structure.focus"
]
},
]
}
... because it totally replaces the global vim.normalModeKeyBindings setting. If there is a way to make this work I would be happy to hear it.
(for now I use vim.normalModeKeyBindingsNoRecursive in user settings, and vim.normalModeKeyBindings in workspace settings, which isn't ideal but does the trick)
Looking at the documentation of the vscode api, seems like getting the languageId should be possible from the TextEditor object. At least that info could be used for defining file type specific key bindings, no?
Here is the link to the documentation: https://code.visualstudio.com/api/references/vscode-api#TextDocument
Looking at the documentation of the vscode api, seems like getting the languageId should be possible from the TextEditor object. At least that info could be used for defining file type specific key bindings, no?
Yes, this is possible. See getConfiguration here: https://code.visualstudio.com/api/references/vscode-api#workspace. This does not currently work because we load remaps on startup and only reload them if configuration changes. We'd really need to reload them (probably with some caching) each time a new file type is opened, using the scope parameter.
Why is that? Whenever the file is saved, the extension could just keep a structure in memory with the mappings and then when the user presses a key the extension just checks against this data structure to see if there is a (key combination, file type) entry in the list. If there isn't, then check if there is a (key combination, GLOBAL) in the list, which is a key combination that does not depend on the file type. Does that make sense?
Ah, I was thinking that getConfiguration would return the underlying "global" value if one specific to the language is not there, but after looking a bit closer, I think you're right. In any case, this is doable with the current API and shouldn't be too difficult or expensive.
I'll assign myself but if anyone wants to open a PR before I get to it, just let me know
@J-Fields You can reassign this to me if you want. I've looked into this before when working on the remap overhaul. I think I have a branch somewhere where I was working on this. But here are some remarks that I remember:
getConfiguration with a specific scope like { languageId: "python" } WILL load the global configuration when a specific one isn't found! This is problematic, because there is no way for us to know if the returned config is specific to that languageId or if it is global. We would have to load the config with no scope first, and then for each scope compare it to the loaded global.
In order for the user to make settings per language without a warning showing up saying "This setting does not support per-language configuration" we would have to duplicate our entire "package.contributes.configuration" into whatever language we want to support like this:
{
"contributes": {
"configuration": { OurEntireGlobalConfiguration },
"languages": [
{
"id": "typescript",
"configuration": { duplicate of OurEntireGlobalConfiguration }
},
{
"id": "python",
"configuration": { duplicate of OurEntireGlobalConfiguration }
},
{
"id": "javascript",
"configuration": { duplicate of OurEntireGlobalConfiguration }
},
// (...) and on and on for every language we want to support
]
I didn't test if we can have a wildcard like "id": "*", but I didn't find any information supporting that. On the brightside if the user sets specific settings for a language we don't support, even though it will show the yellow warning lines, we will still be able to load them as long as the configuration is loaded while a file of that type is the activeTextEditor.
I think that maybe the best way is to have a temporarily "buffer" configuration (like VIM does) that is bound to a specific editor/document (modeHandler) and stores the configurations that are read from that editor specific languageId scope and it also temporarily stores any changes made using the commandLine (like :set ts=4, or if implemented :nmap a b). This buffer configuration would be discarded when that editor is closed (since we don't have buffers like in VIM, I believe that tying this to a document modeHandler is the closest we can get). This would mean, however, that we would require loading the configuration every time we changed documents (unless we changed to one with the same langId as the previous).
Actually my point 2 is completely wrong! We can't do that sort of per-language configurations, the allowed per-language configurations are defined. I don't know if it is even possible to do it without vscode giving the warning...
I believe the warning can be avoided by setting the configuration scope to language-overridable (see scope here). Seems like the way to go is putting most of our config under this scope then storing a different Configuration per language (and clear that map whenever config changes), like you mentioned.
Most helpful comment
@jpoon you can get the file name though right? This would allow for people to have
ftdetectstyle bindings. It is surprising this would not be on the roadmap for a vim emulator.