gboolean command_history(const Arg* arg)
{
- const char* input = GET_TEXT();
int step = vb.state.count ? vb.state.count * arg->i : arg->i;
- const char* entry = NULL;
- char* prefix = NULL;
-
- /* use the right history type according to current input text */
- if (!strncmp(input, ":open ", 6)) {
- entry = history_get(HISTORY_URL, step, input + 6);
- prefix = ":open ";
- } else if (!strncmp(input, ":tabopen ", 9)) {
- entry = history_get(HISTORY_URL, step, input + 9);
- prefix = ":tabopen ";
- } else if (*input == ':') {
- entry = history_get(HISTORY_COMMAND, step, input + 1);
- prefix = ":";
- } else if (*input == '/' || *input == '?') {
- entry = history_get(HISTORY_SEARCH, step, input + 1);
- prefix = *input == '/' ? "/" : "?";
- }
+ const char* input = GET_TEXT();
+ char* entry = history_get(input, step);
if (!entry) {
return FALSE;
}
- char* value = g_strconcat(prefix, entry, NULL);
- command_write_input(value);
- g_free(value);
+ command_write_input(entry);
+ g_free(entry);
return TRUE;
}
FILES_HISTORY
};
+static struct {
+ unsigned int pointer;
+ char* prefix;
+ char* query;
+ GList* active;
+} 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);
return history_load(history_get_file_by_type(type));
}
-const char* history_get(HistoryType type, int step, const char* query)
+/**
+ * Retrieves the command from history to be shown in input box.
+ * The result must be freed by the caller.
+ */
+char* history_get(const char* input, int step)
{
- const char* command;
+ char* command = NULL;
+ unsigned int len;
/* get the search prefix only on start of history search */
- if (!vb.state.history_active) {
- OVERWRITE_STRING(vb.state.history_prefix, query);
+ if (!history.active) {
+ HistoryType type;
+
+ /* get the right history type and command prefix */
+ if (!strncmp(input, ":open ", 6)) {
+ type = HISTORY_URL;
+ OVERWRITE_STRING(history.query, input + 6);
+ OVERWRITE_STRING(history.prefix, ":open ");
+ } else if (!strncmp(input, ":tabopen ", 9)) {
+ type = HISTORY_URL;
+ OVERWRITE_STRING(history.query, input + 9);
+ OVERWRITE_STRING(history.prefix, ":tabopen ");
+ } else if (*input == ':') {
+ type = HISTORY_COMMAND;
+ OVERWRITE_STRING(history.query, input + 1);
+ OVERWRITE_STRING(history.prefix, ":");
+ } else if (*input == '/' || *input == '?') {
+ type = HISTORY_SEARCH;
+ OVERWRITE_STRING(history.query, input + 1);
+ OVERWRITE_STRING(history.prefix, (*input == '/') ? "/" : "?");
+ } else {
+ return NULL;
+ }
GList* src = history_load(history_get_file_by_type(type));
/* generate new history list with the matching items */
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));
+ if (g_str_has_prefix(value, history.query)) {
+ history.active = g_list_prepend(history.active, g_strdup(value));
}
}
+
+ /* if the list is searched forward we would move the history pointer
+ * to the element with index 1, but we should start with 0 */
+ step = step > 0 ? step - 1 : step;
}
- const int len = g_list_length(vb.state.history_active);
+ len = g_list_length(history.active);
if (!len) {
return NULL;
}
/* if reached end/beginnen start at the opposit site of list again */
- vb.state.history_pointer = (len + vb.state.history_pointer + step) % len;
+ history.pointer = (len + history.pointer + step) % len;
- command = (char*)g_list_nth_data(vb.state.history_active, vb.state.history_pointer);
+ command = g_strconcat(
+ history.prefix,
+ g_list_nth_data(history.active, history.pointer),
+ NULL
+ );
return command;
}
void history_rewind(void)
{
- if (vb.state.history_active) {
- OVERWRITE_STRING(vb.state.history_prefix, NULL);
- vb.state.history_pointer = 0;
+ if (history.active) {
/* free temporary used history list */
- g_list_free_full(vb.state.history_active, (GDestroyNotify)g_free);
- vb.state.history_active = NULL;
+ g_list_free_full(history.active, (GDestroyNotify)g_free);
+
+ OVERWRITE_STRING(history.prefix, NULL);
+ history.active = NULL;
+ history.pointer = 0;
}
}