From: Daniel Carl Date: Sat, 20 Oct 2012 17:51:59 +0000 (+0200) Subject: Allow setting and removing keybindings from string. X-Git-Url: https://git.owens.tech/assets/favicon.png/assets/favicon.png/git?a=commitdiff_plain;h=7ca4178278b143e04541b7c946e07ddaeaf7b210;p=vimb.git Allow setting and removing keybindings from string. --- diff --git a/src/command.c b/src/command.c index 2ab0ab6..2764bd2 100644 --- a/src/command.c +++ b/src/command.c @@ -39,6 +39,11 @@ void command_init() } } +gboolean command_exists(const gchar* name) +{ + return g_hash_table_contains(vp.behave.commands, name); +} + gboolean command_run(const gchar* name, const gchar* param) { CommandInfo* c = NULL; diff --git a/src/command.h b/src/command.h index 5cd3942..27dd3f9 100644 --- a/src/command.h +++ b/src/command.h @@ -14,6 +14,7 @@ typedef struct { void command_init(void); +gboolean command_exists(const gchar* name); gboolean command_run(const gchar* name, const gchar* param); #endif /* end of include guard: COMMAND_H */ diff --git a/src/keybind.c b/src/keybind.c index 729b2ce..0b5d30a 100644 --- a/src/keybind.c +++ b/src/keybind.c @@ -6,6 +6,8 @@ static GSList* keys = NULL; static GString* modkeys = NULL; static GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval); +static void keybind_str_to_keybind(gchar* str, Keybind* key); +static guint keybind_str_to_modmask(const gchar* str); static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* event); @@ -15,34 +17,62 @@ void keybind_init(void) g_signal_connect(G_OBJECT(vp.gui.window), "key-press-event", G_CALLBACK(keybind_keypress_callback), NULL); } -void keybind_add(int mode, guint modkey, guint modmask, guint keyval, const gchar* command) +void keybind_add_from_string(const gchar* str, const Mode mode) { - Keybind* keybind = g_new0(Keybind, 1); + if (str == NULL || *str == '\0') { + return; + } + gchar* line = g_strdup(str); + g_strstrip(line); + + /* split into keybinding and command */ + char **string = g_strsplit(line, " ", 2); + + guint len = g_strv_length(string); + if (len == 2 && command_exists(string[1])) { + Keybind* keybind = g_new0(Keybind, 1); + keybind->mode = mode; + keybind->command = g_strdup(string[1]); - keybind->mode = mode; - keybind->modkey = modkey; - keybind->modmask = modmask; - keybind->keyval = keyval; - keybind->command = g_strdup(command); + keybind_str_to_keybind(string[0], keybind); - keys = g_slist_prepend(keys, keybind); + /* add the keybinding to the list */ + keys = g_slist_prepend(keys, keybind); - /* save the modkey also in the modkey string */ - if (modkey) { - g_string_append_c(modkeys, modkey); + /* save the modkey also in the modkey string */ + if (keybind->modkey) { + g_string_append_c(modkeys, keybind->modkey); + } + } else { + fprintf(stderr, "could not add keybind from '%s'", line); } + + g_strfreev(string); + g_free(line); } -void keybind_remove(int mode, guint modkey, guint modmask, guint keyval) +void keybind_remove_from_string(const gchar* str, const Mode mode) { - GSList* link = keybind_find(mode, modkey, modmask, keyval); + gchar* line = NULL; + Keybind keybind = {0}; + + if (str == NULL || *str == '\0') { + return; + } + line = g_strdup(str); + g_strstrip(line); + + /* fill the keybind with data from given string */ + keybind_str_to_keybind(line, &keybind); + + GSList* link = keybind_find(keybind.mode, keybind.modkey, keybind.modmask, keybind.keyval); if (link) { keys = g_slist_delete_link(keys, link); } /* TODO remove eventually no more used modkeys */ } -GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval) +static GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval) { GSList* link; for (link = keys; link != NULL; link = link->next) { @@ -59,6 +89,47 @@ GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval) return NULL; } +static void keybind_str_to_keybind(gchar* str, Keybind* keybind) +{ + gchar** string = NULL; + guint len = 0; + + if (str == NULL || *str == '\0') { + return; + } + g_strstrip(str); + + /* [modkey[]]keyval */ + string = g_strsplit_set(str, "<>", 3); + len = g_strv_length(string); + + if (len == 1) { /* no modmask set */ + if (strlen(string[0]) == 2) { + keybind->modkey = string[0][0]; + keybind->keyval = string[0][1]; + } else { + keybind->keyval = string[0][0]; + } + } else { /* contains modmask */ + keybind->modkey = (string[0][0] != '\0') ? string[0][0] : 0; + keybind->modmask = keybind_str_to_modmask(string[1]); + keybind->keyval = string[2][0]; + } + g_strfreev(string); +} + +static guint keybind_str_to_modmask(const gchar* str) +{ + if (!g_ascii_strcasecmp(str, "ctrl")) { + return GDK_CONTROL_MASK; + } + if (!g_ascii_strcasecmp(str, "shift")) { + return GDK_SHIFT_MASK; + } + + return 0; +} + static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* event) { GdkModifierType irrelevant; diff --git a/src/keybind.h b/src/keybind.h index 6866dab..021f0de 100644 --- a/src/keybind.h +++ b/src/keybind.h @@ -21,7 +21,7 @@ typedef struct { } Keybind; void keybind_init(void); -void keybind_add(int mode, guint modkey, guint modmask, guint keyval, const gchar* command); -void keybind_remove(int mode, guint modkey, guint modmask, guint keyval); +void keybind_add_from_string(const gchar* str, const Mode mode); +void keybind_remove_from_string(const gchar* str, const Mode mode); #endif /* end of include guard: KEYBIND_H */ diff --git a/src/main.c b/src/main.c index 9ff9776..f8a9089 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include "config.h" #include "main.h" +#include "util.h" #include "command.h" #include "keybind.h" @@ -20,6 +21,7 @@ static gboolean vp_process_input(const char* input); static void vp_print_version(void); static void vp_init(void); static void vp_init_gui(void); +static void vp_init_files(void); static void vp_set_widget_font(GtkWidget* widget, const gchar* font_definition, const gchar* bg_color, const gchar* fg_color); static void vp_setup_settings(void); static void vp_setup_signals(void); @@ -210,12 +212,20 @@ void vp_scroll(const Arg* arg) } void vp_close_browser(const Arg* arg) +{ + vp_clean_up(); + gtk_main_quit(); +} + +void vp_clean_up(void) { if (vp.behave.commands) { g_hash_table_destroy(vp.behave.commands); vp.behave.commands = NULL; } - gtk_main_quit(); + for (int i = FILES_FIRST; i < FILES_LAST; i++) { + g_free(vp.files[i]); + } } void vp_view_source(const Arg* arg) @@ -350,32 +360,34 @@ static void vp_init(void) vp_init_gui(); /* initialize the commands hash map */ command_init(); + /* initialize the config files */ + vp_init_files(); /* initialize the keybindings */ keybind_init(); /* TODO read the key bindings from config file */ - keybind_add(VP_MODE_NORMAL, GDK_g, 0, GDK_f, "source"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_colon, "input"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_o, "inputopen"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_O, "inputopencurrent"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_d, "quit"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_o, "back"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_i, "forward"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_r, "reload"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_R, "reload!"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_c, "stop"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_f, "pagedown"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_b, "pageup"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_d, "halfpagedown"); - keybind_add(VP_MODE_NORMAL, 0, GDK_CONTROL_MASK, GDK_u, "halfpageup"); - keybind_add(VP_MODE_NORMAL, GDK_g, 0, GDK_g, "jumptop"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_G, "jumpbottom"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_0, "jumpleft"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_dollar, "jumpright"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_h, "scrollleft"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_l, "scrollright"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_k, "scrollup"); - keybind_add(VP_MODE_NORMAL, 0, 0, GDK_j, "scrolldown"); + keybind_add_from_string("gf source", VP_MODE_NORMAL); + keybind_add_from_string(": input", VP_MODE_NORMAL); + keybind_add_from_string("o inputopen", VP_MODE_NORMAL); + keybind_add_from_string("O inputopencurrent", VP_MODE_NORMAL); + keybind_add_from_string("d quit", VP_MODE_NORMAL); + keybind_add_from_string("o back", VP_MODE_NORMAL); + keybind_add_from_string("i forward", VP_MODE_NORMAL); + keybind_add_from_string("r reload", VP_MODE_NORMAL); + keybind_add_from_string("R reload!", VP_MODE_NORMAL); + keybind_add_from_string("c stop", VP_MODE_NORMAL); + keybind_add_from_string("f pagedown", VP_MODE_NORMAL); + keybind_add_from_string("b pageup", VP_MODE_NORMAL); + keybind_add_from_string("d halfpagedown", VP_MODE_NORMAL); + keybind_add_from_string("u halfpageup", VP_MODE_NORMAL); + keybind_add_from_string("gg jumptop", VP_MODE_NORMAL); + keybind_add_from_string("G jumpbottom", VP_MODE_NORMAL); + keybind_add_from_string("0 jumpleft", VP_MODE_NORMAL); + keybind_add_from_string("$ jumpright", VP_MODE_NORMAL); + keybind_add_from_string("h scrollleft", VP_MODE_NORMAL); + keybind_add_from_string("l scrollright", VP_MODE_NORMAL); + keybind_add_from_string("k scrollup", VP_MODE_NORMAL); + keybind_add_from_string("j scrolldown", VP_MODE_NORMAL); } static void vp_init_gui(void) @@ -456,6 +468,16 @@ static void vp_init_gui(void) gtk_widget_show_all(gui->window); } +static void vp_init_files(void) +{ + gchar* path = util_get_config_dir(); + + vp.files[FILES_CONFIG] = g_build_filename(path, "config", NULL); + util_create_file_if_not_exists(vp.files[FILES_CONFIG]); + + g_free(path); +} + static void vp_set_widget_font(GtkWidget* widget, const gchar* font_definition, const gchar* bg_color, const gchar* fg_color) { GdkColor fg, bg; diff --git a/src/main.h b/src/main.h index ac11121..692354b 100644 --- a/src/main.h +++ b/src/main.h @@ -72,6 +72,12 @@ typedef enum { VP_MSG_ERROR } MessageType; +enum { + FILES_FIRST = 0, + FILES_CONFIG = 0, + FILES_LAST +}; + /* structs */ typedef struct { gint i; @@ -118,6 +124,7 @@ typedef struct { Gui gui; State state; Behaviour behave; + gchar* files[FILES_LAST]; #if 0 Network net; Ssl ssl; @@ -136,6 +143,7 @@ void vp_echo(const MessageType type, const gchar *message); void vp_navigate(const Arg* arg); void vp_scroll(const Arg* arg); void vp_close_browser(const Arg* arg); +void vp_clean_up(void); void vp_view_source(const Arg* arg); void vp_set_mode(const Arg* arg); void vp_input(const Arg* arg); diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..f274e9c --- /dev/null +++ b/src/util.c @@ -0,0 +1,33 @@ +#include "util.h" +#include +#include + +char* util_get_config_dir(void) +{ + char *path = g_build_filename(g_get_user_config_dir(), PROJECT, NULL); + util_create_dir_if_not_exists(path); + + return path; +} + +char* util_get_cache_dir(void) +{ + char *path = g_build_filename(g_get_user_cache_dir(), PROJECT, NULL); + util_create_dir_if_not_exists(path); + + return path; +} + +void util_create_dir_if_not_exists(const gchar* dirpath) +{ + if (!g_file_test(dirpath, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(dirpath, 0755); + } +} + +void util_create_file_if_not_exists(const char* filename) { + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + FILE* f = fopen(filename, "a"); + fclose(f); + } +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..bc359b6 --- /dev/null +++ b/src/util.h @@ -0,0 +1,9 @@ +#ifndef UTIL_H +#define UTIL_H + +char* util_get_config_dir(void); +char* util_get_cache_dir(void); +void util_create_dir_if_not_exists(const char* dirpath); +void util_create_file_if_not_exists(const char* filename); + +#endif /* end of include guard: UTIL_H */