Add url_excluded_characters option to exclude characters from URLs.

This option, like select_by_word_characters, is a set of characters, but
for which to *exclude* from URL parsing. See
https://github.com/kovidgoyal/kitty/issues/3688#issuecomment-862711148.
This commit is contained in:
Radu Butoi 2021-06-16 23:05:47 -04:00
parent 9ec1c28b35
commit 5ee0651f56
7 changed files with 42 additions and 0 deletions

View File

@ -378,6 +378,15 @@ are still clickable.
'''
)
opt('url_excluded_characters', '',
ctype='!url_excluded_characters',
long_text='''
Characters not considered part of a URL under the mouse. In addition to these
characters any character that is marked as the unicode C and Z categories will
be excluded.
'''
)
opt('copy_on_select', 'no',
option_type='copy_on_select',
long_text='''

View File

@ -1206,6 +1206,9 @@ class Parser:
def url_color(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['url_color'] = to_color(val)
def url_excluded_characters(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['url_excluded_characters'] = str(val)
def url_prefixes(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['url_prefixes'] = url_prefixes(val)

View File

@ -265,6 +265,19 @@ convert_from_opts_detect_urls(PyObject *py_opts, Options *opts) {
Py_DECREF(ret);
}
static void
convert_from_python_url_excluded_characters(PyObject *val, Options *opts) {
url_excluded_characters(val, opts);
}
static void
convert_from_opts_url_excluded_characters(PyObject *py_opts, Options *opts) {
PyObject *ret = PyObject_GetAttrString(py_opts, "url_excluded_characters");
if (ret == NULL) return;
convert_from_python_url_excluded_characters(ret, opts);
Py_DECREF(ret);
}
static void
convert_from_python_select_by_word_characters(PyObject *val, Options *opts) {
select_by_word_characters(val, opts);
@ -931,6 +944,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
if (PyErr_Occurred()) return false;
convert_from_opts_detect_urls(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_url_excluded_characters(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_select_by_word_characters(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_click_interval(py_opts, opts);

View File

@ -124,6 +124,15 @@ url_prefixes(PyObject *up, Options *opts) {
}
}
static void
url_excluded_characters(PyObject *chars, Options *opts) {
if (!PyUnicode_Check(chars)) { PyErr_SetString(PyExc_TypeError, "url_excluded_characters must be a string"); return; }
for (size_t i = 0; i < MIN((size_t)PyUnicode_GET_LENGTH(chars), sizeof(opts->url_excluded_characters)/sizeof(opts->url_excluded_characters[0])); i++) {
opts->url_excluded_characters[i] = PyUnicode_READ(PyUnicode_KIND(chars), PyUnicode_DATA(chars), i);
}
opts->url_excluded_characters_count = PyUnicode_GET_LENGTH(chars);
}
static void
select_by_word_characters(PyObject *chars, Options *opts) {
if (!PyUnicode_Check(chars)) { PyErr_SetString(PyExc_TypeError, "select_by_word_characters must be a string"); return; }

View File

@ -417,6 +417,7 @@ option_names = ( # {{{
'touch_scroll_multiplier',
'update_check_interval',
'url_color',
'url_excluded_characters',
'url_prefixes',
'url_style',
'visual_bell_duration',
@ -546,6 +547,7 @@ class Options:
touch_scroll_multiplier: float = 1.0
update_check_interval: float = 24.0
url_color: Color = Color(red=0, green=135, blue=189)
url_excluded_characters: str = ''
url_prefixes: typing.Tuple[str, ...] = ('http', 'https', 'file', 'ftp', 'gemini', 'irc', 'gopher', 'mailto', 'news', 'git')
url_style: int = 3
visual_bell_duration: float = 0

View File

@ -70,6 +70,7 @@ typedef struct {
UrlPrefix *values;
size_t num, max_prefix_len;
} url_prefixes;
char_type url_excluded_characters[256]; size_t url_excluded_characters_count;
bool detect_urls;
bool tab_bar_hidden;
double font_size;

View File

@ -1,5 +1,6 @@
#pragma once
#include "data-types.h"
#include "state.h"
#define VS15 1285
#define VS16 1286
@ -13,6 +14,8 @@ combining_type mark_for_codepoint(char_type c);
static inline bool
is_url_char(uint32_t ch) {
for (size_t i = 0; i < OPT(url_excluded_characters_count); i++)
if (ch == OPT(url_excluded_characters)[i]) return false;
return ch && !is_CZ_category(ch);
}