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.
This commit is contained in:
Kovid Goyal 2018-03-01 12:11:49 +05:30
parent aad4a1fd6a
commit bc21ec7551
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 9 additions and 13 deletions

View File

@ -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)

View File

@ -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):