Allow using the ask kitten to pick a choice

This commit is contained in:
Kovid Goyal 2020-09-15 12:39:07 +05:30
parent 5737904cec
commit 437efe5473
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 73 additions and 37 deletions

View File

@ -13,7 +13,8 @@
from kitty.typing import BossType
from ..tui.handler import result_handler
from ..tui.operations import alternate_screen, set_cursor_visible, styled
from ..tui.operations import alternate_screen, styled
from ..tui.utils import get_key_press
if TYPE_CHECKING:
import readline
@ -70,7 +71,7 @@ def __exit__(self, *a: object) -> None:
def option_text() -> str:
return '''\
--type -t
choices=line,yesno
choices=line,yesno,choices
default=line
Type of input. Defaults to asking for a line of text.
@ -83,6 +84,16 @@ def option_text() -> str:
--name -n
The name for this question. Used to store history of previous answers which can
be used for completions and via the browse history readline bindings.
--choice -c
type=list
dest=choices
A choice for the choices type. Every choice has the syntax: letter:text Where
letter is the accelerator key and text is the corresponding text. There can be
an optional color specification after the letter to indicate what color it should
be.
For example: y:Yes and n;red:No
'''
@ -97,23 +108,34 @@ class Response(TypedDict):
response: Optional[str]
def yesno(cli_opts: AskCLIOptions, items: List[str]) -> Response:
import tty
def choice(cli_opts: AskCLIOptions, items: List[str]) -> Response:
with alternate_screen():
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
print()
print(' ', styled('Y', fg='green') + 'es', ' ', styled('N', fg='red') + 'o', set_cursor_visible(False))
sys.stdout.flush()
tty.setraw(sys.stdin.fileno())
try:
response = sys.stdin.buffer.read(1)
yes = response in (b'y', b'Y', b'\r', b'\n', b' ')
return {'items': items, 'response': 'y' if yes else 'n'}
finally:
sys.stdout.write(set_cursor_visible(True))
tty.setcbreak(sys.stdin.fileno())
sys.stdout.flush()
allowed = ''
for choice in cli_opts.choices:
color = 'green'
letter, text = choice.split(':', maxsplit=1)
if ';' in letter:
letter, color = letter.split(';', maxsplit=1)
letter = letter.lower()
idx = text.lower().index(letter)
allowed += letter
print(text[:idx], styled(text[idx], fg=color), text[idx:], sep='', end=' ')
print()
response = get_key_press(allowed, '')
return {'items': items, 'response': response}
def yesno(cli_opts: AskCLIOptions, items: List[str]) -> Response:
with alternate_screen():
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
print()
print(' ', styled('Y', fg='green') + 'es', ' ', styled('N', fg='red') + 'o')
response = get_key_press('yn', 'n')
return {'items': items, 'response': response}
def main(args: List[str]) -> Response:
@ -132,6 +154,8 @@ def main(args: List[str]) -> Response:
if cli_opts.type == 'yesno':
return yesno(cli_opts, items)
if cli_opts.type == 'choices':
return choice(cli_opts, items)
import readline as rl
readline = rl

View File

@ -11,43 +11,27 @@
import sys
import tempfile
import time
from contextlib import suppress
from typing import Any, List, Optional
from kitty.cli import parse_args
from kitty.cli_stub import RemoteFileCLIOptions
from kitty.constants import cache_dir
from kitty.typing import BossType
from kitty.utils import command_for_open, get_editor, open_cmd, SSHConnectionData
from kitty.utils import (
SSHConnectionData, command_for_open, get_editor, open_cmd
)
from ..tui.handler import result_handler
from ..tui.operations import (
faint, raw_mode, reset_terminal, set_cursor_visible, styled
faint, raw_mode, reset_terminal, styled
)
from ..tui.utils import get_key_press
def key(x: str) -> str:
return styled(x, bold=True, fg='green')
def get_key_press(allowed: str, default: str) -> str:
response = default
with raw_mode():
try:
while True:
q = sys.stdin.buffer.read(1)
if q:
if q in b'\x1b\x03':
break
with suppress(Exception):
response = q.decode('utf-8').lower()
if response in allowed:
break
except (KeyboardInterrupt, EOFError):
pass
return response
def option_text() -> str:
return '''\
--mode -m
@ -194,7 +178,6 @@ def main(args: List[str]) -> Result:
input('Press enter to quit...')
raise SystemExit(e.code)
print(set_cursor_visible(False), end='', flush=True)
try:
action = ask_action(cli_opts)
finally:

29
kittens/tui/utils.py Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import sys
from contextlib import suppress
from .operations import raw_mode, set_cursor_visible
def get_key_press(allowed: str, default: str) -> str:
response = default
with raw_mode():
print(set_cursor_visible(False), end='', flush=True)
try:
while True:
q = sys.stdin.buffer.read(1)
if q:
if q in b'\x1b\x03':
break
with suppress(Exception):
response = q.decode('utf-8').lower()
if response in allowed:
break
except (KeyboardInterrupt, EOFError):
pass
finally:
print(set_cursor_visible(True), end='', flush=True)
return response