diff --git a/kittens/transfer/main.py b/kittens/transfer/main.py index a87bbbd1d..003720048 100644 --- a/kittens/transfer/main.py +++ b/kittens/transfer/main.py @@ -222,8 +222,16 @@ def files_for_send(cli_opts: TransferCLIOptions, args: List[str]) -> Tuple[File, return tuple(files) +class SendManager: + + def __init__(self, files: Tuple[File, ...]): + self.files = files + + def send_main(cli_opts: TransferCLIOptions, args: List[str]) -> None: - pass + print('Scanning files…') + files = files_for_send(cli_opts, args) + print(f'Found {len(files)} files and directories, requesting transfer permission…') def parse_transfer_args(args: List[str]) -> Tuple[TransferCLIOptions, List[str]]: diff --git a/kittens/tui/handler.py b/kittens/tui/handler.py index 68a7260cb..8d3195250 100644 --- a/kittens/tui/handler.py +++ b/kittens/tui/handler.py @@ -5,7 +5,7 @@ from types import TracebackType from typing import ( - Any, Callable, ContextManager, Dict, Optional, Sequence, Type, Union + Any, Callable, ContextManager, Dict, Optional, Sequence, Type, Union, TYPE_CHECKING ) from kitty.types import ParsedShortcut @@ -17,6 +17,10 @@ from kitty.typing import ( from .operations import pending_update +if TYPE_CHECKING: + from kitty.file_transmission import FileTransmissionCommand + + class Handler: image_manager_class: Optional[Type[ImageManagerType]] = None @@ -118,6 +122,9 @@ class Handler: def on_clipboard_response(self, text: str, from_primary: bool = False) -> None: pass + def on_file_transfer_response(self, ftc: 'FileTransmissionCommand') -> None: + pass + def on_capability_response(self, name: str, val: str) -> None: pass diff --git a/kittens/tui/loop.py b/kittens/tui/loop.py index 524c9cb8d..5252db73f 100644 --- a/kittens/tui/loop.py +++ b/kittens/tui/loop.py @@ -17,7 +17,8 @@ from typing import Any, Callable, Dict, Generator, List, NamedTuple, Optional from kitty.constants import is_macos from kitty.fast_data_types import ( - close_tty, normal_tty, open_tty, parse_input_from_terminal, raw_tty + FILE_TRANSFER_CODE, close_tty, normal_tty, open_tty, + parse_input_from_terminal, raw_tty ) from kitty.key_encoding import ( ALT, CTRL, PRESS, RELEASE, REPEAT, SHIFT, backspace_key, decode_key_event, @@ -308,15 +309,18 @@ class Loop: pass def _on_osc(self, osc: str) -> None: - m = re.match(r'(\d+);', osc) - if m is not None: - code = int(m.group(1)) - rest = osc[m.end():] + parts = osc.split(';', 1) + if len(parts) == 2 and parts[0].isdigit(): + code = int(parts[0]) + rest = parts[1] if code == 52: - where, rest = rest.partition(';')[::2] + where, rest = rest.split(';', 1) from_primary = 'p' in where from base64 import standard_b64decode self.handler.on_clipboard_response(standard_b64decode(rest).decode('utf-8'), from_primary) + elif code == FILE_TRANSFER_CODE: + from kitty.file_transmission import FileTransmissionCommand + self.handler.on_file_transfer_response(FileTransmissionCommand.deserialize(rest)) def _on_apc(self, apc: str) -> None: if apc.startswith('G'): diff --git a/kitty/control-codes.h b/kitty/control-codes.h index 28f6c2e35..906b4ff18 100644 --- a/kitty/control-codes.h +++ b/kitty/control-codes.h @@ -238,3 +238,6 @@ // Change cursor shape/blink #define DECSCUSR 'q' + +// File transfer OSC number +# define FILE_TRANSFER_CODE 5113 diff --git a/kitty/data-types.c b/kitty/data-types.c index fccc9bfef..c1f48ecee 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -316,6 +316,7 @@ PyInit_fast_data_types(void) { PyModule_AddIntMacro(m, DCS); PyModule_AddIntMacro(m, APC); PyModule_AddIntMacro(m, OSC); + PyModule_AddIntMacro(m, FILE_TRANSFER_CODE); return m; } diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 38ce71272..3830f9d72 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -256,6 +256,7 @@ GRAPHICS_PROGRAM: int MARK: int MARK_MASK: int OSC: int +FILE_TRANSFER_CODE: int REVERSE: int SCROLL_FULL: int SCROLL_LINE: int diff --git a/kitty/file_transmission.py b/kitty/file_transmission.py index 22ed4fed8..9fdff48c7 100644 --- a/kitty/file_transmission.py +++ b/kitty/file_transmission.py @@ -16,7 +16,7 @@ from gettext import gettext as _ from time import monotonic from typing import IO, Any, Callable, Deque, Dict, List, Optional, Tuple, Union -from kitty.fast_data_types import OSC, add_timer, get_boss +from kitty.fast_data_types import FILE_TRANSFER_CODE, OSC, add_timer, get_boss from .utils import log_error, sanitize_control_codes @@ -485,6 +485,7 @@ class FileTransmission: boss = get_boss() window = boss.window_id_map.get(self.window_id) if window is not None: + payload = f'{FILE_TRANSFER_CODE};{payload}' queued = window.screen.send_escape_code_to_child(OSC, payload) if not queued: if appendleft: diff --git a/kitty/parser.c b/kitty/parser.c index aa6e8831d..7a21a8831 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -445,7 +445,7 @@ dispatch_osc(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { START_DISPATCH DISPATCH_OSC(shell_prompt_marking); END_DISPATCH - case 5113: + case FILE_TRANSFER_CODE: START_DISPATCH DISPATCH_OSC(file_transmission); END_DISPATCH