From 74d2348558767c1d22d6fd68b38e6fae8621a083 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Sun, 24 May 2020 15:32:20 +0200 Subject: [PATCH] Allowing editing of key bindings --- include/my_ncurses.h | 1 + src/builtin/builtin_bindkey.c | 73 +++++++++++++++++++++++++++++++---- src/main.c | 6 ++- src/my_ncurses/string_utils.c | 12 ++++++ 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/include/my_ncurses.h b/include/my_ncurses.h index f2109ae..8cac82c 100644 --- a/include/my_ncurses.h +++ b/include/my_ncurses.h @@ -43,6 +43,7 @@ void my_getcuryx(int *y, int *x); void my_getmaxyx(int *y, int *x); int my_getch(void); const char *my_unctrl(int c); +int my_parsechar(const char *c); void my_addstr(my_window *window, const char *str); #define my_mvaddstr(window, y, x, str) (my_move(window, y, x), \ diff --git a/src/builtin/builtin_bindkey.c b/src/builtin/builtin_bindkey.c index 95e60dd..f28440d 100644 --- a/src/builtin/builtin_bindkey.c +++ b/src/builtin/builtin_bindkey.c @@ -14,9 +14,14 @@ void print_binding(binding_t *binding) { - const char *key = my_unctrl(binding->key); - const char *func = NULL; + const char *key; + const char *func = key_functions[0].name; + if (binding->key == -1) { + puts("Unknown key."); + return; + } + key = my_unctrl(binding->key); for (int i = 0; key_functions[i].run; i++) { if (key_functions[i].run == binding->func) { func = key_functions[i].name; @@ -26,25 +31,77 @@ void print_binding(binding_t *binding) printf("%s -> %s\n", key, func); } +static binding_t *get_binding(const char *c, env_t *env) +{ + int key = my_parsechar(c); + + if (key == -1) + return (NULL); + for (int i = 0; env->bindings[i].func; i++) + if (env->bindings[i].key == key) + return (&env->bindings[i]); + return (NULL); +} + +static void new_binding(const char *c, int (*func)(int, buffer_t *, env_t *), env_t *env) +{ + int key = my_parsechar(c); + int size = 0; + + if (env->bindings) + while (env->bindings[size++].func); + if (key == -1) { + printf("Unknown key: %s\n", c); + return; + } + env->bindings = realloc(env->bindings, (size + 1) * sizeof(binding_t)); + env->bindings[size - 1].key = key; + env->bindings[size - 1].func = func; + env->bindings[size].func = NULL; +} + +static void set_binding(const char *c, const char *cmd, env_t *env) +{ + binding_t *binding = get_binding(c, env); + int (*func)(int, buffer_t *, env_t *) = NULL; + + for (int i = 0; key_functions[i].run; i++) { + if (!strcmp(cmd, key_functions[i].name)) { + func = key_functions[i].run; + break; + } + } + if (!func) { + printf("No command found with the name %s\n", cmd); + return; + } + if (binding) + binding->func = func; + else + new_binding(c, func, env); +} + int builtin_bindkey(char **argv, env_t *env) { binding_t *tmp; + binding_t new_binding = {.key = 0, .func = NULL}; if (!argv[1]) { - if (!env->bindings) - return (0); - for (int i = 0; env->bindings[i].func; i++) + for (int i = 0; env->bindings && env->bindings[i].func; i++) print_binding(&env->bindings[i]); } else if (!strcmp(argv[1], "-l")) { for (int i = 0; key_functions[i].name; i++) puts(key_functions[i].name); } else if (!argv[2]) { - // for (tmp = env->bindings; tmp && tmp->key != ) + tmp = get_binding(argv[1], env); + if (!tmp) { + new_binding.key = my_parsechar(argv[1]); + tmp = &new_binding; + } print_binding(tmp); } else if (!argv[3]) { - + set_binding(argv[1], argv[2], env); } else puts("Invalid usage of bindkey."); - free(argv); return (0); } \ No newline at end of file diff --git a/src/main.c b/src/main.c index b4bab38..be7d890 100644 --- a/src/main.c +++ b/src/main.c @@ -18,10 +18,11 @@ env_t *create_env(char **env) { env_t *envt = malloc(sizeof(*envt)); char **envcp = malloc(sizeof(char *) * (env_get_length(env) + 1)); + int i; if (!env || !envcp) return (NULL); - for (int i = 0; env[i]; i++) + for (i = 0; env[i]; i++) envcp[i] = strdup(env[i]); envcp[env_get_length(env)] = NULL; envt->env = envcp; @@ -29,8 +30,9 @@ env_t *create_env(char **env) envt->history = NULL; envt->bindings = malloc(get_emacs_bindings_size()); if (envt->bindings) { - for (int i = 0; emacs_bindings[i].func; i++) + for (i = 0; emacs_bindings[i].func; i++) envt->bindings[i] = emacs_bindings[i]; + envt->bindings[i].func = NULL; } envt->window = NULL; envt->alias = NULL; diff --git a/src/my_ncurses/string_utils.c b/src/my_ncurses/string_utils.c index a7f76c3..abb577b 100644 --- a/src/my_ncurses/string_utils.c +++ b/src/my_ncurses/string_utils.c @@ -9,6 +9,7 @@ #include #include #include +#include #include void my_addstr(my_window *window, const char *str) @@ -49,6 +50,17 @@ const char *my_unctrl(int c) return (unctrl(c)); } +int my_parsechar(const char *c) +{ + if (!strcmp(c, "^?")) + return (KEY_DC); + if (c[0] == '^' && c[1] == '[') + return (CSI(c[2] | c[3] << 8u)); + if (c[1]) + return (-1); + return (c[0]); +} + void my_getmaxyx(int *y, int *x) { struct winsize size;