aboutsummaryrefslogtreecommitdiff
path: root/app/ui/tui.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-24 03:41:57 -0400
committerhistoria <historiavg@proton.me>2026-08-24 03:41:57 -0400
commit73b466fbc054e80b50e318b49643aee8a03c784b (patch)
treedf3d78efa84956bcf47586af736479f319a80abe /app/ui/tui.py
parent471798cf5e967b2d1bceb02d12a47fe9ad1cbed1 (diff)
downloadtts-audiobook-generator-73b466fbc054e80b50e318b49643aee8a03c784b.tar.gz
feat: settings for ports in TUI
Diffstat (limited to 'app/ui/tui.py')
-rw-r--r--app/ui/tui.py72
1 files changed, 41 insertions, 31 deletions
diff --git a/app/ui/tui.py b/app/ui/tui.py
index c3d79f6..12c7d4f 100644
--- a/app/ui/tui.py
+++ b/app/ui/tui.py
@@ -758,17 +758,18 @@ def form(scr, title: str, fields: Sequence[dict],
Each field renders as a left-justified ``Label: value`` row. Up/Down
(or k/j) move the cursor; Enter on a ``choice`` row opens a single
choice menu, Enter on a ``text`` row opens a line editor (reusing its
- VALIDATE for that one field). Tab or the arrow keys move focus to the
- Save/Cancel buttons; Enter on Save validates every text field (the
- first failure flashes in red and re-focuses that row) and returns
- ``{key: value}``, Enter on Cancel returns BACK_VALUE. Esc (or 'q')
- returns BACK_VALUE / aborts as in menu(). Values are edited in place
- in the FIELDS dicts, so Cancel simply discards them.
+ VALIDATE for that one field). Tab, Left/Right or Up/Down move focus to
+ the Save/Cancel buttons — Up from the first field and Down from the
+ last field step straight onto them; Enter on Save validates every text
+ field (the first failure flashes in red and re-focuses that row) and
+ returns ``{key: value}``, Enter on Cancel returns BACK_VALUE. Esc (or
+ 'q') returns BACK_VALUE / aborts as in menu(). Values are edited in
+ place in the FIELDS dicts, so Cancel simply discards them.
"""
if not fields:
raise ValueError("form() needs at least one field")
frame = Frame(scr, title,
- "Up/Down = move Enter = edit Tab = Save/Cancel "
+ "Up/Down = move Enter = edit Tab/arrows = Save/Cancel "
"Esc = cancel")
cursor = 0
on_buttons = False
@@ -816,31 +817,40 @@ def form(scr, title: str, fields: Sequence[dict],
else: # Cancel
return back_value
else:
- moved = frame.motion(key, cursor, len(fields), wrap=True)
- if moved is not None:
- cursor = moved
- elif key in (9, curses.KEY_BTAB, curses.KEY_LEFT,
- curses.KEY_RIGHT, ord("h"), ord("l")):
+ if key in (curses.KEY_DOWN, ord("j")) \
+ and cursor == len(fields) - 1:
on_buttons = True
- btn_index = 0
- elif key in (10, 13):
- field = fields[cursor]
- if field.get("kind") == "choice":
- choices = list(field.get("choices") or [])
- default = choices.index(field["value"]) \
- if field["value"] in choices else 0
- chosen = menu(scr, field["label"],
- [(c, c) for c in choices],
- default_index=default,
- back_value=edit_cancel)
- if chosen is not edit_cancel:
- field["value"] = chosen
- else:
- edited = line_edit(scr, field["label"], field["value"],
- validate=field.get("validate"),
- back_value=edit_cancel)
- if edited is not edit_cancel:
- field["value"] = edited
+ btn_index = 0 # Save
+ elif key in (curses.KEY_UP, ord("k")) and cursor == 0:
+ on_buttons = True
+ btn_index = 1 # Cancel
+ else:
+ moved = frame.motion(key, cursor, len(fields), wrap=True)
+ if moved is not None:
+ cursor = moved
+ elif key in (9, curses.KEY_BTAB, curses.KEY_LEFT,
+ curses.KEY_RIGHT, ord("h"), ord("l")):
+ on_buttons = True
+ btn_index = 0
+ elif key in (10, 13):
+ field = fields[cursor]
+ if field.get("kind") == "choice":
+ choices = list(field.get("choices") or [])
+ default = choices.index(field["value"]) \
+ if field["value"] in choices else 0
+ chosen = menu(scr, field["label"],
+ [(c, c) for c in choices],
+ default_index=default,
+ back_value=edit_cancel)
+ if chosen is not edit_cancel:
+ field["value"] = chosen
+ else:
+ edited = line_edit(scr, field["label"],
+ field["value"],
+ validate=field.get("validate"),
+ back_value=edit_cancel)
+ if edited is not edit_cancel:
+ field["value"] = edited
# ---------------------------------------------------------------------------