config: add url.protocols

This makes the protocols recognized by auto-detected URLs
configurable.

Closes #531
This commit is contained in:
Daniel Eklöf 2021-05-20 17:58:06 +02:00
parent 0f483d65ce
commit 53516aceec
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 85 additions and 19 deletions

View file

@ -44,6 +44,8 @@
and a new `command` action to run an arbitrary command.
(https://codeberg.org/dnkl/foot/pulls/483)
* Dedicated `[url]` section to config.
* `[url].protocols` option to `foot.ini`
(https://codeberg.org/dnkl/foot/issues/531).
* Support for setting the full 256 color palette in foot.ini
(https://codeberg.org/dnkl/foot/issues/489)
* XDG activation support, will be used by `[bell].urgent` when

View file

@ -1001,6 +1001,47 @@ parse_section_url(const char *key, const char *value, struct config *conf,
}
}
else if (strcmp(key, "protocols") == 0) {
for (size_t i = 0; i < conf->url.prot_count; i++)
free(conf->url.protocols[i]);
free(conf->url.protocols);
conf->url.max_prot_len = 0;
conf->url.prot_count = 0;
conf->url.protocols = NULL;
char *copy = xstrdup(value);
for (char *prot = strtok(copy, " ");
prot != NULL;
prot = strtok(NULL, " "))
{
size_t chars = mbstowcs(NULL, prot, 0);
if (chars == (size_t)-1) {
LOG_AND_NOTIFY_ERRNO(
"%s:%u: [url]: protocols: invalid protocol name: %s",
path, lineno, prot);
return false;
}
conf->url.prot_count++;
conf->url.protocols = xrealloc(
conf->url.protocols,
conf->url.prot_count * sizeof(conf->url.protocols[0]));
size_t idx = conf->url.prot_count - 1;
conf->url.protocols[idx] = xmalloc((chars + 1 + 3) * sizeof(wchar_t));
mbstowcs(conf->url.protocols[idx], prot, chars + 1);
wcscpy(&conf->url.protocols[idx][chars], L"://");
size_t len = chars + 3; /* Include the "://" */
if (len > conf->url.max_prot_len)
conf->url.max_prot_len = len;
}
free(copy);
}
else {
LOG_AND_NOTIFY_ERR("%s:%d: [url]: %s: invalid key", path, lineno, key);
return false;
@ -2527,6 +2568,27 @@ config_load(struct config *conf, const char *conf_path,
conf->url.launch.raw_cmd = xstrdup("xdg-open ${url}");
tokenize_cmdline(conf->url.launch.raw_cmd, &conf->url.launch.argv);
static const wchar_t *url_protocols[] = {
L"http://",
L"https://",
L"ftp://",
L"ftps://",
L"file://",
L"gemini://",
L"gopher://",
};
conf->url.protocols = xmalloc(
ALEN(url_protocols) * sizeof(conf->url.protocols[0]));
conf->url.prot_count = ALEN(url_protocols);
conf->url.max_prot_len = 0;
for (size_t i = 0; i < ALEN(url_protocols); i++) {
size_t len = wcslen(url_protocols[i]);
if (len > conf->url.max_prot_len)
conf->url.max_prot_len = len;
conf->url.protocols[i] = xwcsdup(url_protocols[i]);
}
tll_foreach(*initial_user_notifications, it) {
tll_push_back(conf->notifications, it->item);
tll_remove(*initial_user_notifications, it);
@ -2644,6 +2706,10 @@ config_free(struct config conf)
free(conf.url.label_letters);
free_spawn_template(&conf.url.launch);
for (size_t i = 0; i < conf.url.prot_count; i++)
free(conf.url.protocols[i]);
free(conf.url.protocols);
key_binding_list_free(&conf.bindings.key);
key_binding_list_free(&conf.bindings.search);
key_binding_list_free(&conf.bindings.url);

View file

@ -135,6 +135,9 @@ struct config {
OSC8_UNDERLINE_ALWAYS,
} osc8_underline;
wchar_t **protocols;
size_t prot_count;
size_t max_prot_len;
} url;
struct {

View file

@ -323,6 +323,13 @@ in this order:
String of characters to use when generating key sequences for URL
jump labels. Default: _sadfjklewcmpgh_.
*protocols*
List of protocols (schemes) that should be recognized in URL
mode. Note that only auto-detected URLs are affected by this
option. OSC-8 URLs are always enabled, regardless of
protocol. Default: _http https ftp ftps file gemini gopher_.
# SECTION: cursor
This section controls the cursor style and color. Note that

View file

@ -45,6 +45,8 @@
# launch=xdg-open ${url}
# label-letters=sadfjklewcmpgh
# osc8-underline=url-mode
# protocols = http https ftp ftps file gemini gopher
[cursor]
# style=block
# color=111111 dcdccc

View file

@ -212,23 +212,9 @@ static void
auto_detected(const struct terminal *term, enum url_action action,
url_list_t *urls)
{
static const wchar_t *const prots[] = {
L"http://",
L"https://",
L"ftp://",
L"ftps://",
L"file://",
L"gemini://",
L"gopher://",
};
size_t max_prot_len = 0;
for (size_t i = 0; i < ALEN(prots); i++) {
size_t len = wcslen(prots[i]);
if (len > max_prot_len)
max_prot_len = len;
}
const struct config *conf = term->conf;
size_t max_prot_len = conf->url.max_prot_len;
wchar_t proto_chars[max_prot_len];
struct coord proto_start[max_prot_len];
size_t proto_char_count = 0;
@ -266,15 +252,15 @@ auto_detected(const struct terminal *term, enum url_action action,
proto_start[max_prot_len - 1] = (struct coord){c, r};
proto_char_count++;
for (size_t i = 0; i < ALEN(prots); i++) {
size_t prot_len = wcslen(prots[i]);
for (size_t i = 0; i < conf->url.prot_count; i++) {
size_t prot_len = wcslen(conf->url.protocols[i]);
if (proto_char_count < prot_len)
continue;
const wchar_t *proto = &proto_chars[max_prot_len - prot_len];
if (wcsncasecmp(prots[i], proto, prot_len) == 0) {
if (wcsncasecmp(conf->url.protocols[i], proto, prot_len) == 0) {
state = STATE_URL;
start = proto_start[max_prot_len - prot_len];