1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#include "ecex.h"
#define WK_HOOK_NAME "which-key"
#define WK_SLOT_ENABLED "enabled"
typedef struct which_key_state {
ecex_plugin_t *plugin;
int showing;
} which_key_state_t;
static int which_key_enabled(ecex_plugin_t *plugin) {
return ecex_plugin_slot_i32_get_scalar(plugin, WK_SLOT_ENABLED, 1) != 0;
}
static int cmd_which_key_toggle(ecex_t *ed) {
ecex_plugin_t *plugin = ecex_plugin_find(ed, "which-key");
if (!plugin) return -1;
int enabled = !which_key_enabled(plugin);
ecex_plugin_slot_i32_set_scalar(plugin, WK_SLOT_ENABLED, enabled);
ecex_message(ed, enabled ? "which-key enabled" : "which-key disabled");
return 0;
}
static void which_key_prefix_hook(ecex_t *ed, const char *prefix, int event, void *userdata) {
which_key_state_t *state = (which_key_state_t *)userdata;
char line[1024];
if (!ed || !state || !state->plugin) return;
if (!which_key_enabled(state->plugin)) {
if (state->showing) ecex_message(ed, "");
state->showing = 0;
return;
}
if (event == ECEX_PREFIX_HOOK_CANCEL ||
event == ECEX_PREFIX_HOOK_FINISH ||
event == ECEX_PREFIX_HOOK_UNDEFINED) {
if (state->showing) ecex_message(ed, "");
state->showing = 0;
return;
}
if (event != ECEX_PREFIX_HOOK_BEGIN && event != ECEX_PREFIX_HOOK_UPDATE) {
return;
}
if (ecex_describe_key_prefix(ed, ecex_current_buffer(ed), prefix, line, sizeof(line), 24) >= 0) {
ecex_message(ed, line);
state->showing = 1;
}
}
static void which_key_command_hook(ecex_t *ed,
const char *command,
int event,
int result,
void *userdata) {
(void)command;
(void)result;
which_key_state_t *state = (which_key_state_t *)userdata;
if (event == ECEX_COMMAND_HOOK_AFTER && state && state->showing) {
ecex_plugin_t *plugin = state->plugin ? state->plugin : ecex_plugin_find(ed, "which-key");
if (plugin) {
ecex_message(ed, "");
state->showing = 0;
}
}
}
static void which_key_free(void *userdata) {
which_key_state_t *state = (which_key_state_t *)userdata;
if (!state) return;
ecex_plugin_object_free(state->plugin, state);
}
ECEX_PLUGIN_BEGIN(ecex_which_key_plugin, "which-key")
if (ecex_plugin_slot_i32_get_scalar(plugin, WK_SLOT_ENABLED, -1) < 0) {
ecex_plugin_slot_i32_set_scalar(plugin, WK_SLOT_ENABLED, 1);
}
ECEX_CONFIG_COMMAND("which-key-toggle", cmd_which_key_toggle);
which_key_state_t *state = ecex_plugin_object_calloc(plugin, "state", 1, sizeof(*state));
if (!state) return -1;
state->plugin = plugin;
if (ecex_add_command_hook(ed, WK_HOOK_NAME, which_key_command_hook, state, 0) != 0) {
ecex_plugin_object_free(plugin, state);
return -1;
}
if (ecex_add_prefix_hook(ed, WK_HOOK_NAME, which_key_prefix_hook, state, which_key_free) != 0) {
ecex_remove_command_hook(ed, WK_HOOK_NAME);
ecex_plugin_object_free(plugin, state);
return -1;
}
return 0;
ECEX_PLUGIN_END
#ifndef ECEX_NO_STANDALONE_CONFIG
ECEX_CONFIG_BEGIN
ECEX_CONFIG_INCLUDE(ecex_which_key_plugin);
ECEX_CONFIG_END
#endif
|