From 2074f8b6563b7a6331c94a9231cd5b5af8bd7ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 14 Feb 2021 21:29:22 +0100 Subject: [PATCH] urls: OSC-8 URLs can now optionally be underlined outside of url-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new configuration option, ‘osc8-underline=url-mode|always’. When set to ‘url-mode’, OSC-8 URLs are only highlighted (i.e. underlined) in url-mode, just like auto-detected URLs. When set to ‘always’, they are always underlined, regardless of mode, and regardless of their other attributes. This is implemented by tagging collected URLs with a boolean, instructing urls_render() and urls_reset() whether they should update the cells’ ‘url’ attribute or not. The OSC-8 collecter sets this based on the value of ‘osc8-underline’. Finally, when closing an OSC-8 URL, the cells are immediately tagged with the ‘url’ attribute if ‘osc8-underline’ is set to ‘always’. --- config.c | 15 +++++++++++++++ config.h | 5 +++++ doc/foot.ini.5.scd | 14 +++++++++++++- foot.ini | 1 + terminal.c | 14 +++++++++++++- terminal.h | 1 + url-mode.c | 18 +++++++++++++++++- 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/config.c b/config.c index c2eaf382..d7d2c3a1 100644 --- a/config.c +++ b/config.c @@ -791,6 +791,19 @@ parse_section_main(const char *key, const char *value, struct config *conf, return false; } + else if (strcmp(key, "osc8-underline") == 0) { + if (strcmp(value, "url-mode") == 0) + conf->osc8_underline = OSC8_UNDERLINE_URL_MODE; + else if (strcmp(value, "always") == 0) + conf->osc8_underline = OSC8_UNDERLINE_URL_MODE; + else { + LOG_AND_NOTIFY_ERR( + "%s:%u: [default]: %s: invalid 'osc8-underline'; " + "must be one of 'url-mode', or 'always'", path, lineno, value); + return false; + } + } + else { LOG_AND_NOTIFY_ERR("%s:%u: [default]: %s: invalid key", path, lineno, key); return false; @@ -2243,6 +2256,8 @@ config_load(struct config *conf, const char *conf_path, .argv = NULL, }, + .osc8_underline = OSC8_UNDERLINE_ALWAYS, + .tweak = { .fcft_filter = FCFT_SCALING_FILTER_LANCZOS3, .allow_overflowing_double_width_glyphs = true, diff --git a/config.h b/config.h index 69930ec0..e8d15859 100644 --- a/config.h +++ b/config.h @@ -205,6 +205,11 @@ struct config { struct config_spawn_template notify; struct config_spawn_template url_launch; + enum { + OSC8_UNDERLINE_URL_MODE, + OSC8_UNDERLINE_ALWAYS, + } osc8_underline; + struct { enum fcft_scaling_filter fcft_filter; bool allow_overflowing_double_width_glyphs; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index cdcdcfaa..3108c750 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -241,13 +241,25 @@ in this order: Clipboard target to automatically copy selected text to. One of *none*, *primary*, *clipboard* or *both*. Default: _primary_. - *workers* Number of threads to use for rendering. Set to 0 to disable multithreading. Default: the number of available logical CPUs (including SMT). Note that this is not always the best value. In some cases, the number of physical _cores_ is better. +*osc8-underline* + When to underline OSC-8 URLs. Possible values are *url-mode* and + *always*. + + When set to *url-mode*, OSC-8 URLs are only highlighted in URL + mode, just like auto-detected URLs. + + When set to *always*, OSC-8 URLs are always highlighted, + regardless of their other attributes (bold, italic etc). Note that + this does _not_ make them clickable. + + Default: _url-mode_ + # SECTION: scrollback diff --git a/foot.ini b/foot.ini index 1b309210..8ea060c9 100644 --- a/foot.ini +++ b/foot.ini @@ -29,6 +29,7 @@ # jump-label-letters=sadfjklewcmpgh # selection-target=primary # workers= +# osc8-underline=url-mode [scrollback] # lines=1000 diff --git a/terminal.c b/terminal.c index ce311c3d..3710f005 100644 --- a/terminal.c +++ b/terminal.c @@ -3049,13 +3049,25 @@ term_osc8_close(struct terminal *term) do { int end_col = r == end.row ? end.col : term->cols - 1; + struct row *row = term->grid->rows[r]; + + switch (term->conf->osc8_underline) { + case OSC8_UNDERLINE_ALWAYS: + for (int c = start_col; c <= end_col; c++) + row->cells[c].attrs.url = true; + break; + + case OSC8_UNDERLINE_URL_MODE: + break; + } + struct row_uri_range range = { .start = start_col, .end = end_col, .id = term->vt.osc8.id, .uri = xstrdup(term->vt.osc8.uri), }; - grid_row_add_uri_range(term->grid->rows[r], range); + grid_row_add_uri_range(row, range); start_col = 0; } while (r++ != end.row); diff --git a/terminal.h b/terminal.h index 7d6d0616..acff9d06 100644 --- a/terminal.h +++ b/terminal.h @@ -256,6 +256,7 @@ struct url { struct coord start; struct coord end; enum url_action action; + bool url_mode_dont_change_url_attr; /* Entering/exiting URL mode doesn’t touch the cells’ attr.url */ }; typedef tll(struct url) url_list_t; diff --git a/url-mode.c b/url-mode.c index 09e170e6..a441aa86 100644 --- a/url-mode.c +++ b/url-mode.c @@ -374,6 +374,18 @@ UNIGNORE_WARNINGS static void osc8_uris(const struct terminal *term, enum url_action action, url_list_t *urls) { + bool dont_touch_url_attr = false; + + switch (term->conf->osc8_underline) { + case OSC8_UNDERLINE_URL_MODE: + dont_touch_url_attr = false; + break; + + case OSC8_UNDERLINE_ALWAYS: + dont_touch_url_attr = true; + break; + } + for (int r = 0; r < term->rows; r++) { const struct row *row = grid_row_in_view(term->grid, r); @@ -396,7 +408,8 @@ osc8_uris(const struct terminal *term, enum url_action action, url_list_t *urls) .url = xstrdup(it->item.uri), .start = start, .end = end, - .action = action})); + .action = action, + .url_mode_dont_change_url_attr = dont_touch_url_attr})); } } } @@ -542,6 +555,9 @@ urls_assign_key_combos(const struct config *conf, url_list_t *urls) static void tag_cells_for_url(struct terminal *term, const struct url *url, bool value) { + if (url->url_mode_dont_change_url_attr) + return; + const struct coord *start = &url->start; const struct coord *end = &url->end;