which_key.rs

 1//! Which-key support for Zed.
 2
 3mod which_key_modal;
 4mod which_key_settings;
 5
 6use gpui::{App, Keystroke};
 7use settings::Settings;
 8use std::{sync::LazyLock, time::Duration};
 9use util::ResultExt;
10use which_key_modal::WhichKeyModal;
11use which_key_settings::WhichKeySettings;
12use workspace::Workspace;
13
14pub fn init(cx: &mut App) {
15    WhichKeySettings::register(cx);
16
17    cx.observe_new(|_: &mut Workspace, window, cx| {
18        let Some(window) = window else {
19            return;
20        };
21        let mut timer = None;
22        cx.observe_pending_input(window, move |workspace, window, cx| {
23            if window.pending_input_keystrokes().is_none() {
24                if let Some(modal) = workspace.active_modal::<WhichKeyModal>(cx) {
25                    modal.update(cx, |modal, cx| modal.dismiss(cx));
26                };
27                timer.take();
28                return;
29            }
30
31            let which_key_settings = WhichKeySettings::get_global(cx);
32            if !which_key_settings.enabled {
33                return;
34            }
35
36            let delay_ms = which_key_settings.delay_ms;
37
38            timer.replace(cx.spawn_in(window, async move |workspace_handle, cx| {
39                cx.background_executor()
40                    .timer(Duration::from_millis(delay_ms))
41                    .await;
42                workspace_handle
43                    .update_in(cx, |workspace, window, cx| {
44                        if workspace.active_modal::<WhichKeyModal>(cx).is_some() {
45                            return;
46                        };
47
48                        workspace.toggle_modal(window, cx, |window, cx| {
49                            WhichKeyModal::new(workspace_handle.clone(), window, cx)
50                        });
51                    })
52                    .log_err();
53            }));
54        })
55        .detach();
56    })
57    .detach();
58}
59
60// Hard-coded list of keystrokes to filter out from which-key display
61pub static FILTERED_KEYSTROKES: LazyLock<Vec<Vec<Keystroke>>> = LazyLock::new(|| {
62    [
63        // Modifiers on normal vim commands
64        "g h",
65        "g j",
66        "g k",
67        "g l",
68        "g $",
69        "g ^",
70        // Duplicate keys with "ctrl" held, e.g. "ctrl-w ctrl-a" is duplicate of "ctrl-w a"
71        "ctrl-w ctrl-a",
72        "ctrl-w ctrl-c",
73        "ctrl-w ctrl-h",
74        "ctrl-w ctrl-j",
75        "ctrl-w ctrl-k",
76        "ctrl-w ctrl-l",
77        "ctrl-w ctrl-n",
78        "ctrl-w ctrl-o",
79        "ctrl-w ctrl-p",
80        "ctrl-w ctrl-q",
81        "ctrl-w ctrl-s",
82        "ctrl-w ctrl-v",
83        "ctrl-w ctrl-w",
84        "ctrl-w ctrl-]",
85        "ctrl-w ctrl-shift-w",
86        "ctrl-w ctrl-g t",
87        "ctrl-w ctrl-g shift-t",
88    ]
89    .iter()
90    .filter_map(|s| {
91        let keystrokes: Result<Vec<_>, _> = s
92            .split(' ')
93            .map(|keystroke_str| Keystroke::parse(keystroke_str))
94            .collect();
95        keystrokes.ok()
96    })
97    .collect()
98});