diff --git a/docs/changelog.rst b/docs/changelog.rst index 9fe4b9683..582261d90 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -10,6 +10,9 @@ To update |kitty|, :doc:`follow the instructions `. - A new :opt:`adjust_baseline` option to adjust the vertical alignment of text inside a line (:pull:`3734`) +- A new opt:`url_excluded_characters` option to exclude additional characters + when detecting URLs under the mouse (:pull:`3738`) + - Fix a regression in 0.21.0 that broke rendering of private use unicode symbols followed by spaces, when they also exist not followed by spaces (:iss:`3729`) diff --git a/kitty/options/definition.py b/kitty/options/definition.py index ab55b9f5c..0e510aa54 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -381,9 +381,8 @@ 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. +Additional characters to be disallowed from URLs, when detecting URLs under the +mouse cursor. By default, all characters legal in URLs are allowed. ''' ) diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index 1eab9215b..8e2ce4bf4 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -127,7 +127,7 @@ 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++) { + for (size_t i = 0; i < MIN((size_t)PyUnicode_GET_LENGTH(chars), arraysz(opts->url_excluded_characters)); i++) { opts->url_excluded_characters[i] = PyUnicode_READ(PyUnicode_KIND(chars), PyUnicode_DATA(chars), i); } opts->url_excluded_characters_count = PyUnicode_GET_LENGTH(chars); @@ -136,7 +136,7 @@ url_excluded_characters(PyObject *chars, Options *opts) { 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; } - for (size_t i = 0; i < MIN((size_t)PyUnicode_GET_LENGTH(chars), sizeof(opts->select_by_word_characters)/sizeof(opts->select_by_word_characters[0])); i++) { + for (size_t i = 0; i < MIN((size_t)PyUnicode_GET_LENGTH(chars), arraysz(opts->select_by_word_characters)); i++) { opts->select_by_word_characters[i] = PyUnicode_READ(PyUnicode_KIND(chars), PyUnicode_DATA(chars), i); } opts->select_by_word_characters_count = PyUnicode_GET_LENGTH(chars); diff --git a/kitty/unicode-data.h b/kitty/unicode-data.h index 26d1d5d23..89fe8605a 100644 --- a/kitty/unicode-data.h +++ b/kitty/unicode-data.h @@ -12,11 +12,17 @@ bool is_P_category(char_type); char_type codepoint_for_mark(combining_type m); combining_type mark_for_codepoint(char_type c); +static inline bool +is_excluded_from_url(uint32_t ch) { + for (size_t i = 0; i < OPT(url_excluded_characters_count); i++) { + if (ch == OPT(url_excluded_characters)[i]) return true; + } + return false; +} + 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); + return ch && !is_CZ_category(ch) && !is_excluded_from_url(ch); } static inline bool