commit 5cd2ebb1798e7ee9e1656e7bda590e0790558cd5 from: Omar Polo date: Thu Mar 11 14:14:25 2021 UTC 1X input, load/edit current URL * rework response code handling * support 10/11 input requests * load a url from minibuffer * edit current url and load it from minibuffer commit - 481340ccf7f2ae08e260a374ffaad5a430cc3f57 commit + 5cd2ebb1798e7ee9e1656e7bda590e0790558cd5 blob - 600f2c50a791865471365b60ac5950499f2ecb24 blob + 6b945d131b5f4e03e7a4028d7233d758c3a40b4b --- pages.c +++ pages.c @@ -45,10 +45,14 @@ const char *about_new = "Id dolore aperiam voluptatem libero eaque omnis rerum nulla. Ullam sit voluptate accusamus molestiae enim minus. Fugit sequi quam dignissimos. Odio inventore vel sed. Voluptatem aut magni dignissimos." ; +/* XXX: keep in sync with telescope.c:/^normalize_code/ */ const char *err_pages[70] = { [CANNOT_FETCH] = "# Couldn't load the page\n", [TOO_MUCH_REDIRECTS] = "# Too much redirects\n", + [MALFORMED_RESPONSE] = "# Got a malformed response\n", + [10] = "# Input required\n", + [11] = "# Input required\n", [40] = "# Temporary failure\n", [41] = "# Server unavailable\n", [42] = "# CGI error\n", blob - 4fe903ae320e7036cdfea34342a5ae4e04c06447 blob + 6df001b5456b94ad62d8d599ff1b3ecc122f242d --- telescope.c +++ telescope.c @@ -86,33 +86,48 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal imsg_flush(ibuf); } +static inline int +normalize_code(int n) +{ + if (n < 20) { + if (n == 10 || n == 11) + return n; + return 10; + } else if (n < 30) { + return 20; + } else if (n < 40) { + if (n == 30 || n == 31) + return n; + return 30; + } else if (n < 50) { + if (n <= 44) + return n; + return 40; + } else if (n < 60) { + if (n <= 53 || n == 59) + return n; + return 50; + } else if (n < 70) { + if (n <= 62) + return n; + return 60; + } else + return MALFORMED_RESPONSE; +} + static void handle_imsg_got_code(struct imsg *imsg, size_t datalen) { - const char *errpage; struct tab *tab; tab = tab_by_id(imsg->hdr.peerid); if (sizeof(tab->code) != datalen) die(); - memcpy(&tab->code, imsg->data, sizeof(tab->code)); - if (tab->code < 20) { - if (tab->code != 10 && tab->code != 11) - tab->code = 10; - } else if (tab->code < 30) - tab->code = 20; - else if (tab->code < 40) - tab->code = 30; - else if (tab->code < 50) - tab->code = 40; - else if (tab->code < 60) - tab->code = 50; - else - tab->code = 60; - - if (tab->code != 30) + memcpy(&tab->code, imsg->data, sizeof(tab->code)); + tab->code = normalize_code(tab->code); + if (tab->code != 30 && tab->code != 31) tab->redirect_count = 0; } @@ -125,35 +140,31 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen if (sizeof(tab->meta) <= datalen) die(); + memcpy(tab->meta, imsg->data, datalen); - if (tab->code != 30) - tab->redirect_count = 0; - - if (tab->code == 20) { - /* TODO: parse the MIME type */ + if (tab->code < 10) { /* internal errors */ + load_page_from_str(tab, err_pages[tab->code]); + } else if (tab->code < 20) { /* 1x */ + load_page_from_str(tab, err_pages[tab->code]); + ui_require_input(tab, tab->code == 11); + } else if (tab->code == 20) { + /* TODO: parse mime type */ gemtext_initparser(&tab->page); imsg_compose(ibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0); imsg_flush(ibuf); - return; - } - - if (tab->code == 30) { + } else if (tab->code < 40) { /* 3x */ tab->redirect_count++; /* TODO: make customizable? */ if (tab->redirect_count > 5) { load_page_from_str(tab, err_pages[TOO_MUCH_REDIRECTS]); - return; - } - - load_url(tab, tab->meta); - return; + } else + load_url(tab, tab->meta); + } else { /* 4x, 5x & 6x */ + load_page_from_str(tab, err_pages[tab->code]); } - - /* 4x, 5x or 6x */ - load_page_from_str(tab, err_pages[tab->code]); } static void blob - f4c658d59575f21d0f4a690189336e0a5b8833f9 blob + 9c5befa4fe3de4b7ab1ceb6ccf2bd8b5970d02e8 --- telescope.h +++ telescope.h @@ -124,6 +124,7 @@ extern const char *about_new; #define CANNOT_FETCH 0 #define TOO_MUCH_REDIRECTS 1 +#define MALFORMED_RESPONSE 2 extern const char *err_pages[70]; /* telescope.c */ @@ -136,6 +137,7 @@ void stop_tab(struct tab*); int ui_init(void); void ui_on_tab_loaded(struct tab*); void ui_on_tab_refresh(struct tab*); +void ui_require_input(struct tab*, int); void ui_end(void); /* util.c */ blob - 348b1d7722e39c463da898258334d5f696cc5011 blob + 9084aee50dda572cdeb80779074c97356803eec2 --- ui.c +++ ui.c @@ -100,6 +100,8 @@ static void cmd_tab_close(struct tab*); static void cmd_tab_new(struct tab*); static void cmd_tab_next(struct tab*); static void cmd_tab_previous(struct tab*); +static void cmd_load_url(struct tab*); +static void cmd_load_current_url(struct tab*); static void global_key_unbound(void); @@ -112,9 +114,15 @@ static void cmd_mini_kill_line(struct tab*); static void cmd_mini_abort(); static void cmd_mini_complete_and_exit(); +static void minibuffer_self_insert(void); static void eecmd_self_insert(void); static void eecmd_select(void); +static void ir_self_insert(void); +static void ir_select(void); +static void lu_self_insert(void); +static void lu_select(void); + static struct line *nth_line(struct tab*, size_t); static struct tab *current_tab(void); static void dispatch_stdio(int, short, void*); @@ -136,6 +144,7 @@ static void stop_loading_anim(struct tab*); static void load_url_in_tab(struct tab*, const char*); static void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void)); static void exit_minibuffer(void); +static void switch_to_tab(struct tab*); static void new_tab(void); static struct { int meta, key; } thiskey; @@ -217,7 +226,7 @@ static struct { char buf[1025]; size_t off, len; - char prompt[16]; + char prompt[32]; void (*donefn)(void); void (*abortfn)(void); } ministate; @@ -332,6 +341,8 @@ load_default_keys(void) global_set_key("C-x C-c", cmd_kill_telescope); global_set_key("M-x", cmd_execute_extended_command); + global_set_key("C-x C-f", cmd_load_url); + global_set_key("C-x M-f", cmd_load_current_url); global_set_key("C-x t 0", cmd_tab_close); global_set_key("C-x t 2", cmd_tab_new); @@ -617,9 +628,26 @@ cmd_tab_previous(struct tab *tab) if ((t = TAILQ_PREV(tab, tabshead, tabs)) == NULL) t = TAILQ_LAST(&tabshead, tabshead); t->flags |= TAB_CURRENT; +} + +static void +cmd_load_url(struct tab *tab) +{ + enter_minibuffer(lu_self_insert, lu_select, exit_minibuffer); + strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt)); } static void +cmd_load_current_url(struct tab *tab) +{ + enter_minibuffer(lu_self_insert, lu_select, exit_minibuffer); + strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt)); + strlcpy(ministate.buf, tab->urlstr, sizeof(ministate.buf)); + ministate.off = strlen(tab->urlstr); + ministate.len = ministate.off; +} + +static void global_key_unbound(void) { message("%s is undefined", keybuf); @@ -688,14 +716,8 @@ cmd_mini_complete_and_exit(struct tab *tab) } static void -eecmd_self_insert(void) +minibuffer_self_insert(void) { - if (thiskey.meta || isspace(thiskey.key) || - !isgraph(thiskey.key)) { - global_key_unbound(); - return; - } - if (ministate.len == sizeof(ministate.buf) -1) return; @@ -710,10 +732,65 @@ eecmd_self_insert(void) } static void +eecmd_self_insert(void) +{ + if (thiskey.meta || isspace(thiskey.key) || + !isgraph(thiskey.key)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +static void eecmd_select(void) { exit_minibuffer(); message("TODO: try to execute %s", ministate.buf); +} + +static void +ir_self_insert(void) +{ + minibuffer_self_insert(); +} + +static void +ir_select(void) +{ + char buf[1025] = {0}; + struct url url; + struct tab *tab; + + tab = current_tab(); + + exit_minibuffer(); + + /* a bit ugly but... */ + memcpy(&url, &tab->url, sizeof(tab->url)); + url_set_query(&url, ministate.buf); + url_unparse(&url, buf, sizeof(buf)); + load_url_in_tab(tab, buf); +} + +static void +lu_self_insert(void) +{ + if (thiskey.meta || isspace(thiskey.key) || + !isgraph(thiskey.key)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +static void +lu_select(void) +{ + exit_minibuffer(); + load_url_in_tab(current_tab(), ministate.buf); } static struct line * @@ -1326,6 +1403,18 @@ exit_minibuffer(void) } static void +switch_to_tab(struct tab *tab) +{ + struct tab *t; + + TAILQ_FOREACH(t, &tabshead, tabs) { + t->flags &= ~TAB_CURRENT; + } + + tab->flags |= TAB_CURRENT; +} + +static void new_tab(void) { struct tab *tab, *t; @@ -1338,12 +1427,9 @@ new_tab(void) goto err; TAILQ_INIT(&tab->s->head); - TAILQ_FOREACH(t, &tabshead, tabs) { - t->flags &= ~TAB_CURRENT; - } tab->id = tab_counter++; - tab->flags = TAB_CURRENT; + switch_to_tab(tab); if (TAILQ_EMPTY(&tabshead)) TAILQ_INSERT_HEAD(&tabshead, tab, tabs); @@ -1427,6 +1513,18 @@ ui_on_tab_refresh(struct tab *tab) } void +ui_require_input(struct tab *tab, int hide) +{ + /* TODO: hard-switching to another tab is ugly */ + switch_to_tab(tab); + + enter_minibuffer(ir_self_insert, ir_select, exit_minibuffer); + strlcpy(ministate.prompt, "Input required: ", + sizeof(ministate.prompt)); + redraw_tab(tab); +} + +void ui_end(void) { endwin(); blob - 05ca88cc830beebab8aa1f335938a5c3c2e2fdfc blob + 0400a0d9ca7426bcd82ebe78db300108c62f3e59 --- url.c +++ url.c @@ -480,6 +480,14 @@ url_resolve_from(struct url *url, const char *str, con *i = '\0'; strlcat(url->path, str, sizeof(url->path)); + return 1; +} + +int +url_set_query(struct url *url, const char *query) +{ + /* TODO: pct-encode! */ + memcpy(&url->query, query, strlen(query)+1); return 1; } @@ -497,7 +505,7 @@ url_unparse(struct url *url, char *buf, size_t len) if (*url->path != '\0') strlcat(buf, url->path, len); - if (*url->query != '?') { + if (*url->query != '\0') { strlcat(buf, "?", len); strlcat(buf, url->query, len); } blob - c7c4733788fda0b3bae0891f1541559eca62bae1 blob + 9faa9b4461810bd37a108c882ed890be35667b27 --- url.h +++ url.h @@ -31,4 +31,5 @@ struct url { int url_parse(const char*, struct url*, const char**); int url_resolve_from(struct url*, const char*, const char**); +int url_set_query(struct url*, const char*); void url_unparse(struct url*, char*, size_t);