Delegate kitty +kitten clipboard to kitty-tool
This commit is contained in:
parent
5eb2142d70
commit
375fa73826
@ -1,20 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import codecs
|
||||
import io
|
||||
import os
|
||||
import select
|
||||
import sys
|
||||
from typing import List, NoReturn, Optional
|
||||
|
||||
from kitty.cli import parse_args
|
||||
from kitty.cli_stub import ClipboardCLIOptions
|
||||
from kitty.fast_data_types import parse_input_from_terminal
|
||||
|
||||
from ..tui.operations import (
|
||||
raw_mode, request_from_clipboard, write_to_clipboard
|
||||
)
|
||||
|
||||
OPTIONS = r'''
|
||||
--get-clipboard
|
||||
@ -45,103 +32,8 @@ popup, see :opt:`clipboard_control` for details.
|
||||
'''
|
||||
|
||||
usage = ''
|
||||
got_capability_response = False
|
||||
got_clipboard_response = False
|
||||
clipboard_contents = ''
|
||||
clipboard_from_primary = False
|
||||
|
||||
|
||||
def ignore(x: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def on_text(x: str) -> None:
|
||||
if '\x03' in x:
|
||||
raise KeyboardInterrupt()
|
||||
if '\x04' in x:
|
||||
raise EOFError()
|
||||
|
||||
|
||||
def on_dcs(dcs: str) -> None:
|
||||
global got_capability_response
|
||||
if dcs.startswith('1+r'):
|
||||
got_capability_response = True
|
||||
|
||||
|
||||
def on_osc(osc: str) -> None:
|
||||
global clipboard_contents, clipboard_from_primary, got_clipboard_response
|
||||
idx = osc.find(';')
|
||||
if idx <= 0:
|
||||
return
|
||||
q = osc[:idx]
|
||||
if q == '52':
|
||||
got_clipboard_response = True
|
||||
widx = osc.find(';', idx + 1)
|
||||
if widx < idx:
|
||||
clipboard_from_primary = osc.find('p', idx + 1) > -1
|
||||
clipboard_contents = ''
|
||||
else:
|
||||
from base64 import standard_b64decode
|
||||
clipboard_from_primary = osc.find('p', idx+1, widx) > -1
|
||||
data = memoryview(osc.encode('ascii'))
|
||||
clipboard_contents = standard_b64decode(data[widx+1:]).decode('utf-8')
|
||||
|
||||
|
||||
def wait_loop(tty_fd: int) -> None:
|
||||
os.set_blocking(tty_fd, False)
|
||||
decoder = codecs.getincrementaldecoder('utf-8')('ignore')
|
||||
with raw_mode(tty_fd):
|
||||
buf = ''
|
||||
while not got_capability_response and not got_clipboard_response:
|
||||
rd = select.select([tty_fd], [], [])[0]
|
||||
if rd:
|
||||
raw = os.read(tty_fd, io.DEFAULT_BUFFER_SIZE)
|
||||
if not raw:
|
||||
raise EOFError()
|
||||
data = decoder.decode(raw)
|
||||
buf = (buf + data) if buf else data
|
||||
buf = parse_input_from_terminal(on_text, on_dcs, ignore, on_osc, ignore, ignore, buf, False)
|
||||
|
||||
|
||||
def main(args: List[str]) -> NoReturn:
|
||||
cli_opts, items = parse_args(args[1:], OPTIONS, usage, help_text, 'kitty +kitten clipboard', result_class=ClipboardCLIOptions)
|
||||
if items:
|
||||
raise SystemExit('Unrecognized extra command line arguments')
|
||||
data: Optional[bytes] = None
|
||||
if not sys.stdin.isatty():
|
||||
data = sys.stdin.buffer.read()
|
||||
wait_for_capability_response = False
|
||||
data_to_write = []
|
||||
if data:
|
||||
data_to_write.append(write_to_clipboard(data, cli_opts.use_primary).encode('ascii'))
|
||||
if not cli_opts.get_clipboard and cli_opts.wait_for_completion:
|
||||
data_to_write.append(b'\x1bP+q544e\x1b\\')
|
||||
wait_for_capability_response = True
|
||||
if cli_opts.get_clipboard:
|
||||
data_to_write.append(request_from_clipboard(cli_opts.use_primary).encode('ascii'))
|
||||
wait_for_capability_response = True
|
||||
tty_fd = os.open(os.ctermid(), os.O_RDWR | os.O_CLOEXEC)
|
||||
retcode = 0
|
||||
with open(tty_fd, 'wb', closefd=True) as ttyf:
|
||||
for x in data_to_write:
|
||||
ttyf.write(x)
|
||||
ttyf.flush()
|
||||
if wait_for_capability_response:
|
||||
try:
|
||||
wait_loop(tty_fd)
|
||||
except KeyboardInterrupt:
|
||||
sys.excepthook = lambda *a: None
|
||||
raise
|
||||
except EOFError:
|
||||
retcode = 1
|
||||
if clipboard_contents:
|
||||
print(end=clipboard_contents)
|
||||
|
||||
raise SystemExit(retcode)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
raise SystemExit('This should be run as kitty-tool clipboard')
|
||||
elif __name__ == '__doc__':
|
||||
cd = sys.cli_docs # type: ignore
|
||||
cd['usage'] = usage
|
||||
|
||||
@ -316,19 +316,32 @@ ensure_working_stdio(void) {
|
||||
#undef C
|
||||
}
|
||||
|
||||
static bool
|
||||
is_wrapped_kitten(const char *arg) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf)-1, " %s ", arg);
|
||||
return strstr(" " WRAPPED_KITTENS " ", buf);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_to_kitty_tool_if_possible(int argc, char *argv[], char* exe_dir) {
|
||||
if (argc > 1 && argv[1][0] == '@') {
|
||||
exec_kitty_tool(int argc, char *argv[], char *exe_dir) {
|
||||
char exe[PATH_MAX+1] = {0};
|
||||
snprintf(exe, PATH_MAX, "%s/kitty-tool", exe_dir);
|
||||
char **newargv = malloc(sizeof(char*) * (argc + 1));
|
||||
memcpy(newargv, argv, sizeof(char*) * argc);
|
||||
newargv[argc] = 0;
|
||||
newargv[0] = "kitty-tool";
|
||||
errno = 0;
|
||||
execv(exe, argv);
|
||||
fprintf(stderr, "Failed to execute kitty-tool (%s) with error: %s\n", exe, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_to_kitty_tool_if_possible(int argc, char *argv[], char* exe_dir) {
|
||||
if (argc > 1 && argv[1][0] == '@') exec_kitty_tool(argc, argv, exe_dir);
|
||||
if (argc > 2 && strcmp(argv[1], "+kitten") == 0 && is_wrapped_kitten(argv[2])) exec_kitty_tool(argc - 1, argv + 1, exe_dir);
|
||||
if (argc > 3 && strcmp(argv[1], "+") == 0 && strcmp(argv[2], "kitten") == 0 && is_wrapped_kitten(argv[3])) exec_kitty_tool(argc - 2, argv + 2, exe_dir);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char* envp[]) {
|
||||
|
||||
9
setup.py
9
setup.py
@ -529,8 +529,7 @@ def get_source_specific_defines(env: Env, src: str) -> Tuple[str, Optional[List[
|
||||
if src == 'kitty/parser_dump.c':
|
||||
return 'kitty/parser.c', ['DUMP_COMMANDS']
|
||||
if src == 'kitty/data-types.c':
|
||||
wk = ' '.join(wrapped_kittens())
|
||||
return src, [f'KITTY_VCS_REV="{get_vcs_rev_define()}"', f'WRAPPED_KITTENS="{wk}"']
|
||||
return src, [f'KITTY_VCS_REV="{get_vcs_rev_define()}"', f'WRAPPED_KITTENS="{wrapped_kittens()}"']
|
||||
try:
|
||||
return src, env.library_paths[src]
|
||||
except KeyError:
|
||||
@ -863,12 +862,12 @@ def build_ref_map() -> str:
|
||||
|
||||
|
||||
@lru_cache
|
||||
def wrapped_kittens() -> Sequence[str]:
|
||||
def wrapped_kittens() -> str:
|
||||
with open('shell-integration/ssh/kitty') as f:
|
||||
for line in f:
|
||||
if line.startswith(' wrapped_kittens="'):
|
||||
val = line.strip().partition('"')[2][:-1]
|
||||
return tuple(sorted(filter(None, val.split())))
|
||||
return ' '.join(sorted(filter(None, val.split())))
|
||||
raise Exception('Failed to read wrapped kittens from kitty wrapper script')
|
||||
|
||||
|
||||
@ -965,7 +964,7 @@ def build_static_binaries(args: Options, launcher_dir: str) -> None:
|
||||
def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 'source') -> None:
|
||||
werror = '' if args.ignore_compiler_warnings else '-pedantic-errors -Werror'
|
||||
cflags = f'-Wall {werror} -fpie'.split()
|
||||
cppflags = []
|
||||
cppflags = [define(f'WRAPPED_KITTENS=" {wrapped_kittens()} "')]
|
||||
libs: List[str] = []
|
||||
ldflags = shlex.split(os.environ.get('LDFLAGS', ''))
|
||||
if args.profile or args.sanitize:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user