Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use vscode-which-key to execute an existing keybinding? #5

Open
macintacos opened this issue Jul 31, 2020 · 13 comments
Open

How to use vscode-which-key to execute an existing keybinding? #5

macintacos opened this issue Jul 31, 2020 · 13 comments
Labels
help wanted Extra attention is needed upstream Issues related to upstream dependencies

Comments

@macintacos
Copy link

macintacos commented Jul 31, 2020

As an example, I have the following in my keybindings.json already:

  {
    "command": "workbench.view.explorer",
    "key": "cmd+f t"
  },
  {
    "command": "workbench.view.explorer",
    "key": "cmd+f t",
    "when": "sideBarVisible && !explorerViewletVisible"
  },
  {
    "command": "workbench.action.toggleSidebarVisibility",
    "key": "cmd+f t",
    "when": "sideBarVisible && explorerViewletVisible"
  },

The gist of the above keybindings is that it does one of three things when the chord cmd+f t is invoked:

  1. If the sidebar isn't open, open the sidebar and focus the explorer.
  2. If the sidebar is open but the explorer is not visible, open the explorer and focus it.
  3. If the sidebar is open and the explorer is visible, close it.

It works just fine. I'm trying to set up a which-key binding via VSpaceCode, however I can't figure out how to get this extension to execute a keyboard shortcut, and not a specific command. Right now I can't figure out how to get the above functionality baked into VSpaceCode (via which-key) so I'd rather just be able to execute a keybinding directly instead.

Is it possible to tell which-key to execute a keybinding that already exists?

@macintacos
Copy link
Author

macintacos commented Jul 31, 2020

As an aside, the above 3 conditions is how I expect SPC f t to work in VSpaceCode, since that's how it works in Spacemacs, but it doesn't. If I can get which-key to work by pointing to existing keybindings, I'll open an issue in VSpaceCode to have that implemented so that it works the wya that I expect.

@macintacos
Copy link
Author

Sorry for the various edits to the original description, had to clarify exactly what my keybindings do 🙂

@stevenguh
Copy link
Member

I would like to have this as well. I don't know if there's a way to execute keybinding from an extension.

AFAIK, there is currently no easy way for an extension to read the condition in when (lack of read in context API). Let's keep this open, maybe someone will figure out a way. I will keep thinking meanwhile.

@stevenguh stevenguh added the help wanted Extra attention is needed label Jul 31, 2020
@macintacos
Copy link
Author

As far as the ability to execute arbitrary keybindings from an extension, I'm going to try looking for examples or issues in the vscode repo to see if this has already been discussed before at some point, and open one and link it here if I can't find anything concrete.

I'd really like it if this could be added; for context, I have a keymap called "Chord Heavy" in the marketplace that has a lot of chords set up in a Spacemacs-esque fashion that I'd like to port over to VSpace code if possible, which is why I'm showing a ton of interest in this project in particular 😅

@stevenguh
Copy link
Member

Having getContext API would allow extension to read the when condition, and that issue has been on their radar for a few years. microsoft/vscode#10471

One hacky way to get around is to use keybindings.json to intercept t keys with different when different conditions and send those conditions to which-key to handle like how we handle \t in the QuickPick menu. However, this solution might not scale well with different keys. This way we are by passing the default keyboard input of the QuickPick menu for certain keys, and can have performance concerns. I will prototype it when I have time and see if this is too hacky.

Thank you for interested in this. We would love to have a community to make this better for most people and have to best out-of-box experience for people like spacemacs. Free feel to open issues to track any missing work, feature requests, just asking questions.

This repo is focused on the core code behind the menu display structure which can be a stand alone extension and as well for other extension to consume (like how VSpaceCode bundles this), and ships with a default bindings that doesn't using any third party extension.

The VSpaceCode repo, it hosts the best-of-the box experience like spacemacs with different bindings that uses third party extensions.

@stevenguh
Copy link
Member

stevenguh commented Aug 1, 2020

There are two options I am thinking. One is something you can do today, the another one involved more thinking and infrastructure.

First option:
The following example assumed you are using VSpaceCode, you can change the command name settings name for which key if you are not.
Merged the following keybindings to your keybindings.json

{
	// Adding this will allow VSpaceCode to run when side bar is focused
	{
		"key": "space",
		"command": "vspacecode.space",
		"when": "sideBarFocus && !inputFocus && !whichkeyActive"
	},
	// This is the workaround part, where it will intercept `t` when `whichkeyActive && sideBarVisible && explorerViewletVisible` and pass it back to `which key` as `t_` input.
	{
		"key": "t",
		"command": "whichkey.triggerKey",
		"args": "t_",
		"when": "whichkeyActive && sideBarVisible && explorerViewletVisible"
	}
}

Merge the following settings to your settings.json

{
    "vspacecode.bindingOverrides": [
        // This adds an entry to <spc> f with a key `t_` which will be triggered by the interpretation mechanism.
        {
            "keys": "f.t_",
            "name": "Hide side bar",
            "type": "command",
            "command": "workbench.action.toggleSidebarVisibility"
        },
    ],
}

Explanation:

  1. Adding keybinding to allow VSpaceCode menu to launch when ` is click when side bar is focused
  2. Intercept t key with a specific condition of when and pass it back to which key as t_
  3. Add overrides to add t_ in the <spc> f menu for that specific condition

This workaround works today with no in infrastructure change, although, there are some changes I can see to make this workaround a little bit better.

  • Implement option to hide particular binding from displaying
  • In addition, an extension to that is to have display only binding (I am thinking so <spc> 1...9 can be grouped)

One downside of this approach is that, t_ will be entered into other parts of menu when sideBarVisible && explorerViewletVisible and causing the regular t not execute.


Second option involves more infrastructure change. The process is similar, instead of passing just the key in the interception, pass an extra parameter like named condition to which key. Which key will also need to implement a way for a user to declare that in config and as well as to to match it in the core. Ideally, I am thinking this work should be generalizable to other condition matching like what mode vim is currently in. An imagined config for this might look like:

{
    "key": "t",
    "name": "Show tree/explorer view",
    "type": "conditional",
    "commands": ["workbench.view.explorer", "workbench.action.toggleSidebarVisibility"],
    "conditional": [null, "sideBarVisible && explorerViewletVisible"]
}

Ideally, I think I will work toward something like the second option, but first option is something you can do today :) Sorry for such a long comment. I am just dumping my current thoughts so I don't forget about them.

@macintacos
Copy link
Author

I appreciate the thorough response, so please don't worry about lengthy comments, I welcome them.

As for your workaround, I like it but for one.... it feels a bit hacky. I feel like I'd make it and then a week from now come back and completely forget how I actually created it. And of course, with no sane "go to definition" functionality for keybindings or settings JSON documents, I'd be stuck trying to remember exactly how this works, and I'm not a fan of configurations that can feel a bit too magical. I'm patient enough to wait for a "proper" implementation, at least on the consumer side (I'd hate it for this to get a bit hacky on your side, but naturally I'd leave that decision up to you).

Unfortunately, your first option in the latest comment won't work, because it doesn't keep all three conditions under the same keybinding. As far as I can tell, it only will close the sidebar if the explorer view is visible, which only matches 1/3 of the options that cmd+f t cover with my current keybindings.

To be honest, the current implementation of SPC f t in VSpaceCode is almost there, so I'll probably just open an issue in the VSpaceCode repo proper (it's just missing no. 3 in the condition I mentioned above, which is closing the sidebar if the explorer is visible - currently it just focuses the editor). The example I provided was more of a jumping off point for how to get vscode-which-key to invoke an existing keybinding, which (unfortunately) seems like it's not possible.

Last thing; I do think that your exploration into how to implement "when" conditions similar to how you can set them in native keybindings is worth continuing, but not sure if it fits into the spirit of this issue. Perhaps you should create a new issue referencing that to make sure that you don't lose that train of thought?

@stevenguh
Copy link
Member

Unfortunately, your first option in the latest comment won't work, because it doesn't keep all three conditions under the same keybinding. As far as I can tell, it only will close the sidebar if the explorer view is visible, which only matches 1/3 of the options that cmd+f t cover with my current keybindings.

Just want to make sure I understand. The first option doesn't work for you because

  1. the bindings are not in the same place (config experience issue)

and

  1. functionally not working

If there is a functionally issue, I'd like to know what's missing. I am current running that config and it seems to satisfy your 3 conditions you mentioned in the first post.

The example I provided was more of a jumping off point for how to get vscode-which-key to invoke an existing keybinding, which (unfortunately) seems like it's not possible.

Last thing; I do think that your exploration into how to implement "when" conditions similar to how you can set them in native keybindings is worth continuing, but not sure if it fits into the spirit of this issue. Perhaps you should create a new issue referencing that to make sure that you don't lose that train of thought?

I read this issue more as how to execute binding with a when condition, and I thoughts that's what you are trying to achieve when invoking keybindings (shortcuts). If you want to keep it issue strict to track the work to invoking keybindings, I can see another issue being valuable.

@macintacos
Copy link
Author

Yeah honestly I opened this in the spirit of "can this extension run existing shortcuts directly", so a new issue might be better.

As for implementation, I must've messed something up, because I just double-checked my config and its working as expected; sorry about that. I don't think I want to keep it that way more because of the configuration issue though.

@stevenguh
Copy link
Member

Created #11, although, realistically I am not optimistic that vscode will ever allow extension to invoke keybindings (shortcuts).

@macintacos
Copy link
Author

@stevenguh just noticed an unintentional side effect of the above t_ implementation that I'm not sure how to deal with aside from removing it altogether.

Now when I execute SPC p t, I can't hit the t menu item, it just inserts t_:

image

Also, I replaced the default SPC p p keybinding with the projectManager.listProjects, and for some reason when I'm searching for projects I can't type the literal letter t anymore. When I removed the t_ keybindings, the problem goes away entirely.

@stevenguh
Copy link
Member

That's the one of the cons about that approach (hack) I described above.

One downside of this approach is that, t_ will be entered into other parts of menu when sideBarVisible && explorerViewletVisible and causing the regular t not execute.

You can add t_ binding in <spc> p to fix this in the short term.

@macintacos
Copy link
Author

Oh blah sorry I glossed over that bit. Thanks!

@stevenguh stevenguh added the upstream Issues related to upstream dependencies label Oct 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed upstream Issues related to upstream dependencies
Projects
None yet
Development

No branches or pull requests

2 participants