commit da3ec8f4f3408d50f29d5430883939a3f0ff4cff
parent a61a1d406b4fc9655b385938830ab92faa45698b
Author: Kyle Milz <kmilz@ucalgary.ca>
Date: Sun, 14 Oct 2012 16:35:03 -0600
re-implement tab completion
implement rudimentary command and history completion. still needs a few
things (highlighting of current suggestion, other bugs).
rip out the old completion.
Diffstat:
M | src/commands.c | | | 364 | +++++++++++++++++++++++++------------------------------------------------------ |
1 file changed, 114 insertions(+), 250 deletions(-)
diff --git a/src/commands.c b/src/commands.c
@@ -8,270 +8,134 @@
#include "commands.h"
#include "utilities.h"
-static unsigned int scrollstep = 40; /* cursor difference in pixel */
-static unsigned int pagingkeep = 40; /* pixels kept when paging */
+// static unsigned int scrollstep = 40; /* cursor difference in pixel */
+// static unsigned int pagingkeep = 40; /* pixels kept when paging */
-void fill_suggline(char * suggline, const char * command, const char *fill_with);
-Evas_Object * fill_eventbox(const char * completion_line);
+Eina_Bool
+complete(const Arg *arg, void *data)
+{
+ Window_Data *wd = data;
+ const char *match;
+ Eina_List *l;
+ size_t len;
+ int i;
+ Evas_Object *label;
+
+ /* make this function re-entrant */
+ static Eina_List *matches = NULL;
+ static const char *prefix;
+ static int current = -1, n;
+ static Eina_List *widgets = NULL;
+
+ printf("complete()\n");
+
+ match = elm_entry_entry_get(wd->url);
+ len = strlen(match);
+
+ if ((len == 0 || match[0] != ':') && arg->i != HideCompletion)
+ return EINA_TRUE;
+
+ if (prefix) {
+ printf("\tprefix found, current = %i, num matches = %i\n", current, eina_list_count(matches));
+ if (arg->i != HideCompletion && widgets && current != -1 && !strcmp(&match[0],
+ eina_list_nth(matches, current))) {
+ elm_object_style_set(eina_list_nth(widgets, current), "normal");
+ current = (n + current + (arg->i == DirectionPrev ? -1 : 1)) % n;
+ if ((arg->i == DirectionNext && current == 0)
+ || (arg->i == DirectionPrev && current == n - 1))
+ current = -1;
+ } else {
+ eina_list_free(widgets);
+ eina_list_free(matches);
+ eina_stringshare_del(prefix);
+ elm_box_clear(wd->event_box);
+ widgets = NULL;
+ matches = NULL;
+ prefix = NULL;
+ n = 0;
+ current = -1;
+ if (arg->i == HideCompletion)
+ return EINA_TRUE;
+ }
+ } else if (arg->i == HideCompletion)
+ return EINA_TRUE;
+ if (!widgets) {
+ prefix = eina_stringshare_add(match);
-void fill_suggline(char * suggline, const char * command, const char *fill_with) {
- memset(suggline, 0, 512);
- strncpy(suggline, command, 512);
- strncat(suggline, " ", 1);
- strncat(suggline, fill_with, 512 - strlen(suggline) - 1);
-}
+ if (strchr(match, ' ') == NULL) {
+ for (i = 0; i < LENGTH(commands); i++)
+ if (strncmp(commands[i].cmd, match + 1, len - 1) == 0) {
+ Eina_Strbuf *buf = eina_strbuf_new();
+ eina_strbuf_append_printf(buf, ":%s", commands[i].cmd);
+ matches = eina_list_append(matches, eina_strbuf_string_get(buf));
+ }
+ }
-Evas_Object *fill_eventbox(const char * completion_line)
-{
- /*
- GtkBox * row;
- Evas_Object *row_eventbox, *el;
- GdkColor color;
- char *markup, *markup_tmp;
-
- row = GTK_BOX(gtk_hbox_new(FALSE, 0));
- row_eventbox = gtk_event_box_new();
- gdk_color_parse(completionbgcolor[0], &color);
- gtk_widget_modify_bg(row_eventbox, GTK_STATE_NORMAL, &color);
- el = gtk_label_new(NULL);
- markup_tmp = g_markup_escape_text(completion_line, strlen(completion_line));
- markup = g_strconcat("<span font=\"", completionfont[0], "\" color=\"", completioncolor[0], "\">",
- markup_tmp, "</span>", NULL);
- gtk_label_set_markup(GTK_LABEL(el), markup);
- g_free(markup_tmp);
- g_free(markup);
- gtk_misc_set_alignment(GTK_MISC(el), 0, 0);
- gtk_box_pack_start(row, el, TRUE, TRUE, 2);
- gtk_container_add(GTK_CONTAINER(row_eventbox), GTK_WIDGET(row));
- return row_eventbox;
- */
- return NULL;
-}
+ char **tokens = eina_str_split(match, " ", 2);
+ if (tokens && (strncmp(tokens[0], ":open", 5) == 0 ||
+ strncmp(tokens[0], ":tabopen", 8) == 0)) {
+ /* :open history completion */
+ void *hash_data;
+ Eina_Iterator *it = eina_hash_iterator_tuple_new(hist_items_hash_get(wd->app->history));
+
+ while (eina_iterator_next(it, &hash_data)) {
+ Eina_Hash_Tuple *t = hash_data;
+ Eina_Strbuf *buf = eina_strbuf_new();
+ Hist_Item *hist_item = t->data;
+ const char *url = hist_item_url_get(hist_item);
+ if (strncmp(url, tokens[1], strlen(tokens[1])) == 0) {
+ eina_strbuf_append_printf(buf, "%s %s", tokens[0], url);
+ matches = eina_list_append(matches, eina_strbuf_string_get(buf));
+ }
+ }
+ }
+ else if (tokens && strncmp(tokens[0], ":set", 5) == 0) {
+ printf("\t:set not implemented yet\n");
+ }
-Eina_Bool
-complete(const Arg *arg, void *data)
-{
-#if 0
- char *p, *s, *markup, *entry, *searchfor, command[32] = "", suggline[512] = "", **suggurls;
- char *str;
- size_t listlen, len, cmdlen;
- int i, spacepos;
- Listelement *elementlist = NULL, *elementpointer;
- Eina_Bool highlight = FALSE;
- // GtkBox *row;
- // GtkWidget *row_eventbox, *el;
- // GtkBox *_table;
- // GdkColor color;
- // static GtkWidget *table, *top_border;
- Evas_Object *row, *row_eventbox, *el, *_table;
- Evas_Object *table, *top_border;
- static char *prefix;
- static char **suggestions;
- static Evas_Object **widgets;
- static int n = 0, m, current = -1;
- Window_Data *ad = data;
+ n = eina_list_count(matches);
+ printf("\tfound %i matches for %s\n", n, match);
- str = elm_entry_entry_get(ad->url);
- // str = (char*)gtk_entry_get_text(GTK_ENTRY(inputbox));
- len = strlen(str);
+ EINA_LIST_FOREACH(matches, l, match) {
- /* Get the length of the list of commands for completion. We need this to
- * malloc/realloc correctly.
- */
- listlen = LENGTH(commands);
+ printf("\tbuilding label for match %s\n", match);
- if ((len == 0 || str[0] != ':') && arg->i != HideCompletion)
- return TRUE;
- /*
- if (prefix) {
- if (arg->i != HideCompletion && widgets && current != -1 && !strcmp(&str[1], suggestions[current])) {
- gdk_color_parse(completionbgcolor[0], &color);
- gtk_widget_modify_bg(widgets[current], GTK_STATE_NORMAL, &color);
- current = (n + current + (arg->i == DirectionPrev ? -1 : 1)) % n;
- if ((arg->i == DirectionNext && current == 0)
- || (arg->i == DirectionPrev && current == n - 1))
- current = -1;
- } else {
- free(widgets);
- free(suggestions);
- free(prefix);
- gtk_widget_destroy(GTK_WIDGET(table));
- gtk_widget_destroy(GTK_WIDGET(top_border));
- table = NULL;
- widgets = NULL;
- suggestions = NULL;
- prefix = NULL;
- n = 0;
- current = -1;
- if (arg->i == HideCompletion)
- return TRUE;
- }
- } else if (arg->i == HideCompletion)
- return TRUE;
- */
- if (!widgets) {
- prefix = strdup(str);
- // widgets = malloc(sizeof(GtkWidget*) * listlen);
- widgets = malloc(sizeof(Evas_Object*) * listlen);
- suggestions = malloc(sizeof(char*) * listlen);
- top_border = gtk_event_box_new();
- gtk_widget_set_size_request(GTK_WIDGET(top_border), 0, 1);
-
- // gdk_color_parse(completioncolor[2], &color);
- // gtk_widget_modify_bg(top_border, GTK_STATE_NORMAL, &color);
- elm_bg_color_set(top_border, completioncolor[2][0], completioncolor[2][1], completioncolor[2][2]);
-
- table = gtk_event_box_new();
- gdk_color_parse(completionbgcolor[0], &color);
- _table = GTK_BOX(gtk_vbox_new(FALSE, 0));
- highlight = len > 1;
- if (strchr(str, ' ') == NULL) {
- /* command completion */
- listlen = LENGTH(commands);
- for (i = 0; i < listlen; i++) {
- if (commands[i].cmd == NULL)
- break;
- cmdlen = strlen(commands[i].cmd);
- if (!highlight || (n < MAX_LIST_SIZE && len - 1 <= cmdlen && !strncmp(&str[1], commands[i].cmd, len - 1))) {
- p = s = malloc(sizeof(char*) * (highlight ? sizeof(COMPLETION_TAG_OPEN) + sizeof(COMPLETION_TAG_CLOSE) - 1 : 1) + cmdlen);
- if (highlight) {
- memcpy(p, COMPLETION_TAG_OPEN, sizeof(COMPLETION_TAG_OPEN) - 1);
- memcpy((p += sizeof(COMPLETION_TAG_OPEN) - 1), &str[1], len - 1);
- memcpy((p += len - 1), COMPLETION_TAG_CLOSE, sizeof(COMPLETION_TAG_CLOSE) - 1);
- p += sizeof(COMPLETION_TAG_CLOSE) - 1;
- }
- memcpy(p, &commands[i].cmd[len - 1], cmdlen - len + 2);
- row = GTK_BOX(gtk_hbox_new(FALSE, 0));
- row_eventbox = gtk_event_box_new();
- gtk_widget_modify_bg(row_eventbox, GTK_STATE_NORMAL, &color);
- el = gtk_label_new(NULL);
- markup = g_strconcat("<span font=\"", completionfont[0], "\" color=\"", completioncolor[0], "\">", s, "</span>", NULL);
- free(s);
- gtk_label_set_markup(GTK_LABEL(el), markup);
- g_free(markup);
- gtk_misc_set_alignment(GTK_MISC(el), 0, 0);
- gtk_box_pack_start(row, el, TRUE, TRUE, 2);
- gtk_container_add(GTK_CONTAINER(row_eventbox), GTK_WIDGET(row));
- gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0);
- suggestions[n] = commands[i].cmd;
- widgets[n++] = row_eventbox;
- }
- }
- } else {
- entry = (char *)malloc(512 * sizeof(char));
- if (entry == NULL) {
- return FALSE;
- }
- memset(entry, 0, 512);
- suggurls = malloc(sizeof(char*) * listlen);
- if (suggurls == NULL) {
- return FALSE;
- }
- spacepos = strcspn(str, " ");
- searchfor = (str + spacepos + 1);
- strncpy(command, (str + 1), spacepos - 1);
- if (strlen(command) == 3 && strncmp(command, "set", 3) == 0) {
- /* browser settings */
- listlen = LENGTH(browsersettings);
- for (i = 0; i < listlen; i++) {
- if (n < MAX_LIST_SIZE && strstr(browsersettings[i].name, searchfor) != NULL) {
- /* match */
- fill_suggline(suggline, command, browsersettings[i].name);
- /* FIXME(HP): This memory is never freed */
- suggurls[n] = (char *)malloc(sizeof(char) * 512 + 1);
- strncpy(suggurls[n], suggline, 512);
- suggestions[n] = suggurls[n];
- row_eventbox = fill_eventbox(suggline);
- gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0);
- widgets[n++] = row_eventbox;
- }
+ label = elm_label_add(wd->win);
+ evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+ elm_object_text_set(label, match);
+ elm_box_pack_end(wd->event_box, label);
+ evas_object_show(label);
- }
- } else if (strlen(command) == 2 && strncmp(command, "qt", 2) == 0) {
- /* completion on tags */
- spacepos = strcspn(str, " ");
- searchfor = (str + spacepos + 1);
- elementlist = complete_list(searchfor, 1, elementlist);
- } else {
- /* URL completion: bookmarks */
- elementlist = complete_list(searchfor, 0, elementlist);
- m = count_list(elementlist);
- if (m < MAX_LIST_SIZE) {
- /* URL completion: history */
- elementlist = complete_list(searchfor, 2, elementlist);
- }
- }
- elementpointer = elementlist;
- while (elementpointer != NULL) {
- fill_suggline(suggline, command, elementpointer->element);
- /* FIXME(HP): This memory is never freed */
- suggurls[n] = (char *)malloc(sizeof(char) * 512 + 1);
- strncpy(suggurls[n], suggline, 512);
- suggestions[n] = suggurls[n];
- row_eventbox = fill_eventbox(suggline);
- gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0);
- widgets[n++] = row_eventbox;
- elementpointer = elementpointer->next;
- if (n >= MAX_LIST_SIZE)
- break;
- }
- free_list(elementlist);
- if (suggurls != NULL) {
- free(suggurls);
- suggurls = NULL;
- }
- if (entry != NULL) {
- free(entry);
- entry = NULL;
- }
- }
- /* TA: FIXME - this needs rethinking entirely. */
- {
- GtkWidget **widgets_temp = realloc(widgets, sizeof(*widgets) * n);
- if (widgets_temp == NULL && widgets == NULL) {
- fprintf(stderr, "Couldn't realloc() widgets\n");
- exit(1);
- }
- widgets = widgets_temp;
- char **suggestions_temp = realloc(suggestions, sizeof(*suggestions) * n);
- if (suggestions_temp == NULL && suggestions == NULL) {
- fprintf(stderr, "Couldn't realloc() suggestions\n");
- exit(1);
- }
- suggestions = suggestions_temp;
- }
- if (!n) {
- gdk_color_parse(completionbgcolor[1], &color);
- gtk_widget_modify_bg(table, GTK_STATE_NORMAL, &color);
- el = gtk_label_new(NULL);
- gtk_misc_set_alignment(GTK_MISC(el), 0, 0);
- markup = g_strconcat("<span font=\"", completionfont[1], "\" color=\"", completioncolor[1], "\">No Completions</span>", NULL);
- gtk_label_set_markup(GTK_LABEL(el), markup);
- g_free(markup);
- gtk_box_pack_start(_table, GTK_WIDGET(el), FALSE, FALSE, 0);
- }
- gtk_box_pack_start(box, GTK_WIDGET(top_border), FALSE, FALSE, 0);
- gtk_container_add(GTK_CONTAINER(table), GTK_WIDGET(_table));
- gtk_box_pack_start(box, GTK_WIDGET(table), FALSE, FALSE, 0);
- gtk_widget_show_all(GTK_WIDGET(window));
- if (!n)
- return TRUE;
+ widgets = eina_list_append(widgets, label);
+ }
+
+ if (!n) {
+ label = elm_label_add(wd->win);
+ evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+ elm_object_text_set(label, "No Completions");
+ elm_box_pack_end(wd->event_box, label);
+ evas_object_show(label);
+ }
+
+ evas_object_show(wd->event_box);
+ if (!n)
+ return EINA_TRUE;
current = arg->i == DirectionPrev ? n - 1 : 0;
- }
+ }
+
if (current != -1) {
- gdk_color_parse(completionbgcolor[2], &color);
- gtk_widget_modify_bg(GTK_WIDGET(widgets[current]), GTK_STATE_NORMAL, &color);
- s = g_strconcat(":", suggestions[current], NULL);
- gtk_entry_set_text(GTK_ENTRY(inputbox), s);
- g_free(s);
+ Eina_Strbuf *suggestion = eina_strbuf_new();
+ eina_strbuf_append_printf(suggestion, "%s", (char*)eina_list_nth(matches, current));
+ elm_entry_entry_set(wd->url, eina_strbuf_string_get(suggestion));
+ elm_object_style_set(eina_list_nth(matches, current), "highlighted");
} else
- gtk_entry_set_text(GTK_ENTRY(inputbox), prefix);
- gtk_editable_set_position(GTK_EDITABLE(inputbox), -1);
-#endif
- return TRUE;
+ elm_entry_entry_set(wd->url, prefix);
+ elm_entry_cursor_end_set(wd->url);
+
+ return EINA_TRUE;
}
Eina_Bool