ask kitten: Get readline to work even when stdout is redirected

This commit is contained in:
Kovid Goyal 2023-01-26 21:14:21 +05:30
parent b408abe304
commit f8991ce3c8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 26 additions and 17 deletions

View File

@ -495,16 +495,20 @@ def main(args: List[str]) -> Response:
loop.loop(phandler)
return {'items': items, 'response': phandler.response}
import readline as rl
readline = rl
init_readline()
response = None
orig_stdout = os.dup(sys.stdout.fileno())
try:
with open(os.ctermid(), 'r') as tty:
os.dup2(tty.fileno(), sys.stdin.fileno())
with open(os.ctermid(), 'w') as tty:
os.dup2(tty.fileno(), sys.stdout.fileno())
import readline as rl
readline = rl
init_readline()
response = None
with alternate_screen(), HistoryCompleter(cli_opts.name):
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
with suppress(KeyboardInterrupt, EOFError):
with alternate_screen(), HistoryCompleter(cli_opts.name), suppress(KeyboardInterrupt, EOFError):
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
if cli_opts.default:
def prefill_text() -> None:
readline.insert_text(cli_opts.default or '')
@ -514,6 +518,10 @@ def prefill_text() -> None:
readline.set_pre_input_hook()
else:
response = input(prompt)
sys.stdout.flush()
os.dup2(orig_stdout, sys.stdout.fileno())
finally:
os.close(orig_stdout)
return {'items': items, 'response': response}

View File

@ -1,11 +1,12 @@
#!/usr/bin/env python3
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os
import sys
from contextlib import contextmanager
from enum import Enum, auto
from functools import wraps
from typing import IO, Any, Callable, Dict, Generator, Optional, TypeVar, Union
from typing import Any, Callable, Dict, Generator, Optional, TypeVar, Union
from kitty.fast_data_types import Color
from kitty.rgb import color_as_sharp, to_color
@ -348,13 +349,13 @@ def cursor(write: Callable[[str], None]) -> Generator[None, None, None]:
@contextmanager
def alternate_screen(f: Optional[IO[str]] = None) -> Generator[None, None, None]:
f = f or sys.stdout
print(set_mode(Mode.ALTERNATE_SCREEN), end='', file=f)
try:
yield
finally:
print(reset_mode(Mode.ALTERNATE_SCREEN), end='', file=f)
def alternate_screen() -> Generator[None, None, None]:
with open(os.ctermid(), 'w') as f:
print(set_mode(Mode.ALTERNATE_SCREEN), end='', file=f, flush=True)
try:
yield
finally:
print(reset_mode(Mode.ALTERNATE_SCREEN), end='', file=f, flush=True)
@contextmanager