hints kitten: Allow clicking on matched text to select it in addition to typing the hint

This commit is contained in:
Kovid Goyal
2024-05-14 15:20:18 +05:30
parent 38fed8b391
commit 8c1e365eb5
8 changed files with 69 additions and 9 deletions

View File

@@ -3,6 +3,7 @@
package hints
import (
"encoding/json"
"fmt"
"io"
"os"
@@ -183,7 +184,8 @@ func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
} else {
mark_text = mark_text[len(hint):]
}
return hint_style(hint) + text_style(mark_text)
ans := hint_style(hint) + text_style(mark_text)
return fmt.Sprintf("\x1b]8;;mark:%d\a%s\x1b]8;;\a", m.Index, ans)
}
render := func() string {
@@ -230,6 +232,30 @@ func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
draw_screen()
return nil
}
lp.OnRCResponse = func(data []byte) error {
var r struct {
Type string
Mark int
}
if err := json.Unmarshal(data, &r); err != nil {
return err
}
if r.Type == "mark_activated" {
if m, ok := index_map[r.Mark]; ok {
chosen = append(chosen, m)
if o.Multiple {
ignore_mark_indices.Add(m.Index)
reset()
} else {
lp.Quit(0)
return nil
}
}
}
return nil
}
lp.OnText = func(text string, _, _ bool) error {
changed := false
for _, ch := range text {

View File

@@ -9,7 +9,7 @@ from kitty.cli_stub import HintsCLIOptions
from kitty.clipboard import set_clipboard_string, set_primary_selection
from kitty.constants import website_url
from kitty.fast_data_types import get_options
from kitty.typing import BossType
from kitty.typing import BossType, WindowType
from kitty.utils import get_editor, resolve_custom_file
from ..tui.handler import result_handler
@@ -312,7 +312,14 @@ def linenum_handle_result(args: List[str], data: Dict[str, Any], target_window_i
}[action])(*cmd)
@result_handler(type_of_input='screen-ansi', has_ready_notification=True)
def on_mark_clicked(boss: BossType, window: WindowType, url: str, hyperlink_id: int, cwd: str) -> bool:
if url.startswith('mark:'):
window.send_cmd_response({'Type': 'mark_activated', 'Mark': int(url[5:])})
return True
return False
@result_handler(type_of_input='screen-ansi', has_ready_notification=True, open_url_handler=on_mark_clicked)
def handle_result(args: List[str], data: Dict[str, Any], target_window_id: int, boss: BossType) -> None:
cp = data['customize_processing']
if data['type'] == 'linenum':

View File

@@ -59,7 +59,10 @@ def import_kitten_main_module(config_dir: str, kitten: str) -> Dict[str, Any]:
kitten = resolved_kitten(kitten)
m = importlib.import_module(f'kittens.{kitten}.main')
return {'start': getattr(m, 'main'), 'end': getattr(m, 'handle_result', lambda *a, **k: None)}
return {
'start': getattr(m, 'main'),
'end': getattr(m, 'handle_result', lambda *a, **k: None),
}
def create_kitten_handler(kitten: str, orig_args: List[str]) -> Any:
@@ -70,6 +73,7 @@ def create_kitten_handler(kitten: str, orig_args: List[str]) -> Any:
setattr(ans, 'type_of_input', getattr(m['end'], 'type_of_input', None))
setattr(ans, 'no_ui', getattr(m['end'], 'no_ui', False))
setattr(ans, 'has_ready_notification', getattr(m['end'], 'has_ready_notification', False))
setattr(ans, 'open_url_handler', getattr(m['end'], 'open_url_handler', None))
return ans

View File

@@ -21,6 +21,7 @@ from kitty.typing import (
MouseEvent,
ScreenSize,
TermManagerType,
WindowType,
)
from .operations import MouseTracking, pending_update
@@ -29,6 +30,9 @@ if TYPE_CHECKING:
from kitty.file_transmission import FileTransmissionCommand
OpenUrlHandler = Optional[Callable[[BossType, WindowType, str, int, str], bool]]
class ButtonEvent(NamedTuple):
mouse_event: MouseEvent
timestamp: float
@@ -223,23 +227,26 @@ class HandleResult:
type_of_input: Optional[str] = None
no_ui: bool = False
def __init__(self, impl: Callable[..., Any], type_of_input: Optional[str], no_ui: bool, has_ready_notification: bool):
def __init__(self, impl: Callable[..., Any], type_of_input: Optional[str], no_ui: bool, has_ready_notification: bool, open_url_handler: OpenUrlHandler):
self.impl = impl
self.no_ui = no_ui
self.type_of_input = type_of_input
self.has_ready_notification = has_ready_notification
self.open_url_handler = open_url_handler
def __call__(self, args: Sequence[str], data: Any, target_window_id: int, boss: BossType) -> Any:
return self.impl(args, data, target_window_id, boss)
def result_handler(
type_of_input: Optional[str] = None,
no_ui: bool = False,
has_ready_notification: bool = Handler.overlay_ready_report_needed
has_ready_notification: bool = Handler.overlay_ready_report_needed,
open_url_handler: OpenUrlHandler = None,
) -> Callable[[Callable[..., Any]], HandleResult]:
def wrapper(impl: Callable[..., Any]) -> HandleResult:
return HandleResult(impl, type_of_input, no_ui, has_ready_notification)
return HandleResult(impl, type_of_input, no_ui, has_ready_notification, open_url_handler)
return wrapper