mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-25 17:52:02 +02:00
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:
@@ -415,17 +415,12 @@ global_options_spec = partial('''\
|
|||||||
'''.format, appname=appname)
|
'''.format, appname=appname)
|
||||||
|
|
||||||
|
|
||||||
def read_from_stdin(send, no_response):
|
def do_io(send, no_response):
|
||||||
send = ('@kitty-cmd' + json.dumps(send)).encode('ascii')
|
send = ('@kitty-cmd' + json.dumps(send)).encode('ascii')
|
||||||
out = sys.stdout if sys.stdout.isatty() else sys.stderr
|
with open('/dev/tty', 'wb') as out:
|
||||||
if not out.isatty():
|
out.write(b'\x1bP' + send + b'\x1b\\')
|
||||||
raise SystemExit('Neither stdout nor stderr is a terminal')
|
|
||||||
out.buffer.write(b'\x1bP' + send + b'\x1b\\')
|
|
||||||
out.flush()
|
|
||||||
if no_response:
|
if no_response:
|
||||||
return {'ok': True}
|
return {'ok': True}
|
||||||
if not sys.stdin.isatty():
|
|
||||||
raise SystemExit('stdin is not a terminal')
|
|
||||||
|
|
||||||
received = b''
|
received = b''
|
||||||
dcs = re.compile(br'\x1bP@kitty-cmd([^\x1b]+)\x1b\\')
|
dcs = re.compile(br'\x1bP@kitty-cmd([^\x1b]+)\x1b\\')
|
||||||
@@ -437,7 +432,8 @@ def read_from_stdin(send, no_response):
|
|||||||
match = dcs.search(received)
|
match = dcs.search(received)
|
||||||
return match is None
|
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:
|
if match is None:
|
||||||
raise SystemExit('Failed to receive response from ' + appname)
|
raise SystemExit('Failed to receive response from ' + appname)
|
||||||
response = json.loads(match.group(1).decode('ascii'))
|
response = json.loads(match.group(1).decode('ascii'))
|
||||||
@@ -474,11 +470,11 @@ def main(args):
|
|||||||
if func.no_response and isinstance(payload, types.GeneratorType):
|
if func.no_response and isinstance(payload, types.GeneratorType):
|
||||||
for item in payload:
|
for item in payload:
|
||||||
send['payload'] = item
|
send['payload'] = item
|
||||||
read_from_stdin(send, func.no_response)
|
do_io(send, func.no_response)
|
||||||
return
|
return
|
||||||
if payload is not None:
|
if payload is not None:
|
||||||
send['payload'] = payload
|
send['payload'] = payload
|
||||||
response = read_from_stdin(send, func.no_response)
|
response = do_io(send, func.no_response)
|
||||||
if not response.get('ok'):
|
if not response.get('ok'):
|
||||||
if response.get('tb'):
|
if response.get('tb'):
|
||||||
print(response['tb'], file=sys.stderr)
|
print(response['tb'], file=sys.stderr)
|
||||||
|
|||||||
@@ -279,14 +279,14 @@ def non_blocking_read(src=sys.stdin):
|
|||||||
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl)
|
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
|
import select
|
||||||
start_time = monotonic()
|
start_time = monotonic()
|
||||||
with non_blocking_read(src) as fd:
|
with non_blocking_read(src) as fd:
|
||||||
while timeout > monotonic() - start_time:
|
while timeout > monotonic() - start_time:
|
||||||
rd = select.select([fd], [], [], max(0, timeout - (monotonic() - start_time)))[0]
|
rd = select.select([fd], [], [], max(0, timeout - (monotonic() - start_time)))[0]
|
||||||
if rd:
|
if rd:
|
||||||
data = sys.stdin.buffer.read()
|
data = src.read()
|
||||||
if not data:
|
if not data:
|
||||||
break # eof
|
break # eof
|
||||||
if not more_needed(data):
|
if not more_needed(data):
|
||||||
|
|||||||
Reference in New Issue
Block a user