Open bersace opened 3 months ago
Yep. We could use some better documentation around context for keybindings. Here's a non-exhaustive list of contexts used by the default bindings.
Workspace
Pane
ProjectPanel
(left files sidebar)
ProjectPanel && not_editing
Editor
Editor && mode == full
Editor && mode == full && inline_completion
Editor && mode == full && !jupyter
Editor && mode == full && inline_completion
Editor && !inline_completion
Editor && mode == auto_height
Editor && renaming
Editor && showing_completions
Editor && inline_completion && !showing_completions
Editor && showing_code_actions
Editor && (showing_code_actions || showing_completions)
ContextEditor > Editor
Picker > Editor
BufferSearchBar
BufferSearchBar && in_replace
BufferSearchBar && !in_replace > Editor
ProjectSearchBar
ProjectSearchBar > Editor
ProjectSearchBar && in_replace > Editor
ProjectSearchBar && !in_replace
ProjectSearchView
Dock
AssistantPanel
PromptLibrary
Terminal
OutlinePanel
CollabPanel
CollabPanel && not_editing
(CollabPanel && editing) > Editor
ChannelModal
ChannelModal > Picker > Editor
TabSwitcher
(ctrl-tab / ctrl-shift modal)FileFinder
(cmd+p modal "Search project files")Markdown
(markdown preview window)EmptyPane || SharedScreen
Plus a bunch more in vim.json
What is mode ?
Editor mode
can be either full
or auto_height
. Full is the normal editor, I believe auto_height
is during the find in files where you can directly edit the results (in a height constrained space).
What context when no file are opens ?
If you have no panels in focus, no files open Workspace
or global (no context) will apply.
What is Markdown?
Markdown preview.
How to know the current context ? How to know available shortcut in a context ? Doom Emacs has a bottom drawer showing next shortcut.
This would be a useful enhancement.
Thanks @notpeter
Workspace
also applies if a panel is opened. I want space space
to trigger file_finder::Toggle
only if no panel.
Anyway, a documentation on this powerfull feature would be great, e.g. for community to implement #4642 .
Regards,
What does "BufferSearchBar && !in_replace > Editor"
mean ? Especially the greater than sign ?
Workspace
also applies if a panel is opened. I wantspace space
to triggerfile_finder::Toggle
only if no panel.
EmptyPane
do the trick. Thanks !
A primer:
Contextes:
AssistantPanel
BufferSearchBar
ChannelModal
CollabPanel
ContextEditor
Dock
Editor
EmptyPane
FileFinder
Markdown
OutlinePanel
Pane
Picker
ProjectPanel
ProjectSearchBar
ProjectSearchView
PromptLibrary
TabSwitcher
Terminal
VimControl
Workspace
vim_mode
values :
insert
normal
operator
replace
visual
waiting
Context operators:
&&
!=
==
>
()
!
||
Variables:
auto_height
editing
full
inline_completion
in_replace
jupyter
menu
mode
not_editing
renaming
showing_code_actions
showing_completions
vim_mode
vim_operator
I grepped from keymaps, not Rust.
From grepping Rust code:
Identifiers (key_context.add(...)
, .key_context(...)
, dispatch_context.add(...)
):
alternate_scroll
any_mouse_reporting
AssistantPanel
bracketed_paste
BufferSearchBar
ChannelModal
ChatPanel
child-1
child-2
CollabPanel
ContextEditor
copilot_suggestion
DECAWM
DECCKM
DECOM
DECPAM
DECPNM
DECTCEM
DevServerModal
Dock
Editor
EmptyPane
FileFinder
GiveFeedback
GoToLine
inline_completion
in_replace
IRM
jupyter
LNM
MarkdownPreview
menu
nested
OutlinePanel
Pane
parent
Picker
ProjectPanel
ProjectSearchBar
Prompt
PromptLibrary
renaming
report_focus
SharedScreen
showing_code_actions
showing_completions
TabSwitcher
TasksModal
Terminal
TextInput
Context Key/values (key_context.set(...)
):
mode
extension
mouse_reporting
mouse_format
screen
I spent the last few days configuring zed, and have found keybind configuration has some room for improvement :) A few notes:
It took a while to get over the initial confusion of what contexts actually are. do they relate to the mere presence of an element? or does it have to have focus? if one context is active does it deactivate others or do they coexist? is there some hierarchical structure to them? how do they relate to actions, given the similar prefixes? how are keybind conflicts resolved?
Here are my conclusions, please correct me if I'm wrong:
context represents the focus location within the cascading hierarchy of graphical elements
the last keybind definition for a key wins
any action can be called from within any context, but not all actions will work from all contexts
when an action for a keybind cannot be applied, it falls back to the previous one
an immediate child of an element can be selected with Parent > Child
One could compare it to the following html and css selectors:
<div class="Global">
<div class="Workspace">
<div class="Pane">
<div class="BufferSearchBar">
<div class="Editor">
<!-- search --> <!-- .Workspace > .Pane > .BufferSearchBar > .Editor -->
</div>
</div>
<div class="Editor">
<!-- buffer --> <!-- .Workspace > .Pane > .Editor -->
</div>
</div>
</div>
</div>
It's possible to apply rules Parent > Child
just like in css, but this is hard to use when the document structure is unknown. Having a non-direct child selector would probably make things easier to use too (like Workspace > Editor
)
It's possible to specify the same context multiple times, where the last one wins. This can be useful when a command may not succeed to make it fallback to a previous one, see this example:
[{
"context": "Editor && mode == full",
"bindings": {
"f1": "buffer_search::Deploy" // only gets called if "buffer_search::FocusSearch" fails
}
},{
"context": "Editor && mode == full",
"bindings": {
"f1": "buffer_search::FocusSearch" // focus if open, else look for next action
}
}]
Which feels like an anti-pattern, would be nice to have a way of specifying fallback commands. This is how micro deals with it: "Tab": "Autocomplete|IndentSelection|InsertTab"
.
What I would like to see:
A few observations:
Editor && mode == full
vs Editor && mode == auto_height
actually has nothing to do with multibuffers.
From my testing, it looks like Editor
includes everything you can type in - from menu and find panel to rename box in sidebar.
mode == full
seems to include any tab (?), including search tabmode == auto_height
every other typable element?ProjectSearchView
no matter what the name implies couldn't apply any keybindWorkspace
is always active? same as global thenAnd some additional suggestions:
Hi @neunato. You seem to know how the whole context system works, and I had multiple questions about that. Could you answer them please? Here:
A primer:
Contextes:
AssistantPanel BufferSearchBar ChannelModal CollabPanel ContextEditor Dock Editor EmptyPane FileFinder Markdown OutlinePanel Pane Picker ProjectPanel ProjectSearchBar ProjectSearchView PromptLibrary TabSwitcher Terminal VimControl Workspace
vim_mode
values :insert normal operator replace visual waiting
Context operators:
&&
!=
==
>
()
!
||
Variables:
auto_height editing full inline_completion in_replace jupyter menu mode not_editing renaming showing_code_actions showing_completions vim_mode vim_operator
I grepped from keymaps, not Rust.
I feel like these variables should be documented somewhere! I had to use the editing
variable here to bind a/A/r within the ProjectPanel. Without this, I wouldn't be able to type these letters in the input box.
{
"context": "ProjectPanel && !editing",
"bindings": {
"space e": "workspace::ToggleLeftDock",
"a": "project_panel::NewFile",
"A": "project_panel::NewDirectory",
"r": "project_panel::Rename",
"d": "project_panel::Delete"
}
}
]
Yep. We could use some better documentation around context for keybindings. Here's a non-exhaustive list of contexts used by the default bindings.
- (no context) == global shortcut
Workspace
Pane
ProjectPanel
(left files sidebar)
ProjectPanel && not_editing
Editor
Editor && mode == full
Editor && mode == full && inline_completion
Editor && mode == full && !jupyter
Editor && mode == full && inline_completion
Editor && !inline_completion
Editor && mode == auto_height
Editor && renaming
Editor && showing_completions
Editor && inline_completion && !showing_completions
Editor && showing_code_actions
Editor && (showing_code_actions || showing_completions)
ContextEditor > Editor
Picker > Editor
BufferSearchBar
BufferSearchBar && in_replace
BufferSearchBar && !in_replace > Editor
ProjectSearchBar
ProjectSearchBar > Editor
ProjectSearchBar && in_replace > Editor
ProjectSearchBar && !in_replace
ProjectSearchView
Dock
AssistantPanel
PromptLibrary
Terminal
OutlinePanel
CollabPanel
CollabPanel && not_editing
(CollabPanel && editing) > Editor
ChannelModal
ChannelModal > Picker > Editor
TabSwitcher
(ctrl-tab / ctrl-shift modal)FileFinder
(cmd+p modal "Search project files")Markdown
(markdown preview window)EmptyPane || SharedScreen
Plus a bunch more in vim.json
What is mode ?
Editor
mode
can be eitherfull
orauto_height
. Full is the normal editor, I believeauto_height
is during the find in files where you can directly edit the results (in a height constrained space).What context when no file are opens ?
If you have no panels in focus, no files open
Workspace
or global (no context) will apply.What is Markdown?
Markdown preview.
How to know the current context ? How to know available shortcut in a context ? Doom Emacs has a bottom drawer showing next shortcut.
This would be a useful enhancement.
Apparently, this document is outdated.
I tried Search
and BufferSearch
. Finally, BufferSearchBar
context works for me.
Yes, same for Assistant
, I belive now it is AssistantPanel
I am confused, I thought that this would work for file finder, project finder and buffer list but it's not
{
"context": "menu",
"bindings": {
"ctrl-j": "menu::SelectNext",
"ctrl-k": "menu::SelectPrev"
}
}
It works if I remove context. I also tried ProjectSearchBar, BufferSearchBar etc... no context work. I often times am confused about what to insert here and what are the possibilities.
This really need a better documentation because it's most likely a deal breaker compared to the way we can configure Neovim
I have setup some keybinds like this : Editor && !AssistantPanel && (vim_mode == normal || vim_mode == visual)
However, when I open the assitant panel, it stills uses this keyind, so the !AssistantPanel does not seems to take effect.
Is it because of cascading rules ?
Is there a way to have keyinds disabled in the assistant panel ?
Would be super useful if there was a command that would show/print what context you are currently in to make it easier to create your keymaps.
Would be super useful if there was a command that would show/print what context you are currently in to make it easier to create your keymaps.
Yeah, we could certainly do better here, but I recommend you look at the existing Contexts in default-linux.json or default-macos.json as a reference.
Because sometimes in addition to knowing your current context (e.g. Root > Workspace > Pane > Editor
) you may want to exclude certain context for mapping. For example :
https://github.com/zed-industries/zed/blob/b83b42b9beba389c3b77eef5f0323b68eff9ea5a/assets/keymaps/default-macos.json#L446-L452
There has been discussion about building a debug window (like debug: open syntax tree view
does for tree-sitter) which displays your GPUI context for keymapping or your syntax highlighting context for themes.
There has been discussion about building a debug window (like debug: open syntax tree view does for tree-sitter) which displays your GPUI context for keymapping or your syntax highlighting context for themes.
that would be super awesome. confusion about contexts and why some keybindings are not working / being overridden has been by far my biggest pain point in adopting Zed (although that isn't saying much - it's been wonderful with almost everything else).
IMO it would be ideal if we could have a command like debug: key bindings
which shows the name of the current context, a list of all active context
values from your custom keybindings + the default ones, and then a list of all values per unique binding / context tuple, e.g.
"currentContext": "ContextC",
"activeContexts": ["ContextB", "ContextC"]
"keys": {
"ctrl-g": {
"activeBindings": [
"ContextB": "bar",
"ContextC": "baz"
]
}
}
if the last one is the winner, then that makes it easy to figure out why it's doing baz
instead of bar
/ how overrides work.
you can also see ContextA
is not active at all, which helps explain issues with adding a binding under the wrong context.
I agree with Andrew. There needs to be some debuggability here. I am trying to remove the cmd-r (which toggles the right dock) with "cmd-r": null
and adding that to Workspace and Editor did not help.
It'd be a huge huge win to have a way to debug keybindings. Specifically, it would have two bits of functionality:
That would make it much easier to rebind keys to the hotkeys that I want. Right now, the context and the keybinding actions are really undiscoverable.
@Apromixately I've seen null
not working a lot of the time, so I sometimes instead remap to an action that seems to be a no-op, while still being a command. I found "workspace::Unfollow"
to suit this purpose - I'm not actually sure what it's intended to do.
One thing I'm finding surprising, it seems that "context": "Editor",
has higher precedence than "context": "Editor && mode == auto_height",
, so the precedence logic seems to respect "nearer" context (so Editor beats Workspace), but it doesn't respect "specificity" precedence, so "mode == auto_height" either randomly beats or has lower precedence than having no mode filter (haven't figured out if random precedence or lower precedence). Intuitively, more specific contexts should beat less specific contexts.
I'm trying to redo how assist/inline assist get opened and submitted, so I had a cmd-enter
binding in context: Editor
and overwrote it in context: Editor && mode == auto_height
to override the value while in the inline_assist window, but that didn't actually work.
I had to move the cmd-enter binding to context: Editor && mode == full
to eliminate the conflict.
Check for existing issues
Describe the feature
Hi,
Reading https://github.com/zed-industries/zed/blob/main/docs/src/key-bindings.md, I don't find a proper documentation of
"context"
query in keymaps.json. Could you document this ?My questions:
mode
?Markdown
?Regards, Étienne
If applicable, add mockups / screenshots to help present your vision of the feature
No response