From bc21ec75517d9198db323c7bc25d663da89378ca Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 1 Mar 2018 12:11:49 +0530 Subject: [PATCH] Have kitty @ use /dev/tty instead of stdout/stdin Allows redirecting those streams, while still being able to send messages. Downside is that if user runs it outside kitty there wont be any useful error message. --- kitty/remote_control.py | 18 +++++++----------- kitty/utils.py | 4 ++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/kitty/remote_control.py b/kitty/remote_control.py index 4cce23873..502a91c6f 100644 --- a/kitty/remote_control.py +++ b/kitty/remote_control.py @@ -415,17 +415,12 @@ global_options_spec = partial('''\ '''.format, appname=appname) -def read_from_stdin(send, no_response): +def do_io(send, no_response): send = ('@kitty-cmd' + json.dumps(send)).encode('ascii') - out = sys.stdout if sys.stdout.isatty() else sys.stderr - if not out.isatty(): - raise SystemExit('Neither stdout nor stderr is a terminal') - out.buffer.write(b'\x1bP' + send + b'\x1b\\') - out.flush() + with open('/dev/tty', 'wb') as out: + out.write(b'\x1bP' + send + b'\x1b\\') if no_response: return {'ok': True} - if not sys.stdin.isatty(): - raise SystemExit('stdin is not a terminal') received = b'' dcs = re.compile(br'\x1bP@kitty-cmd([^\x1b]+)\x1b\\') @@ -437,7 +432,8 @@ def read_from_stdin(send, no_response): match = dcs.search(received) return match is None - read_with_timeout(more_needed) + with open('/dev/tty', 'rb') as src: + read_with_timeout(more_needed, src=src) if match is None: raise SystemExit('Failed to receive response from ' + appname) response = json.loads(match.group(1).decode('ascii')) @@ -474,11 +470,11 @@ def main(args): if func.no_response and isinstance(payload, types.GeneratorType): for item in payload: send['payload'] = item - read_from_stdin(send, func.no_response) + do_io(send, func.no_response) return if payload is not None: send['payload'] = payload - response = read_from_stdin(send, func.no_response) + response = do_io(send, func.no_response) if not response.get('ok'): if response.get('tb'): print(response['tb'], file=sys.stderr) diff --git a/kitty/utils.py b/kitty/utils.py index 932e7584e..bb0c42f0f 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -279,14 +279,14 @@ def non_blocking_read(src=sys.stdin): fcntl.fcntl(fd, fcntl.F_SETFL, oldfl) -def read_with_timeout(more_needed, timeout=10, src=sys.stdin): +def read_with_timeout(more_needed, timeout=10, src=sys.stdin.buffer): import select start_time = monotonic() with non_blocking_read(src) as fd: while timeout > monotonic() - start_time: rd = select.select([fd], [], [], max(0, timeout - (monotonic() - start_time)))[0] if rd: - data = sys.stdin.buffer.read() + data = src.read() if not data: break # eof if not more_needed(data):