commit 4d3785b1daec2139c584305f088d4eedce580920 from: Omar Polo date: Tue Mar 09 07:00:03 2021 UTC refactor load_url dispatch tables are cool -- semicit commit - 43a1b8d081bd3c444b70d0f1a0da23dd598c4749 commit + 4d3785b1daec2139c584305f088d4eedce580920 blob - e2e901d20a6c83134747f66d74dd1cfbf22595cb blob + fd41dd34ee49a80387c977619c17039f358dffcf --- telescope.c +++ telescope.c @@ -14,6 +14,12 @@ struct event imsgev; struct tabshead tabshead; +struct proto protos[] = { + { "gemini:", load_gemini_url }, + { "about:", load_about_url }, + { NULL, NULL }, +}; + static struct imsgbuf *ibuf; static void handle_imsg_err(struct imsg*, size_t); @@ -65,7 +71,7 @@ handle_imsg_err(struct imsg *imsg, size_t datalen) page[datalen-1] = '\0'; if (asprintf(&page, "# Error loading %s\n\n> %s\n", - tab->url, page) == -1) + tab->urlstr, page) == -1) die(); load_page_from_str(tab, page); free(page); @@ -218,49 +224,67 @@ load_page_from_str(struct tab *tab, const char *page) } void -load_url(struct tab *tab, const char *url) +load_about_url(struct tab *tab, const char *url) { - /* TODO: parsing the url here is a bit ugly. maybe store it - * in the struct tab? */ - struct url u; - const char *err; - char *page; + char *m; - if (!strcmp(url, "about:new")) { - strlcpy(tab->url, url, sizeof(tab->url)); + memset(tab->urlstr, 0, sizeof(tab->urlstr)); + memset(&tab->url, 0, sizeof(tab->url)); + + m = strchr(url, ':'); + strlcpy(tab->url.scheme, "about", sizeof(tab->url.scheme)); + strlcpy(tab->url.path, m+1, sizeof(tab->url.path)); + + if (!strcmp(url, "about:new")) load_page_from_str(tab, about_new); - return; - } + else + load_page_from_str(tab, "# not found\n"); +} - if (has_prefix(tab->url, "about:")) { - strlcpy(tab->url, url, sizeof(tab->url)); - } else { - if (!url_parse(tab->url, &u, &err)) - goto err; +void +load_gemini_url(struct tab *tab, const char *url) +{ + const char *err; + char *p; - if (!url_resolve_from(&u, url, &err)) + if (has_prefix(url, "gemini:")) { + if (!url_parse(url, &tab->url, &err)) goto err; - - /* TODO: this is nowhere good enough */ - strlcpy(tab->url, u.scheme, sizeof(tab->url)); - strlcat(tab->url, "://", sizeof(tab->url)); - strlcat(tab->url, u.host, sizeof(tab->url)); - strlcat(tab->url, "/", sizeof(tab->url)); - strlcat(tab->url, u.path, sizeof(tab->url)); + } else { + if (!url_resolve_from(&tab->url, url, &err)) + goto err; } - imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1, url, strlen(url)+1); + url_unparse(&tab->url, tab->urlstr, sizeof(tab->urlstr)); + imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1, + tab->urlstr, strlen(tab->urlstr)+1); imsg_flush(ibuf); return; err: - if (asprintf(&page, "# error resolving %s from %s\n\n> %s\n", - url, tab->url, err) == -1) + if (asprintf(&p, "#error loading %s\n>%s\n", + url, err) == -1) die(); - load_page_from_str(tab, page); - free(page); + strlcpy(tab->urlstr, url, sizeof(tab->urlstr)); + load_page_from_str(tab, p); + free(p); } +void +load_url(struct tab *tab, const char *url) +{ + struct proto *p; + + for (p = protos; p->schema != NULL; ++p) { + if (has_prefix(url, p->schema)) { + p->loadfn(tab, url); + return; + } + } + + protos[0].loadfn(tab, url); +} + int main(void) { blob - 72bda1bf3350c40fa7c7fe8783237bab8dcd518e blob + 2ca8fdf2b69ebaf2803317f281603af31265e97e --- telescope.h +++ telescope.h @@ -88,7 +88,8 @@ struct tab { uint32_t id; uint32_t flags; - char url[GEMINI_URL_LEN]; + char urlstr[GEMINI_URL_LEN]; + struct url url; int code; char meta[GEMINI_URL_LEN]; @@ -97,6 +98,19 @@ struct tab { struct ui_state *s; }; +struct proto { + const char *schema; + + /* should load the given url in the tab. Optionally, it may + * consider the given url as relative to the one already + * present in tab. It must set tab->urlstr to a serialized + * human-friendly URL. */ + void (*loadfn)(struct tab*, const char*); +}; + +/* the first is also the fallback one */ +extern struct proto protos[]; + extern struct event imsgev; /* gemini.c */ @@ -113,6 +127,8 @@ extern const char *about_new; extern const char *err_pages[70]; /* telescope.c */ +void load_about_url(struct tab*, const char*); +void load_gemini_url(struct tab*, const char*); void load_url(struct tab*, const char*); /* ui.c */ blob - 677e97baffdaf0ed7c0c09de4391105af007b7c3 blob + 1a96ed6f7968f22cf4440e7204dc8b8617a67c33 --- ui.c +++ ui.c @@ -675,7 +675,7 @@ redraw_modeline(struct tab *tab) wmove(modeline, 0, 0); wprintw(modeline, "-%c %s %s ", - spin[tab->s->loading_anim_step], mode, tab->url); + spin[tab->s->loading_anim_step], mode, tab->urlstr); getyx(modeline, y, x); getmaxyx(modeline, max_y, max_x); @@ -871,7 +871,7 @@ void ui_on_tab_loaded(struct tab *tab) { stop_loading_anim(tab); - message("Loaded %s", tab->url); + message("Loaded %s", tab->urlstr); } void blob - b7d99055862723b1ee6e5a9e62cc963169110af0 blob + 05ca88cc830beebab8aa1f335938a5c3c2e2fdfc --- url.c +++ url.c @@ -481,4 +481,24 @@ url_resolve_from(struct url *url, const char *str, con *i = '\0'; strlcat(url->path, str, sizeof(url->path)); return 1; +} + +void +url_unparse(struct url *url, char *buf, size_t len) +{ + strlcpy(buf, url->scheme, len); + strlcat(buf, "://", len); + strlcat(buf, url->host, len); + + if (*url->path == '\0' && *url->query == '\0') + return; + + strlcat(buf, "/", len); + + if (*url->path != '\0') + strlcat(buf, url->path, len); + if (*url->query != '?') { + strlcat(buf, "?", len); + strlcat(buf, url->query, len); + } } blob - 1da297cb09c85ac346bf9128b7838afb3ccb901a blob + c7c4733788fda0b3bae0891f1541559eca62bae1 --- url.h +++ url.h @@ -15,6 +15,7 @@ */ #include +#include #define GEMINI_URL_LEN 1024 @@ -30,3 +31,4 @@ struct url { int url_parse(const char*, struct url*, const char**); int url_resolve_from(struct url*, const char*, const char**); +void url_unparse(struct url*, char*, size_t);