config: add url.style=none|single|double|curly|dotted|dashed

This option allows you to configure which underline style to use with
URLs.

The default is dotted. Since before this patch, URL underlines were
always plain underlines, this means the default URL underline style
has changed, from single to dotted.

Closes #2302
This commit is contained in:
Daniel Eklöf 2026-04-06 15:47:26 +02:00
parent ecf3b864e4
commit 2c454a71f1
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
8 changed files with 50 additions and 11 deletions

View file

@ -71,7 +71,20 @@
## Unreleased
### Added
* `url.style=none|single|double|curly|dotted|dashed` option added,
allowing you to configure how URL underlines are drawn. The default
is `dotted` ([#2302][2302]).
[2302]: https://codeberg.org/dnkl/foot/issues/2302
### Changed
* URL underlines are now dotted by default, instead of plain
underlines. This can be changed with the new `url.style` option.
### Deprecated
### Removed
### Fixed

View file

@ -1304,6 +1304,14 @@ parse_section_url(struct context *ctx)
else if (streq(key, "label-letters"))
return value_to_wchars(ctx, &conf->url.label_letters);
else if (streq(key, "style")) {
_Static_assert(sizeof(conf->url.style) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(
ctx, (const char *[]){"none", "single", "double", "curly", "dotted", "dashed", NULL},
(int *)&conf->url.style);
}
else if (streq(key, "osc8-underline")) {
_Static_assert(sizeof(conf->url.osc8_underline) == sizeof(int),
"enum is not 32-bit");
@ -3518,6 +3526,7 @@ config_load(struct config *conf, const char *conf_path,
.url = {
.label_letters = xc32dup(U"sadfjklewcmpgh"),
.osc8_underline = OSC8_UNDERLINE_URL_MODE,
.style = UNDERLINE_DOTTED,
},
.custom_regexes = tll_init(),
.can_shape_grapheme = fcft_caps & FCFT_CAPABILITY_GRAPHEME_SHAPING,

View file

@ -218,6 +218,15 @@ enum center_when {
CENTER_ALWAYS,
};
enum underline_style {
UNDERLINE_NONE,
UNDERLINE_SINGLE, /* Legacy underline */
UNDERLINE_DOUBLE,
UNDERLINE_CURLY,
UNDERLINE_DOTTED,
UNDERLINE_DASHED,
};
struct config {
char *conf_path;
char *term;
@ -327,6 +336,7 @@ struct config {
OSC8_UNDERLINE_URL_MODE,
OSC8_UNDERLINE_ALWAYS,
} osc8_underline;
enum underline_style style;
char *regex;
regex_t preg;

View file

@ -867,6 +867,14 @@ section.
Default: _url-mode_
*style*
The underline style to use when rendering URL underlines. This
applies to both OSC-8 underlines when *osc8-underline=always*, and
all detected URLs in URL mode. One of *none*, *single*, *double*,
*curly*, *dotted* or *dashed*.
Default: _dotted_
*label-letters*
String of characters to use when generating key sequences for URL
jump labels.

View file

@ -72,6 +72,7 @@
[url]
# launch=xdg-open ${url}
# label-letters=sadfjklewcmpgh
# style=dotted (none|single|double|curly|dotted|dashed)
# osc8-underline=url-mode
# regex=(((https?://|mailto:|ftp://|file:|ssh:|ssh://|git://|tel:|magnet:|ipfs://|ipns://|gemini://|gopher://|news:)|www\.)([0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]+|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*')+([0-9a-zA-Z/#@$&*+=~_%^\-]|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*'))

View file

@ -1171,13 +1171,16 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (cell->attrs.strikethrough)
draw_strikeout(term, pix, font, &fg, x, y, cell_cols);
if (unlikely(cell->attrs.url)) {
if (unlikely(cell->attrs.url && term->conf->url.style != UNDERLINE_NONE)) {
pixman_color_t url_color = color_hex_to_pixman(
term->conf->colors_dark.use_custom.url
? term->conf->colors_dark.url
: term->colors.table[3],
gamma_correct);
draw_underline(term, pix, font, &url_color, x, y, cell_cols);
draw_styled_underline(
term, pix, font, &url_color, term->conf->url.style,
x, y, cell_cols);
}
draw_cursor:

View file

@ -105,15 +105,6 @@ struct uri_range_data {
char *uri;
};
enum underline_style {
UNDERLINE_NONE,
UNDERLINE_SINGLE, /* Legacy underline */
UNDERLINE_DOUBLE,
UNDERLINE_CURLY,
UNDERLINE_DOTTED,
UNDERLINE_DASHED,
};
struct underline_range_data {
enum underline_style style;
enum color_source color_src;

View file

@ -632,6 +632,10 @@ test_section_url(void)
(const char *[]){"url-mode", "always"},
(int []){OSC8_UNDERLINE_URL_MODE, OSC8_UNDERLINE_ALWAYS},
(int *)&conf.url.osc8_underline);
test_enum(&ctx, &parse_section_url, "style",
6, (const char *[]){"none", "single", "double", "curly", "dotted", "dashed"},
(int []){UNDERLINE_NONE, UNDERLINE_SINGLE, UNDERLINE_DOUBLE, UNDERLINE_CURLY, UNDERLINE_DOTTED, UNDERLINE_DASHED},
(int *)&conf.url.style);
test_c32string(&ctx, &parse_section_url, "label-letters", &conf.url.label_letters);
config_free(&conf);