From: Daniel Carl Date: Sun, 24 Mar 2013 14:38:00 +0000 (+0100) Subject: Merged url_history and history together. X-Git-Url: https://git.owens.tech/dummy.html/dummy.html/git?a=commitdiff_plain;h=6e03f99eb55c6357a0cf5e991281c5512091adac;p=vimb.git Merged url_history and history together. The history mechanism can now handle different types of history and persist the items into different files. --- diff --git a/doc/vimb.1.txt b/doc/vimb.1.txt index 3f4fac8..39f51bf 100644 --- a/doc/vimb.1.txt +++ b/doc/vimb.1.txt @@ -320,6 +320,11 @@ Holds the URI of the last closed browser window. .RS This file holds the history of unique opened URIs. .RE +.I $XDG_CONFIG_HOME/PROJECT/command +.RS +This file holds the history of commands and search queries performed via input +box. +.RE .I $XDG_CONFIG_HOME/PROJECT/scripts.js .RS This file can be used to run user scripts, that are injected into every paged diff --git a/src/command.c b/src/command.c index a77d2bb..f1368fc 100644 --- a/src/command.c +++ b/src/command.c @@ -527,7 +527,7 @@ gboolean command_history(const Arg* arg) { const int count = vb.state.count ? vb.state.count : 1; const gint step = count * (arg->i == VB_SEARCH_BACKWARD ? -1 : 1); - const char* entry = history_get(step); + const char* entry = history_get(HISTORY_COMMAND, step); if (!entry) { return FALSE; diff --git a/src/completion.c b/src/completion.c index 6d5797e..7835f45 100644 --- a/src/completion.c +++ b/src/completion.c @@ -19,7 +19,7 @@ #include "completion.h" #include "util.h" -#include "url_history.h" +#include "history.h" extern VbCore vb; @@ -77,24 +77,26 @@ gboolean completion_complete(gboolean back) vb.comps.completions = completion_init_completion( vb.comps.completions, source, (Comp_Func)g_str_has_prefix, &input[5], ":set " ); + g_list_free(source); } else if (!strncmp(input, ":open ", 6)) { - url_history_get_all(&source); + source = history_get_all(HISTORY_URL); vb.comps.completions = completion_init_completion( vb.comps.completions, source, (Comp_Func)util_strcasestr, &input[6], ":open " ); - g_list_free(source); + history_list_free(&source); } else if (!strncmp(input, ":tabopen ", 9)) { - url_history_get_all(&source); + source = history_get_all(HISTORY_URL); vb.comps.completions = completion_init_completion( vb.comps.completions, source, (Comp_Func)util_strcasestr, &input[9], ":tabopen " ); - g_list_free(source); + history_list_free(&source); } else { source = g_hash_table_get_keys(vb.behave.commands); source = g_list_sort(source, (GCompareFunc)g_strcmp0); vb.comps.completions = completion_init_completion( vb.comps.completions, source, (Comp_Func)g_str_has_prefix, &input[1], ":" ); + g_list_free(source); } if (!vb.comps.completions) { diff --git a/src/config.h b/src/config.h index 8cc974f..1467e0b 100644 --- a/src/config.h +++ b/src/config.h @@ -30,8 +30,6 @@ const unsigned int MAXIMUM_HINTS = 500; -const unsigned int COMMAND_HISTORY_SIZE = 30; - const struct { char* command; } default_config[] = { @@ -144,7 +142,7 @@ const struct { {"set ca-bundle=/etc/ssl/certs/ca-certificates.crt"}, {"set home-page=https://github.com/fanglingsu/vimb"}, {"set download-path=/tmp/vimb"}, - {"set history-max-items=500"}, + {"set history-max-items=2000"}, {NULL} }; diff --git a/src/history.c b/src/history.c index e97f30b..4b31317 100644 --- a/src/history.c +++ b/src/history.c @@ -21,25 +21,56 @@ #include "history.h" extern VbCore vb; -extern const unsigned int COMMAND_HISTORY_SIZE; +/* map history types to files */ +static const VbFile file_map[HISTORY_LAST] = { + FILES_COMMAND, + FILES_HISTORY +}; + +static const char* history_get_file_by_type(HistoryType type); +static GList* history_load(const char* file); +static void history_write_to_file(GList* list, const char* file); + + +/** + * Makes all history items unique and force them to fit the maximum history + * size and writes all entries of the different history types to file. + */ void history_cleanup(void) { - g_list_free_full(vb.behave.history, (GDestroyNotify)g_free); + for (HistoryType i = HISTORY_FIRST; i < HISTORY_LAST; i++) { + const char* file = history_get_file_by_type(i); + history_write_to_file(history_load(file), file); + } } -void history_append(const char* line) +/** + * Write a new history entry to the end of history file. + */ +void history_add(HistoryType type, const char* value) { - if (COMMAND_HISTORY_SIZE <= g_list_length(vb.behave.history)) { - /* if list is too long - remove items from beginning */ - GList* first = g_list_first(vb.behave.history); - g_free((char*)first->data); - vb.behave.history = g_list_delete_link(vb.behave.history, first); + const char* file = history_get_file_by_type(type); + FILE* f; + if ((f = fopen(file, "a+"))) { + file_lock_set(fileno(f), F_WRLCK); + + fprintf(f, "%s\n", value); + + file_lock_set(fileno(f), F_UNLCK); + fclose(f); } - vb.behave.history = g_list_append(vb.behave.history, g_strdup(line)); } -const char* history_get(const int step) +/** + * Retrieves all history entries for given history type. + */ +GList* history_get_all(HistoryType type) +{ + return history_load(history_get_file_by_type(type)); +} + +const char* history_get(HistoryType type, int step) { const char* command; @@ -47,11 +78,13 @@ const char* history_get(const int step) if (!vb.state.history_active) { OVERWRITE_STRING(vb.state.history_prefix, GET_TEXT()); + GList* src = history_load(history_get_file_by_type(type)); + /* generate new history list with the matching items */ - for (GList* l = vb.behave.history; l; l = l->next) { - char* entry = g_strdup((char*)l->data); - if (g_str_has_prefix(entry, vb.state.history_prefix)) { - vb.state.history_active = g_list_prepend(vb.state.history_active, entry); + for (GList* l = src; l; l = l->next) { + char* value = (char*)l->data; + if (g_str_has_prefix(value, vb.state.history_prefix)) { + vb.state.history_active = g_list_prepend(vb.state.history_active, g_strdup(value)); } } @@ -71,7 +104,7 @@ const char* history_get(const int step) return command; } -void history_rewind() +void history_rewind(void) { if (vb.state.history_active) { OVERWRITE_STRING(vb.state.history_prefix, NULL); @@ -81,3 +114,88 @@ void history_rewind() vb.state.history_active = NULL; } } + +void history_list_free(GList** list) +{ + if (*list) { + g_list_free_full(*list, (GDestroyNotify)g_free); + *list = NULL; + } +} + +static const char* history_get_file_by_type(HistoryType type) +{ + return vb.files[file_map[type]]; +} + +/** + * Loads history items form file but elemiate duplicates. + */ +static GList* history_load(const char* file) +{ + /* read the history items from file */ + GList* list = NULL; + char buf[512] = {0}; + FILE* f; + + if (!(f = fopen(file, "r"))) { + return list; + } + + file_lock_set(fileno(f), F_WRLCK); + while (fgets(buf, sizeof(buf), f)) { + g_strstrip(buf); + + /* skip empty lines */ + if (!*buf) { + continue; + } + /* if the value is already in history, remove this entry */ + for (GList* l = list; l; l = l->next) { + if (*buf && !g_strcmp0(buf, (char*)l->data)) { + g_free(l->data); + list = g_list_delete_link(list, l); + break; + } + } + + list = g_list_prepend(list, g_strdup(buf)); + } + file_lock_set(fileno(f), F_UNLCK); + fclose(f); + + /* if list is too long - remove items from end (oldest entries) */ + if (vb.config.history_max < g_list_length(list)) { + /* reverse to not use the slow g_list_last */ + list = g_list_reverse(list); + while (vb.config.history_max < g_list_length(list)) { + GList* last = g_list_first(list); + g_free(last->data); + list = g_list_delete_link(list, last); + } + list = g_list_reverse(list); + } + + return list; +} + +/** + * Loads the entries from file, make them unique and write them back to file. + */ +static void history_write_to_file(GList* list, const char* file) +{ + FILE* f; + if ((f = fopen(file, "w"))) { + file_lock_set(fileno(f), F_WRLCK); + + /* overwrite the history file with new unique history items */ + for (GList* link = g_list_reverse(list); link; link = link->next) { + fprintf(f, "%s\n", (char*)link->data); + } + + file_lock_set(fileno(f), F_UNLCK); + fclose(f); + } + + history_list_free(&list); +} diff --git a/src/history.h b/src/history.h index b968ed2..6e618d4 100644 --- a/src/history.h +++ b/src/history.h @@ -20,9 +20,18 @@ #ifndef _HISTORY_H #define _HISTORY_H +typedef enum { + HISTORY_FIRST = 0, + HISTORY_COMMAND = 0, + HISTORY_URL, + HISTORY_LAST +} HistoryType; + void history_cleanup(void); -void history_append(const char* line); -const char* history_get(const int step); -void history_rewind(); +void history_add(HistoryType type, const char* value); +GList* history_get_all(HistoryType type); +const char* history_get(HistoryType type, int step); +void history_rewind(void); +void history_list_free(GList** list); #endif /* end of include guard: _HISTORY_H */ diff --git a/src/main.c b/src/main.c index 938d9c8..7466e5f 100644 --- a/src/main.c +++ b/src/main.c @@ -29,7 +29,6 @@ #include "hints.h" #include "searchengine.h" #include "history.h" -#include "url_history.h" /* variables */ static char **args; @@ -415,7 +414,7 @@ static void vb_webview_load_status_cb(WebKitWebView* view, GParamSpec* pspec) dom_check_auto_insert(); - url_history_add(uri, webkit_web_view_get_title(vb.gui.webview)); + history_add(HISTORY_URL, uri); break; case WEBKIT_LOAD_FAILED: @@ -472,7 +471,7 @@ static void vb_inputbox_activate_cb(GtkEntry *entry) if (hist_save) { /* save the command in history */ - history_append(command); + history_add(HISTORY_COMMAND, command); } g_free(command); } @@ -837,6 +836,9 @@ static void vb_init_files(void) vb.files[FILES_HISTORY] = g_build_filename(path, "history", NULL); util_create_file_if_not_exists(vb.files[FILES_HISTORY]); + vb.files[FILES_COMMAND] = g_build_filename(path, "command", NULL); + util_create_file_if_not_exists(vb.files[FILES_COMMAND]); + vb.files[FILES_SCRIPT] = g_build_filename(path, "scripts.js", NULL); vb.files[FILES_USER_STYLE] = g_build_filename(path, "style.css", NULL); @@ -1007,7 +1009,7 @@ static void vb_destroy_client() setting_cleanup(); keybind_cleanup(); searchengine_cleanup(); - url_history_cleanup(); + history_cleanup(); for (int i = 0; i < FILES_LAST; i++) { g_free(vb.files[i]); diff --git a/src/main.h b/src/main.h index efb5a78..0fb0211 100644 --- a/src/main.h +++ b/src/main.h @@ -182,9 +182,10 @@ typedef enum { FILES_CLOSED, FILES_SCRIPT, FILES_HISTORY, + FILES_COMMAND, FILES_USER_STYLE, FILES_LAST -} VpFile; +} VbFile; typedef enum { TYPE_CHAR, @@ -256,7 +257,6 @@ typedef struct { GSList* keys; GString* modkeys; GSList* searchengines; - GList* history; } Behaviour; typedef struct { @@ -265,7 +265,7 @@ typedef struct { guint max_completion_items; char* home_page; char* download_dir; - guint url_history_max; + guint history_max; } Config; typedef struct { diff --git a/src/setting.c b/src/setting.c index c1dbfc6..8570c00 100644 --- a/src/setting.c +++ b/src/setting.c @@ -677,11 +677,11 @@ static gboolean setting_user_style(const Setting* s, const SettingType type) static gboolean setting_history_max_items(const Setting* s, const SettingType type) { if (type == SETTING_GET) { - setting_print_value(s, &vb.config.url_history_max); + setting_print_value(s, &vb.config.history_max); return TRUE; } - vb.config.url_history_max = s->arg.i; + vb.config.history_max = s->arg.i; return TRUE; } diff --git a/src/url_history.c b/src/url_history.c deleted file mode 100644 index b5ef10f..0000000 --- a/src/url_history.c +++ /dev/null @@ -1,172 +0,0 @@ -/** - * vimb - a webkit based vim like browser. - * - * Copyright (C) 2012-2013 Daniel Carl - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -#include "main.h" -#include "url_history.h" - -extern VbCore vb; -static void url_history_add_unique(GList** list, const char* url, const char* title); -static GList* url_history_load(void); -static void url_history_write_to_file(GList* list); -static void url_history_clear(GList** list); -static void url_history_free(UrlHist* item); - - -void url_history_cleanup(void) -{ - url_history_write_to_file(url_history_load()); -} - -/** - * Write a new history entry to the end of history file. - */ -void url_history_add(const char* uri, const char* title) -{ - FILE* file = fopen(vb.files[FILES_HISTORY], "a+"); - if (file) { - file_lock_set(fileno(file), F_WRLCK); - - char* name = g_shell_quote(title ? title : ""); - char* new = g_strdup_printf("%s %s\n", uri, name); - - fwrite(new, strlen(new), 1, file); - - g_free(name); - g_free(new); - - file_lock_set(fileno(file), F_UNLCK); - fclose(file); - } -} - -/** - * Appends all url history entries form history file to given list. - */ -void url_history_get_all(GList** list) -{ - GList* src = url_history_load(); - - for (GList* link = src; link; link = link->next) { - UrlHist* hi = (UrlHist*)link->data; - /* put only the url in the list - do not allocate new memory */ - *list = g_list_prepend(*list, hi->uri); - } - - *list = g_list_reverse(*list); -} - -/** - * Loads history items form file but elemiate duplicates. - */ -static GList* url_history_load(void) -{ - /* read the history items from file */ - GList* list = NULL; - char buf[512] = {0}; - FILE* file; - - if (!(file = fopen(vb.files[FILES_HISTORY], "r"))) { - return list; - } - - file_lock_set(fileno(file), F_WRLCK); - while (fgets(buf, sizeof(buf), file)) { - char** argv = NULL; - int argc = 0; - if (g_shell_parse_argv(buf, &argc, &argv, NULL)) { - url_history_add_unique(&list, argv[0], argc > 1 ? argv[1] : NULL); - } - g_strfreev(argv); - } - file_lock_set(fileno(file), F_UNLCK); - fclose(file); - - /* if list is too long - remove items from end (oldest entries) */ - while (vb.config.url_history_max < g_list_length(list)) { - GList* last = g_list_last(list); - url_history_free((UrlHist*)last->data); - list = g_list_delete_link(list, last); - } - - return list; -} - -static void url_history_add_unique(GList** list, const char* url, const char* title) -{ - /* if the url is already in history, remove this entry */ - for (GList* link = *list; link; link = link->next) { - UrlHist* hi = (UrlHist*)link->data; - if (!g_strcmp0(url, hi->uri)) { - url_history_free(hi); - *list = g_list_delete_link(*list, link); - break; - } - } - - UrlHist* item = g_new0(UrlHist, 1); - item->uri = g_strdup(url); - item->title = title ? g_strdup(title) : NULL; - - *list = g_list_prepend(*list, item); -} - -/** - * Loads the entries from file, make them unique and write them back to file. - */ -static void url_history_write_to_file(GList* list) -{ - FILE* file = fopen(vb.files[FILES_HISTORY], "w"); - if (file) { - file_lock_set(fileno(file), F_WRLCK); - - /* overwrite the history file with new unique history items */ - for (GList* link = g_list_reverse(list); link; link = link->next) { - UrlHist* item = (UrlHist*)link->data; - - char* title = g_shell_quote(item->title ? item->title : ""); - char* new = g_strdup_printf("%s %s\n", item->uri, title); - - fwrite(new, strlen(new), 1, file); - - g_free(title); - g_free(new); - } - - file_lock_set(fileno(file), F_UNLCK); - fclose(file); - } - url_history_clear(&list); -} - -static void url_history_clear(GList** list) -{ - if (*list) { - g_list_free_full(*list, (GDestroyNotify)url_history_free); - *list = NULL; - } -} - -static void url_history_free(UrlHist* item) -{ - g_free(item->uri); - if (item->title) { - g_free(item->title); - } - g_free(item); -} diff --git a/src/url_history.h b/src/url_history.h deleted file mode 100644 index ee4a159..0000000 --- a/src/url_history.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * vimb - a webkit based vim like browser. - * - * Copyright (C) 2012-2013 Daniel Carl - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -#ifndef _URL_HISTORY_H -#define _URL_HISTORY_H - -typedef struct { - char* uri; - char* title; -} UrlHist; - -void url_history_cleanup(void); -void url_history_add(const char* uri, const char* title); -void url_history_get_all(GList** list); - -#endif /* end of include guard: _URL_HISTORY_H */