diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 434260b20..fe91f5011 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -255,6 +255,7 @@ |<>|Dictionary file to be used by the word hints. |<>|Which implementation to use to find elements to hint. |<>|Hide unmatched hints in rapid mode. +|<>|Labels for hint characters. |<>|Leave hint mode when starting a new page load. |<>|Minimum number of characters used for hint strings. |<>|Mode to use for hints. @@ -264,7 +265,6 @@ |<>|Rounding radius (in pixels) for the edges of hints. |<>|Scatter hint key chains (like Vimium) or not (like dwb). |<>|CSS selectors used to determine which elements on a page should have hints. -|<>|Make characters in hint strings uppercase. |<>|Maximum time (in minutes) between two history items for them to be considered being from the same browsing session. |<>|Allow Escape to quit the crash reporter. |<>|Which unbound keys to forward to the webview in normal mode. @@ -3359,6 +3359,15 @@ Type: <> Default: +pass:[true]+ +[[hints.labels]] +=== hints.labels +Labels for hint characters. +To replace the deprecated `hints.uppercase` setting set `c.hints.labels = c.hints.chars.upper()` in `config.py`. + +Type: <> + +Default: empty + [[hints.leave_on_load]] === hints.leave_on_load Leave hint mode when starting a new page load. @@ -3528,14 +3537,6 @@ Default: * +pass:[[src\]]+ * +pass:[[href\]]+ -[[hints.uppercase]] -=== hints.uppercase -Make characters in hint strings uppercase. - -Type: <> - -Default: +pass:[false]+ - [[history_gap_interval]] === history_gap_interval Maximum time (in minutes) between two history items for them to be considered being from the same browsing session. diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index b3f45610d..11c7307af 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -110,10 +110,13 @@ class HintLabel(QLabel): matched: The part of the text which was typed. unmatched: The part of the text which was not typed yet. """ - if (config.cache['hints.uppercase'] and + if (config.cache['hints.labels'] and self._context.hint_mode in ['letter', 'word']): - matched = html.escape(matched.upper()) - unmatched = html.escape(unmatched.upper()) + chars = config.val.hints.chars + labels = config.val.hints.labels + table = str.maketrans(dict(zip(chars, labels))) + matched = html.escape(matched.translate(table)) + unmatched = html.escape(unmatched.translate(table)) else: matched = html.escape(matched) unmatched = html.escape(unmatched) diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index b221a70dc..164513240 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -1719,9 +1719,25 @@ hints.chars: completions: - ['asdfghjkl', "Home row"] - ['aoeuidnths', "Home row (Dvorak)"] + - ['hjkl', "Directional keys (Vim)"] + - ['hjklyubn', "Directional keys (roguelike)"] - ['abcdefghijklmnopqrstuvwxyz', "All letters"] desc: Characters used for hint strings. +hints.labels: + default: + type: + name: UniqueCharString + none_ok: true + completions: + - ['←↓↑→', "Arrows for directional keys (Vim)"] + - ['←↓↑→↖↗↙↘', "Arrows for directional keys (roguelike)"] + desc: >- + Labels for hint characters. + + To replace the removed `hints.uppercase` setting, set `c.hints.labels = + c.hints.chars.upper()` in `config.py`. + hints.dictionary: default: /usr/share/dict/words type: @@ -1875,11 +1891,6 @@ hints.selectors: desc: CSS selectors used to determine which elements on a page should have hints. -hints.uppercase: - default: false - type: Bool - desc: Make characters in hint strings uppercase. - hints.leave_on_load: default: false type: Bool diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index 3fcdd53d8..945c4ba7c 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -450,6 +450,7 @@ class YamlMigrations(QObject): self._migrate_bindings_default() self._migrate_font_default_family() self._migrate_font_replacements() + self._migrate_hints_uppercase() self._migrate_bool('tabs.favicons.show', 'always', 'never') self._migrate_bool('scrolling.bar', 'always', 'overlay') @@ -540,6 +541,23 @@ class YamlMigrations(QObject): del self._settings['bindings.default'] self.changed.emit() + def _migrate_hints_uppercase(self) -> None: + if 'hints.uppercase' not in self._settings: + return + + self._settings['hints.labels'] = {} + + for scope, val in self._settings['hints.uppercase'].items(): + if val and 'hints.chars' in self._settings: + labels = self._settings['hints.chars'][scope].upper() + self._settings['hints.labels'][scope] = labels + elif val and 'hints.chars' not in self._settings: + labels = configdata.DATA['hints.chars'].default.upper() + self._settings['hints.labels'][scope] = labels + + del self._settings['hints.uppercase'] + self.changed.emit() + def _migrate_font_default_family(self) -> None: old_name = 'fonts.monospace' new_name = 'fonts.default_family' diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py index d01a0e721..dfe66d567 100644 --- a/tests/unit/config/test_configfiles.py +++ b/tests/unit/config/test_configfiles.py @@ -866,6 +866,40 @@ class TestYamlMigrations: 'content.media.video_capture']: assert data[setting]['global'] == val + @pytest.mark.parametrize('chars, uppercase', [ + ('aoeuidnths', True), + ('abcdefghijklmnopqrstuvwxyz', True), + (None, True), + ('aoeuidnths', False), + ('abcdefghijklmnopqrstuvwxyz', False), + (None, False), + ('aoeuidnths', None), + ('abcdefghijklmnopqrstuvwxyz', None), + (None, None), + ]) + def test_hints_uppercase(self, yaml, autoconfig, chars, uppercase): + settings = {} + if chars is not None: + settings['hints.chars'] = {'global': chars} + if uppercase is not None: + settings['hints.uppercase'] = {'global': uppercase} + + autoconfig.write(settings) + + yaml.load() + yaml._save() + + data = autoconfig.read() + if uppercase: + if 'hints.chars' in data: + labels = data['hints.chars']['global'].upper() + assert data['hints.labels']['global'] == labels + else: + labels = configdata.DATA['hints.chars'].default.upper() + assert data['hints.labels']['global'] == labels + else: + assert 'hints.labels' not in data + def test_empty_pattern(self, yaml, autoconfig): valid_pattern = 'https://example.com/*' invalid_pattern = '*://*./*'