aboutsummaryrefslogtreecommitdiff
path: root/config/which_key_plugin.c
blob: 8d4fb507d5c57631cdb38b732eecd4042f3f995f (plain)
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