diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2016-12-29 17:58:00 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2016-12-29 17:58:00 +0100 |
| commit | eda4ab0e8e2f97225e4c0470318e9427e09bbfb9 (patch) | |
| tree | bd988ad26c4dd7825cb5ab7635d16c81c82b6edb | |
| parent | a8116c57341f87b293d35ef7e1d140ceb01ed8b1 (diff) | |
| download | vis-eda4ab0e8e2f97225e4c0470318e9427e09bbfb9.tar.gz vis-eda4ab0e8e2f97225e4c0470318e9427e09bbfb9.tar.xz | |
vis: cleanup key action lifetime management
| -rw-r--r-- | vis-core.h | 1 | ||||
| -rw-r--r-- | vis-lua.c | 18 | ||||
| -rw-r--r-- | vis-modes.c | 45 | ||||
| -rw-r--r-- | vis.c | 4 | ||||
| -rw-r--r-- | vis.h | 17 |
5 files changed, 59 insertions, 26 deletions
@@ -184,6 +184,7 @@ struct Vis { volatile sig_atomic_t terminate; /* need to terminate we were being killed by SIGTERM */ sigjmp_buf sigbus_jmpbuf; /* used to jump back to a known good state in the mainloop after (SIGBUS) */ Map *actions; /* registered editor actions / special keys commands */ + Array actions_user; /* dynamically allocated editor actions */ lua_State *lua; /* lua context used for syntax highligthing */ VisEvent *event; Array motions; @@ -665,23 +665,14 @@ static int keymap(lua_State *L, Vis *vis, Win *win) { const char *key = luaL_checkstring(L, 3); const void *func = func_ref_new(L, 4); const char *help = luaL_optstring(L, 5, NULL); - KeyBinding *binding = vis_binding_new(vis); - if (!binding) - goto err; - KeyAction *action = calloc(1, sizeof *action); + KeyBinding *binding = NULL; + KeyAction *action = vis_action_new(vis, NULL, help, keymapping, (Arg){ .v = func }); if (!action) goto err; + if (!(binding = vis_binding_new(vis))) + goto err; binding->action = action; - *action = (KeyAction){ - .name = NULL, - .help = help ? strdup(help) : help, - .func = keymapping, - .arg = (const Arg){ - .v = func, - }, - }; - if (win) { if (!vis_window_mode_map(win, mode, true, key, binding)) goto err; @@ -694,6 +685,7 @@ static int keymap(lua_State *L, Vis *vis, Win *win) { return 1; err: vis_binding_free(vis, binding); + vis_action_free(vis, action); lua_pushboolean(L, false); return 1; } diff --git a/vis-modes.c b/vis-modes.c index 86c86f0..1fe460d 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -2,6 +2,41 @@ #include "vis-core.h" #include "util.h" +KeyAction *vis_action_new(Vis *vis, const char *name, const char *help, KeyActionFunction *func, Arg arg) { + KeyAction *action = calloc(1, sizeof *action); + if (!action) + return NULL; + if (name && !(action->name = strdup(name))) + goto err; + if (help && !(action->help = strdup(help))) + goto err; + action->func = func; + action->arg = arg; + if (!array_add_ptr(&vis->actions_user, action)) + goto err; + return action; +err: + free((char*)action->name); + free((char*)action->help); + free(action); + return NULL; +} + +void vis_action_free(Vis *vis, KeyAction *action) { + if (!action) + return; + size_t len = array_length(&vis->actions_user); + for (size_t i = 0; i < len; i++) { + if (action == array_get_ptr(&vis->actions_user, i)) { + free((char*)action->name); + free((char*)action->help); + free(action); + array_remove(&vis->actions_user, i); + return; + } + } +} + KeyBinding *vis_binding_new(Vis *vis) { KeyBinding *binding = calloc(1, sizeof *binding); if (binding && array_add_ptr(&vis->bindings, binding)) @@ -18,15 +53,11 @@ void vis_binding_free(Vis *vis, KeyBinding *binding) { if (binding == array_get_ptr(&vis->bindings, i)) { if (binding->alias) free((char*)binding->alias); - const KeyAction *action = binding->action; - if (action) { - free((char*)action->name); - free((char*)action->help); - free((KeyAction*)action); - } + if (binding->action && !binding->action->name) + vis_action_free(vis, (KeyAction*)binding->action); free(binding); array_remove(&vis->bindings, i); - break; + return; } } } @@ -511,6 +511,7 @@ Vis *vis_new(Ui *ui, VisEvent *event) { array_init(&vis->motions); array_init(&vis->textobjects); array_init(&vis->bindings); + array_init(&vis->actions_user); action_reset(&vis->action); buffer_init(&vis->input_queue); vis->keys = &vis->input_queue; @@ -574,6 +575,9 @@ void vis_free(Vis *vis) { while (array_length(&vis->bindings)) vis_binding_free(vis, array_get_ptr(&vis->bindings, 0)); array_release(&vis->bindings); + while (array_length(&vis->actions_user)) + vis_action_free(vis, array_get_ptr(&vis->actions_user, 0)); + array_release(&vis->actions_user); free(vis->shell); free(vis); } @@ -53,15 +53,17 @@ typedef union { /* various types of arguments passed to key action functions */ void (*f)(Vis*); } Arg; +/* action handling function, keys refers to the next characters found in the input queue + * (an empty string "" indicates an empty queue). The return value of func has to point to + * the first non consumed key. Returning NULL indicates that not enough keys were available + * to complete the action. In this case the function will be called again when more input + * becomes available */ +typedef const char *KeyActionFunction(Vis*, const char *keys, const Arg*); + typedef struct { /* a KeyAction can be bound to a key binding */ const char *name; /* aliases can refer to this action by means of a pseudo key <name> */ const char *help; /* short (one line) human readable description, displayed by :help */ - /* action handling function, keys refers to the next characters found in the input queue - * (an empty string "" indicates an empty queue). The return value of func has to point to - * the first non consumed key. Returning NULL indicates that not enough keys were available - * to complete the action. In this case the function will be called again when more input - * becomes available */ - const char* (*func)(Vis*, const char *keys, const Arg*); + KeyActionFunction *func; /* action implementation */ Arg arg; /* additional arguments which will be passed as to func */ } KeyAction; @@ -175,6 +177,9 @@ bool vis_window_mode_map(Win*, enum VisMode, bool force, const char *key, const /* in the specified mode: unmap a given key, fails if the key is not currently mapped */ bool vis_mode_unmap(Vis*, enum VisMode, const char *key); bool vis_window_mode_unmap(Win*, enum VisMode, const char *key); + +KeyAction *vis_action_new(Vis*, const char *name, const char *help, KeyActionFunction*, Arg); +void vis_action_free(Vis*, KeyAction*); /* associates the special pseudo key <keyaction->name> with the given key action. * after successfull registration the pseudo key can be used key binding aliases */ bool vis_action_register(Vis*, const KeyAction*); |
