commit 84b880390e4a2a475936742c3b1aa37609ca2cab from: Omar Polo date: Mon Jul 12 15:26:32 2021 UTC move minibuffer-related fns to their own file and a bit of foreshadowing... :) commit - 7943bb816bd80662aa2a36f1d4f1ee0584052357 commit + 84b880390e4a2a475936742c3b1aa37609ca2cab blob - 669e558b248be11c4f2e7e695af4a9d5567ffb60 blob + 4cf6090fd4e119dbe9786d16b60ec2f58f0b7bf5 --- Makefile.am +++ Makefile.am @@ -13,6 +13,7 @@ telescope_SOURCES = cmd.c \ hist.c \ keymap.c \ mime.c \ + minibuffer.c \ pages.c \ parse.y \ parser.c \ blob - /dev/null blob + 9c208d86af425dd4ff8edc99b0d903e25b1f9cea (mode 644) --- /dev/null +++ minibuffer.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2021 Omar Polo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "telescope.h" + +static void minibuffer_hist_save_entry(void); +static void minibuffer_self_insert(void); +static void yornp_self_insert(void); +static void yornp_abort(void); +static void read_self_insert(void); +static void read_abort(void); +static void read_select(void); + +static void (*yornp_cb)(int, struct tab *); +static struct tab *yornp_data; + +static void (*read_cb)(const char*, unsigned int); +static unsigned int read_data; + +struct histhead eecmd_history, + ir_history, + lu_history, + read_history; + +struct ministate ministate; + +static void +minibuffer_hist_save_entry(void) +{ + struct hist *hist; + + if (ministate.history == NULL) + return; + + if ((hist = calloc(1, sizeof(*hist))) == NULL) + abort(); + + strlcpy(hist->h, ministate.buf, sizeof(hist->h)); + + if (TAILQ_EMPTY(&ministate.history->head)) + TAILQ_INSERT_HEAD(&ministate.history->head, hist, entries); + else + TAILQ_INSERT_TAIL(&ministate.history->head, hist, entries); + ministate.history->len++; +} + +/* + * taint the minibuffer cache: if we're currently showing a history + * element, copy that to the current buf and reset the "history + * navigation" thing. + */ +void +minibuffer_taint_hist(void) +{ + if (ministate.hist_cur == NULL) + return; + + strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf)); + ministate.hist_cur = NULL; +} + +static void +minibuffer_self_insert(void) +{ + char *c, tmp[5] = {0}; + size_t len; + + minibuffer_taint_hist(); + + if (thiskey.cp == 0) + return; + + len = utf8_encode(thiskey.cp, tmp); + c = utf8_nth(ministate.buffer.current_line->line, ministate.buffer.cpoff); + if (c + len > ministate.buf + sizeof(ministate.buf) - 1) + return; + + memmove(c + len, c, strlen(c)+1); + memcpy(c, tmp, len); + ministate.buffer.cpoff++; +} + +void +eecmd_self_insert(void) +{ + if (thiskey.meta || unicode_isspace(thiskey.cp) || + !unicode_isgraph(thiskey.cp)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +void +eecmd_select(void) +{ + struct cmd *cmd; + + for (cmd = cmds; cmd->cmd != NULL; ++cmd) { + if (!strcmp(cmd->cmd, ministate.buf)) { + exit_minibuffer(); + minibuffer_hist_save_entry(); + cmd->fn(current_buffer()); + return; + } + } + + message("No match"); +} + +void +ir_self_insert(void) +{ + minibuffer_self_insert(); +} + +void +ir_select(void) +{ + char buf[1025] = {0}; + struct phos_uri uri; + struct tab *tab; + + tab = current_tab(); + + exit_minibuffer(); + minibuffer_hist_save_entry(); + + /* a bit ugly but... */ + memcpy(&uri, &tab->uri, sizeof(tab->uri)); + phos_uri_set_query(&uri, ministate.buf); + phos_serialize_uri(&uri, buf, sizeof(buf)); + load_url_in_tab(tab, buf); +} + +void +lu_self_insert(void) +{ + if (thiskey.meta || unicode_isspace(thiskey.key) || + !unicode_isgraph(thiskey.key)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +void +lu_select(void) +{ + exit_minibuffer(); + minibuffer_hist_save_entry(); + load_url_in_tab(current_tab(), ministate.buf); +} + +void +bp_select(void) +{ + exit_minibuffer(); + if (*ministate.buf != '\0') + add_to_bookmarks(ministate.buf); + else + message("Abort."); +} + +static void +yornp_self_insert(void) +{ + if (thiskey.key != 'y' && thiskey.key != 'n') { + message("Please answer y or n"); + return; + } + + exit_minibuffer(); + yornp_cb(thiskey.key == 'y', yornp_data); +} + +static void +yornp_abort(void) +{ + exit_minibuffer(); + yornp_cb(0, yornp_data); +} + +static void +read_self_insert(void) +{ + if (thiskey.meta || !unicode_isgraph(thiskey.cp)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +static void +read_abort(void) +{ + exit_minibuffer(); + read_cb(NULL, read_data); +} + +static void +read_select(void) +{ + exit_minibuffer(); + minibuffer_hist_save_entry(); + read_cb(ministate.buf, read_data); +} + +void +enter_minibuffer(void (*self_insert_fn)(void), void (*donefn)(void), + void (*abortfn)(void), struct histhead *hist) +{ + in_minibuffer = 1; + base_map = &minibuffer_map; + current_map = &minibuffer_map; + + base_map->unhandled_input = self_insert_fn; + + ministate.donefn = donefn; + ministate.abortfn = abortfn; + memset(ministate.buf, 0, sizeof(ministate.buf)); + ministate.buffer.current_line = &ministate.vline; + ministate.buffer.current_line->line = ministate.buf; + ministate.buffer.cpoff = 0; + strlcpy(ministate.buf, "", sizeof(ministate.prompt)); + + ministate.history = hist; + ministate.hist_cur = NULL; + ministate.hist_off = 0; +} + +void +exit_minibuffer(void) +{ + in_minibuffer = 0; + base_map = &global_map; + current_map = &global_map; +} + +void +yornp(const char *prompt, void (*fn)(int, struct tab*), + struct tab *data) +{ + size_t len; + + if (in_minibuffer) { + fn(0, data); + return; + } + + yornp_cb = fn; + yornp_data = data; + enter_minibuffer(yornp_self_insert, yornp_self_insert, + yornp_abort, NULL); + + len = sizeof(ministate.prompt); + strlcpy(ministate.prompt, prompt, len); + strlcat(ministate.prompt, " (y or n) ", len); +} + +/* + * Not yet "completing", but soon maybe... + */ +void +completing_read(const char *prompt, void (*fn)(const char *, unsigned int), + unsigned int data) +{ + size_t len; + + if (in_minibuffer) + return; + + read_cb = fn; + read_data = data; + enter_minibuffer(read_self_insert, read_select, read_abort, + &read_history); + + len = sizeof(ministate.prompt); + strlcpy(ministate.prompt, prompt, len); + strlcat(ministate.prompt, ": ", len); +} blob - 17475e59659c68fa7e64a500759111da5ddce936 blob + 5adf485a07ae9fee6013a4d24bd3987c75255895 --- telescope.h +++ telescope.h @@ -342,6 +342,15 @@ int kmap_define_key(struct kmap*, const char*, void( /* mime.c */ int setup_parser_for(struct tab*); + +/* minibuffer.c */ +void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void), + struct histhead *); +void exit_minibuffer(void); +void yornp(const char *, void (*)(int, struct tab *), struct tab *); +void completing_read(const char *, + void (*)(const char *, unsigned int), + unsigned int); /* pages.c */ extern const char *about_about; @@ -394,6 +403,8 @@ extern int body_lines; extern int body_cols; extern int in_minibuffer; +extern struct kmap global_map, minibuffer_map, *current_map, *base_map; + struct excursion { int curs_x, curs_y; size_t line_off; @@ -491,10 +502,9 @@ void vmessage(const char*, va_list); void message(const char*, ...) __attribute__((format(printf, 1, 2))); void start_loading_anim(struct tab *tab); void load_url_in_tab(struct tab *, const char *); -void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void), struct histhead *); -void exit_minibuffer(void); void switch_to_tab(struct tab *); struct tab *current_tab(void); +struct buffer *current_buffer(void); struct tab *new_tab(const char *); unsigned int tab_new_id(void); int ui_init(void); blob - 55aebbdf2cc9f89d144d15ead94dfd811d16ea03 blob + 8055b9d85b8cacb91708ce0f17d71ba19cfdb826 --- ui.c +++ ui.c @@ -45,16 +45,8 @@ static struct event stdioev, winchev; static void restore_curs_x(struct buffer *); -static void minibuffer_hist_save_entry(void); -static void minibuffer_self_insert(void); -static void yornp_self_insert(void); -static void yornp_abort(void); -static void read_self_insert(void); -static void read_abort(void); -static void read_select(void); static struct vline *nth_line(struct buffer*, size_t); -static struct buffer *current_buffer(void); static int readkey(void); static void dispatch_stdio(int, short, void*); static void handle_clear_echoarea(int, short, void*); @@ -100,26 +92,13 @@ static uint32_t tab_counter; static char keybuf[64]; -static void (*yornp_cb)(int, struct tab *); -static struct tab *yornp_data; - -static void (*read_cb)(const char*, unsigned int); -static unsigned int read_data; - struct kmap global_map, minibuffer_map, *current_map, *base_map; -struct histhead eecmd_history, - ir_history, - lu_history, - read_history; - int in_minibuffer; -struct ministate ministate; - static inline void update_x_offset(void) { @@ -175,191 +154,6 @@ global_key_unbound(void) message("%s is undefined", keybuf); } -static void -minibuffer_hist_save_entry(void) -{ - struct hist *hist; - - if (ministate.history == NULL) - return; - - if ((hist = calloc(1, sizeof(*hist))) == NULL) - abort(); - - strlcpy(hist->h, ministate.buf, sizeof(hist->h)); - - if (TAILQ_EMPTY(&ministate.history->head)) - TAILQ_INSERT_HEAD(&ministate.history->head, hist, entries); - else - TAILQ_INSERT_TAIL(&ministate.history->head, hist, entries); - ministate.history->len++; -} - -/* - * taint the minibuffer cache: if we're currently showing a history - * element, copy that to the current buf and reset the "history - * navigation" thing. - */ -void -minibuffer_taint_hist(void) -{ - if (ministate.hist_cur == NULL) - return; - - strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf)); - ministate.hist_cur = NULL; -} - -static void -minibuffer_self_insert(void) -{ - char *c, tmp[5] = {0}; - size_t len; - - minibuffer_taint_hist(); - - if (thiskey.cp == 0) - return; - - len = utf8_encode(thiskey.cp, tmp); - c = utf8_nth(ministate.buffer.current_line->line, ministate.buffer.cpoff); - if (c + len > ministate.buf + sizeof(ministate.buf) - 1) - return; - - memmove(c + len, c, strlen(c)+1); - memcpy(c, tmp, len); - ministate.buffer.cpoff++; -} - -void -eecmd_self_insert(void) -{ - if (thiskey.meta || unicode_isspace(thiskey.cp) || - !unicode_isgraph(thiskey.cp)) { - global_key_unbound(); - return; - } - - minibuffer_self_insert(); -} - -void -eecmd_select(void) -{ - struct cmd *cmd; - - for (cmd = cmds; cmd->cmd != NULL; ++cmd) { - if (!strcmp(cmd->cmd, ministate.buf)) { - exit_minibuffer(); - minibuffer_hist_save_entry(); - cmd->fn(current_buffer()); - return; - } - } - - message("No match"); -} - -void -ir_self_insert(void) -{ - minibuffer_self_insert(); -} - -void -ir_select(void) -{ - char buf[1025] = {0}; - struct phos_uri uri; - struct tab *tab; - - tab = current_tab(); - - exit_minibuffer(); - minibuffer_hist_save_entry(); - - /* a bit ugly but... */ - memcpy(&uri, &tab->uri, sizeof(tab->uri)); - phos_uri_set_query(&uri, ministate.buf); - phos_serialize_uri(&uri, buf, sizeof(buf)); - load_url_in_tab(tab, buf); -} - -void -lu_self_insert(void) -{ - if (thiskey.meta || unicode_isspace(thiskey.key) || - !unicode_isgraph(thiskey.key)) { - global_key_unbound(); - return; - } - - minibuffer_self_insert(); -} - -void -lu_select(void) -{ - exit_minibuffer(); - minibuffer_hist_save_entry(); - load_url_in_tab(current_tab(), ministate.buf); -} - -void -bp_select(void) -{ - exit_minibuffer(); - if (*ministate.buf != '\0') - add_to_bookmarks(ministate.buf); - else - message("Abort."); -} - -static void -yornp_self_insert(void) -{ - if (thiskey.key != 'y' && thiskey.key != 'n') { - message("Please answer y or n"); - return; - } - - exit_minibuffer(); - yornp_cb(thiskey.key == 'y', yornp_data); -} - -static void -yornp_abort(void) -{ - exit_minibuffer(); - yornp_cb(0, yornp_data); -} - -static void -read_self_insert(void) -{ - if (thiskey.meta || !unicode_isgraph(thiskey.cp)) { - global_key_unbound(); - return; - } - - minibuffer_self_insert(); -} - -static void -read_abort(void) -{ - exit_minibuffer(); - read_cb(NULL, read_data); -} - -static void -read_select(void) -{ - exit_minibuffer(); - minibuffer_hist_save_entry(); - read_cb(ministate.buf, read_data); -} - static struct vline * nth_line(struct buffer *buffer, size_t n) { @@ -1194,39 +988,6 @@ load_url_in_tab(struct tab *tab, const char *url) tab->buffer.curs_x = 0; tab->buffer.curs_y = 0; redraw_tab(tab); -} - -void -enter_minibuffer(void (*self_insert_fn)(void), void (*donefn)(void), - void (*abortfn)(void), struct histhead *hist) -{ - in_minibuffer = 1; - base_map = &minibuffer_map; - current_map = &minibuffer_map; - - base_map->unhandled_input = self_insert_fn; - - ministate.donefn = donefn; - ministate.abortfn = abortfn; - memset(ministate.buf, 0, sizeof(ministate.buf)); - ministate.buffer.current_line = &ministate.vline; - ministate.buffer.current_line->line = ministate.buf; - ministate.buffer.cpoff = 0; - strlcpy(ministate.buf, "", sizeof(ministate.prompt)); - - ministate.history = hist; - ministate.hist_cur = NULL; - ministate.hist_off = 0; -} - -void -exit_minibuffer(void) -{ - werase(echoarea); - - in_minibuffer = 0; - base_map = &global_map; - current_map = &global_map; } void @@ -1416,21 +1177,7 @@ void ui_yornp(const char *prompt, void (*fn)(int, struct tab *), struct tab *data) { - size_t len; - - if (in_minibuffer) { - fn(0, data); - return; - } - - yornp_cb = fn; - yornp_data = data; - enter_minibuffer(yornp_self_insert, yornp_self_insert, - yornp_abort, NULL); - - len = sizeof(ministate.prompt); - strlcpy(ministate.prompt, prompt, len); - strlcat(ministate.prompt, " (y or n) ", len); + yornp(prompt, fn, data); redraw_tab(current_tab()); } @@ -1438,19 +1185,7 @@ void ui_read(const char *prompt, void (*fn)(const char*, unsigned int), unsigned int data) { - size_t len; - - if (in_minibuffer) - return; - - read_cb = fn; - read_data = data; - enter_minibuffer(read_self_insert, read_select, read_abort, - &read_history); - - len = sizeof(ministate.prompt); - strlcpy(ministate.prompt, prompt, len); - strlcat(ministate.prompt, ": ", len); + completing_read(prompt, fn, data); redraw_tab(current_tab()); }