diff --git a/docs/kittens/choose-files.rst b/docs/kittens/choose-files.rst index d20696e0d..a68246bd8 100644 --- a/docs/kittens/choose-files.rst +++ b/docs/kittens/choose-files.rst @@ -30,6 +30,17 @@ press :kbd:`Enter`. You can change the current directory by instead selecting a directory and pressing the :kbd:`Tab` key. :kbd:`Shift+Tab` goes up one directory level. +If you want to choose a file and insert it into your shell prompt at the +current cursor position, press :sc:`insert_chosen_file` for files or +:sc:`insert_chosen_directory` for directories. Similarly, to have a file +chosen in a command line, use, or example:: + + some-command $(kitten choose-file) + +Note, that the above may not work in a complicated pipeline as it performs +terminal I/O and needs exclusive access to the ttyy device while choosing a +file. + Creating shortcuts to favorite/frequently used directories ------------------------------------------------------------ diff --git a/kittens/choose_files/main.go b/kittens/choose_files/main.go index 28f2b9b01..19017940c 100644 --- a/kittens/choose_files/main.go +++ b/kittens/choose_files/main.go @@ -772,18 +772,22 @@ func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) { } return } - m := strings.Join(selections, "\n") - if opts.OutputFormat == "json" { - payload["paths"] = selections - if current_filter != "" { - payload["current_filter"] = current_filter - } - b, _ := json.MarshalIndent(payload, "", " ") - m = string(b) + payload["paths"] = selections + if current_filter != "" { + payload["current_filter"] = current_filter } - fmt.Print(m) - if opts.WriteOutputTo != "" { - os.WriteFile(opts.WriteOutputTo, []byte(m), 0600) + if tui.RunningAsUI() { + fmt.Println(tui.KittenOutputSerializer()(payload)) + } else { + m := strings.Join(selections, "\n") + if opts.OutputFormat == "json" { + b, _ := json.MarshalIndent(payload, "", " ") + m = string(b) + } + fmt.Print(m) + if opts.WriteOutputTo != "" { + os.WriteFile(opts.WriteOutputTo, []byte(m), 0600) + } } } diff --git a/kittens/choose_files/main.py b/kittens/choose_files/main.py index f0657499b..ff8270c78 100644 --- a/kittens/choose_files/main.py +++ b/kittens/choose_files/main.py @@ -2,10 +2,14 @@ # License: GPLv3 Copyright: 2025, Kovid Goyal import sys +from typing import Any from kitty.conf.types import Definition from kitty.constants import appname from kitty.simple_cli_definitions import CONFIG_HELP, CompletionSpec +from kitty.typing_compat import BossType + +from ..tui.handler import result_handler definition = Definition( '!kittens.choose_files', @@ -123,6 +127,32 @@ egr() # }}} def main(args: list[str]) -> None: raise SystemExit('This must be run as kitten choose-files') +def relative_path_if_possible(path: str, base: str) -> str: + if not base or not path: + return path + from contextlib import suppress + from pathlib import Path + b = Path(base) + q = Path(path) + with suppress(ValueError): + return str(q.relative_to(b)) + return path + + +@result_handler(has_ready_notification=True) +def handle_result(args: list[str], data: dict[str, Any], target_window_id: int, boss: BossType) -> None: + paths: list[str] = data.get('paths', []) + if not paths: + boss.ring_bell_if_allowed() + return + path = paths[0] + w = boss.window_id_map.get(target_window_id) + if w is not None: + cwd = w.cwd_of_child + if cwd: + path = relative_path_if_possible(path, cwd) + w.paste_text(path) + usage = '[directory to start choosing files in]' diff --git a/kittens/hints/main.py b/kittens/hints/main.py index 48cd50816..86b81b575 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -407,9 +407,7 @@ def handle_result(args: list[str], data: dict[str, Any], target_window_id: int, if __name__ == '__main__': # Run with kitty +kitten hints - ans = main(sys.argv) - if ans: - print(ans) + main(sys.argv) elif __name__ == '__doc__': cd = sys.cli_docs # type: ignore cd['usage'] = usage diff --git a/kitty/options/definition.py b/kitty/options/definition.py index ef7e17af2..a5be71490 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -4363,6 +4363,23 @@ map('Open selected path', long_text='Select a path/filename and open it with the default open program.' ) +map('Insert chosen file', + 'insert_chosen_file kitty_mod+p>c kitten choose-files', + long_text=''' +Select a file using the :doc:`choose-files ` kitten and insert +it into the terminal. +''' + ) + +map('Insert chosen directory', + 'insert_chosen_directory kitty_mod+p>d kitten choose-files --mode=dir', + long_text=''' +Select a directory using the :doc:`choose-files ` kitten and insert +it into the terminal. +''' + ) + + map('Insert selected line', 'insert_selected_line kitty_mod+p>l kitten hints --type line --program -', long_text=''' diff --git a/kitty/options/types.py b/kitty/options/types.py index c15a34e08..aae01e95a 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -929,6 +929,10 @@ defaults.map = [ KeyDefinition(is_sequence=True, trigger=SingleKey(mods=256, key=112), rest=(SingleKey(key=102),), definition='kitten hints --type path --program -'), # open_selected_path KeyDefinition(is_sequence=True, trigger=SingleKey(mods=256, key=112), rest=(SingleKey(mods=1, key=102),), definition='kitten hints --type path'), + # insert_chosen_file + KeyDefinition(is_sequence=True, trigger=SingleKey(mods=256, key=112), rest=(SingleKey(key=99),), definition='kitten choose-files'), + # insert_chosen_directory + KeyDefinition(is_sequence=True, trigger=SingleKey(mods=256, key=112), rest=(SingleKey(key=100),), definition='kitten choose-files --mode=dir'), # insert_selected_line KeyDefinition(is_sequence=True, trigger=SingleKey(mods=256, key=112), rest=(SingleKey(key=108),), definition='kitten hints --type line --program -'), # insert_selected_word diff --git a/shell-integration/ssh/kitty b/shell-integration/ssh/kitty index 8bb0a9176..08e30e9d2 100755 --- a/shell-integration/ssh/kitty +++ b/shell-integration/ssh/kitty @@ -24,7 +24,7 @@ exec_kitty() { is_wrapped_kitten() { - wrapped_kittens="clipboard icat hyperlinked_grep ask hints unicode_input ssh themes diff show_key transfer query_terminal" + wrapped_kittens="clipboard icat hyperlinked_grep ask hints unicode_input ssh themes diff show_key transfer query_terminal choose-files" [ -n "$1" ] && { case " $wrapped_kittens " in *" $1 "*) printf "%s" "$1" ;;