From e31a5e4e076e61d79a5b486ab85167b9bec652b2 Mon Sep 17 00:00:00 2001 From: Hassan Raza Date: Fri, 28 Aug 2026 11:49:17 +0500 Subject: [PATCH] Fix empty hints selection handling --- kittens/hints/main.py | 2 ++ kitty_tests/hints.py | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/kittens/hints/main.py b/kittens/hints/main.py index 05906c5f3..8da6c1637 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -366,6 +366,8 @@ def handle_result(args: list[str], data: dict[str, Any], target_window_id: int, if m: matches.append(m) groupdicts.append(g) + if not matches: + return joiner = data['multiple_joiner'] try: is_int: int | None = int(joiner) diff --git a/kitty_tests/hints.py b/kitty_tests/hints.py index 678ba6b89..9fea419a6 100644 --- a/kitty_tests/hints.py +++ b/kitty_tests/hints.py @@ -2,7 +2,7 @@ # License: GPL v3 Copyright: 2026, Kovid Goyal from typing import Any -from unittest.mock import Mock +from unittest.mock import Mock, patch from kittens.hints.main import handle_result @@ -10,6 +10,42 @@ from .base import BaseTest class TestHints(BaseTest): + def test_multiple_selection_actions(self): + for matches in ([], [''], ['alpha', 'beta']): + for joiner, expected in (('auto', 'alpha beta'), ('json', '[\n\t"alpha",\n\t"beta"\n]'), ('0', 'alpha'), ('-1', 'beta')): + with self.subTest(matches=matches, joiner=joiner): + boss: Any = Mock() + window = Mock() + boss.window_id_map = {1: window} + data = { + 'customize_processing': '', + 'type': 'word', + 'programs': ['@', '*', '@test', '-'], + 'match': matches, + 'groupdicts': [{} for _ in matches], + 'multiple_joiner': joiner, + } + with patch('kittens.hints.main.set_clipboard_string') as clipboard, patch('kittens.hints.main.set_primary_selection') as primary: + handle_result([], data, 1, boss) + if any(matches): + clipboard.assert_called_once_with(expected) + primary.assert_called_once_with(expected) + boss.set_clipboard_buffer.assert_called_once_with('test', expected) + window.paste_text.assert_called_once_with(expected) + else: + clipboard.assert_not_called() + primary.assert_not_called() + boss.set_clipboard_buffer.assert_not_called() + window.paste_text.assert_not_called() + + def test_custom_handler_receives_empty_selection(self): + boss: Any = Mock() + custom_handler = Mock() + data = {'customize_processing': 'custom.py', 'type': 'word', 'match': [], 'groupdicts': [], 'extra_cli_args': ['extra']} + with patch('kittens.hints.main.load_custom_processor', return_value={'handle_result': custom_handler}): + handle_result([], data, 1, boss) + custom_handler.assert_called_once_with([], data, 1, boss, ['extra']) + def test_named_groups_are_passed_to_program(self): boss: Any = Mock() boss.window_id_map = {}