commit 9ca159513d033a9c5b19bc882035bf5126bd6f16 from: Omar Polo date: Tue Mar 09 19:25:12 2021 UTC scratching the minibuffer functions commit - ed44414dc1ff557d4dcdedee96d6a61c6f7efa2b commit + 9ca159513d033a9c5b19bc882035bf5126bd6f16 blob - bc41ba38ba8e73c3ed253b3f9bd0a8f37c2d7715 blob + c6f583820cb7630b0bf5bece25f27b60700b20b9 --- ui.c +++ ui.c @@ -83,6 +83,7 @@ static void load_default_keys(void); static int push_line(struct tab*, const struct line*, const char*, size_t); static void empty_vlist(struct tab*); static void restore_cursor(struct tab *); + static void cmd_previous_line(struct tab*); static void cmd_next_line(struct tab*); static void cmd_forward_char(struct tab*); @@ -94,6 +95,17 @@ static void cmd_scroll_up(struct tab*); static void cmd_scroll_down(struct tab*); static void cmd_kill_telescope(struct tab*); static void cmd_push_button(struct tab*); +static void cmd_execute_extended_command(struct tab*); + +static void global_key_unbound(void); + +static void cmd_mini_del(struct tab*); +static void cmd_mini_forward_char(struct tab*); +static void cmd_mini_backward_char(struct tab*); +static void cmd_mini_move_end_of_line(struct tab*); +static void cmd_mini_move_beginning_of_line(struct tab*); +static void eecmd_self_insert(void); + static struct line *nth_line(struct tab*, size_t); static struct tab *current_tab(void); static void dispatch_stdio(int, short, void*); @@ -106,14 +118,19 @@ static int wrap_page(struct tab*); static void print_line(struct line*); static void redraw_tabline(void); static void redraw_modeline(struct tab*); +static void redraw_minibuffer(void); static void redraw_tab(struct tab*); static void message(const char*, ...) __attribute__((format(printf, 1, 2))); static void start_loading_anim(struct tab*); static void update_loading_anim(int, short, void*); static void stop_loading_anim(struct tab*); static void load_url_in_tab(struct tab*, const char*); +static void enter_minibuffer(struct kmap*); +static void exit_minibuffer(struct tab*); static void new_tab(void); +static struct { int meta, key; } thiskey; + static WINDOW *tabline, *body, *modeline, *minibuf; static int body_lines, body_cols; @@ -139,7 +156,19 @@ struct ui_state { #define CTRL(n) ((n)&0x1F) -static TAILQ_HEAD(kmap, keymap) global_map, *current_map; +struct kmap { + TAILQ_HEAD(map, keymap) m; + void (*unhandled_input)(void); +}; + +struct kmap global_map, + eecmd_map, + yornp_map, + yesornop_map, + cmplread_map, + *current_map, + *base_map; + struct keymap { int meta; int key; @@ -149,6 +178,14 @@ struct keymap { TAILQ_ENTRY(keymap) keymaps; }; +static int in_minibuffer; + +static struct { + char buf[1024]; + size_t off, len; + char prompt[16]; +} ministate; + static int kbd(const char *key) { @@ -162,7 +199,11 @@ kbd(const char *key) { "", KEY_RIGHT }, { "", KEY_PPAGE }, { "", KEY_NPAGE }, + { "", KEY_HOME }, + { "", KEY_END }, /* ... */ + { "del", KEY_BACKSPACE }, + { "esc", 27 }, { "space", ' ' }, { "spc", ' ' }, { "enter", CTRL('m') }, @@ -203,7 +244,7 @@ again: while (*key != '\0' && isspace(*key)) ++key; - TAILQ_FOREACH(entry, map, keymaps) { + TAILQ_FOREACH(entry, &map->m, keymaps) { if (entry->meta == meta && entry->key == k) { if (*key == '\0') { entry->fn = fn; @@ -219,12 +260,12 @@ again: entry->meta = meta; entry->key = k; - TAILQ_INIT(&entry->map); + TAILQ_INIT(&entry->map.m); - if (TAILQ_EMPTY(map)) - TAILQ_INSERT_HEAD(map, entry, keymaps); + if (TAILQ_EMPTY(&map->m)) + TAILQ_INSERT_HEAD(&map->m, entry, keymaps); else - TAILQ_INSERT_TAIL(map, entry, keymaps); + TAILQ_INSERT_TAIL(&map->m, entry, keymaps); if (*key != '\0') { map = &entry->map; @@ -240,9 +281,17 @@ global_set_key(const char *key, void (*fn)(struct tab* kmap_define_key(&global_map, key, fn); } +static inline void +eecmd_set_key(const char *key, void (*fn)(struct tab*)) +{ + kmap_define_key(&eecmd_map, key, fn); +} + static void load_default_keys(void) { + /* === global map === */ + /* emacs */ global_set_key("C-p", cmd_previous_line); global_set_key("C-n", cmd_next_line); @@ -254,6 +303,8 @@ load_default_keys(void) global_set_key("C-x C-c", cmd_kill_telescope); + global_set_key("M-x", cmd_execute_extended_command); + /* vi/vi-like */ global_set_key("k", cmd_previous_line); global_set_key("j", cmd_next_line); @@ -266,6 +317,8 @@ load_default_keys(void) /* tmp */ global_set_key("q", cmd_kill_telescope); + global_set_key(":", cmd_execute_extended_command); + /* cua */ global_set_key("", cmd_previous_line); global_set_key("", cmd_next_line); @@ -279,6 +332,18 @@ load_default_keys(void) /* global */ global_set_key("C-m", cmd_push_button); + + /* === eecmd map === */ + eecmd_set_key("C-g", exit_minibuffer); + eecmd_set_key("esc", exit_minibuffer); + eecmd_set_key("del", cmd_mini_del); + + eecmd_set_key("C-f", cmd_mini_forward_char); + eecmd_set_key("C-b", cmd_mini_backward_char); + eecmd_set_key("C-e", cmd_mini_move_end_of_line); + eecmd_set_key("C-a", cmd_mini_move_beginning_of_line); + eecmd_set_key("", cmd_mini_move_end_of_line); + eecmd_set_key("", cmd_mini_move_beginning_of_line); } static int @@ -448,6 +513,94 @@ cmd_push_button(struct tab *tab) return; load_url_in_tab(tab, l->alt); +} + +static void +cmd_execute_extended_command(struct tab *tab) +{ + size_t len; + + enter_minibuffer(&eecmd_map); + + len = sizeof(ministate.prompt); + strlcpy(ministate.prompt, "", len); + + if (thiskey.meta) + strlcat(ministate.prompt, "M-", len); + + strlcat(ministate.prompt, keyname(thiskey.key), len); + strlcat(ministate.prompt, " ", len); +} + +static void +global_key_unbound(void) +{ + message("%s%c is undefined", + thiskey.meta ? "M-" : "", + thiskey.key); +} + +static void +cmd_mini_del(struct tab *tab) +{ + if (ministate.len == 0 || ministate.off == 0) + return; + + memmove(&ministate.buf[ministate.off-1], + &ministate.buf[ministate.off], + ministate.len - ministate.off + 1); + ministate.off--; + ministate.len--; +} + +static void +cmd_mini_forward_char(struct tab *tab) +{ + if (ministate.off == ministate.len) + return; + ministate.off++; +} + +static void +cmd_mini_backward_char(struct tab *tab) +{ + if (ministate.off == 0) + return; + ministate.off--; +} + +static void +cmd_mini_move_end_of_line(struct tab *tab) +{ + ministate.off = ministate.len; +} + +static void +cmd_mini_move_beginning_of_line(struct tab *tab) +{ + ministate.off = 0; +} + +static void +eecmd_self_insert(void) +{ + if (thiskey.meta || isspace(thiskey.key) || + !isgraph(thiskey.key)) { + global_key_unbound(); + return; + } + + if (ministate.len == sizeof(ministate.buf)) + return; + + /* TODO: utf8 handling! */ + + memmove(&ministate.buf[ministate.off+1], + &ministate.buf[ministate.off], + ministate.len - ministate.off + 1); + ministate.buf[ministate.off] = thiskey.key; + ministate.off++; + ministate.len++; } static struct line * @@ -485,45 +638,49 @@ static void dispatch_stdio(int fd, short ev, void *d) { struct keymap *k; - int meta, key; - key = wgetch(body); - if (key == ERR) + thiskey.key = wgetch(body); + if (thiskey.key == ERR) return; - if (key == 27) { + if (thiskey.key == 27) { /* TODO: make escape-time customizable */ - meta = 1; - key = wgetch(body); - if (key == ERR) - key = 27; + thiskey.meta = 1; + thiskey.key = wgetch(body); + if (thiskey.key == ERR) + thiskey.key = 27; } else - meta = 0; + thiskey.meta = 0; - TAILQ_FOREACH(k, current_map, keymaps) { - if (k->meta == meta && k->key == key) { + TAILQ_FOREACH(k, ¤t_map->m, keymaps) { + if (k->meta == thiskey.meta && + k->key == thiskey.key) { if (k->fn == NULL) current_map = &k->map; else { - current_map = &global_map; + current_map = base_map; k->fn(current_tab()); } goto done; } } - current_map = &global_map; + current_map->unhandled_input(); + current_map = base_map; - message("%s%c is undefined", - meta ? "M-" : "", key); - done: + redraw_minibuffer(); restore_cursor(current_tab()); wrefresh(tabline); wrefresh(modeline); - wrefresh(minibuf); - wrefresh(body); + if (in_minibuffer) { + wrefresh(body); + wrefresh(minibuf); + } else { + wrefresh(minibuf); + wrefresh(body); + } } static void @@ -813,6 +970,21 @@ redraw_modeline(struct tab *tab) for (; x < max_x; ++x) waddstr(modeline, "-"); +} + +static void +redraw_minibuffer(void) +{ + size_t off; + + wclear(minibuf); + if (!in_minibuffer) + return; + + off = strlen(ministate.prompt); + mvwprintw(minibuf, 0, 0, "%s%s", ministate.prompt, + ministate.buf); + wmove(minibuf, 0, off + ministate.off); } static void @@ -839,13 +1011,19 @@ redraw_tab(struct tab *tab) redraw_tabline(); redraw_modeline(tab); + redraw_minibuffer(); restore_cursor(tab); wrefresh(tabline); wrefresh(modeline); - wrefresh(minibuf); - wrefresh(body); + if (in_minibuffer) { + wrefresh(body); + wrefresh(minibuf); + } else { + wrefresh(minibuf); + wrefresh(body); + } } static void @@ -853,6 +1031,9 @@ message(const char *fmt, ...) { va_list ap; + if (in_minibuffer) + return; + va_start(ap, fmt); if (clminibufev_set) @@ -889,7 +1070,10 @@ update_loading_anim(int fd, short ev, void *d) redraw_modeline(tab); wrefresh(modeline); + wrefresh(body); + if (in_minibuffer) + wrefresh(minibuf); evtimer_add(&tab->s->loadingev, &loadingev_timer); } @@ -904,8 +1088,11 @@ stop_loading_anim(struct tab *tab) tab->s->loading_anim_step = 0; redraw_modeline(tab); + wrefresh(modeline); wrefresh(body); + if (in_minibuffer) + wrefresh(minibuf); } static void @@ -922,6 +1109,33 @@ load_url_in_tab(struct tab *tab, const char *url) } static void +enter_minibuffer(struct kmap *map) +{ + if (clminibufev_set) { + clminibufev_set = 0; + evtimer_del(&clminibufev); + } + + in_minibuffer = 1; + base_map = map; + current_map = map; + + memset(ministate.buf, 0, sizeof(ministate.buf)); + ministate.off = 0; + strlcpy(ministate.buf, "", sizeof(ministate.prompt)); +} + +static void +exit_minibuffer(struct tab *tab) +{ + wclear(minibuf); + + in_minibuffer = 0; + base_map = &global_map; + current_map = &global_map; +} + +static void new_tab(void) { struct tab *tab, *t; @@ -958,7 +1172,17 @@ ui_init(void) { setlocale(LC_ALL, ""); - TAILQ_INIT(&global_map); + TAILQ_INIT(&global_map.m); + global_map.unhandled_input = global_key_unbound; + + TAILQ_INIT(&eecmd_map.m); + eecmd_map.unhandled_input = eecmd_self_insert; + + TAILQ_INIT(&yornp_map.m); + TAILQ_INIT(&yesornop_map.m); + TAILQ_INIT(&cmplread_map.m); + + base_map = &global_map; current_map = &global_map; load_default_keys();