diff options
| author | Don Williams <don.e.williams@gmail.com> | 2026-01-15 01:56:42 -0500 |
|---|---|---|
| committer | Don Williams <don.e.williams@gmail.com> | 2026-01-15 01:56:42 -0500 |
| commit | 0886304d0fe31f88343391f5405465f90d2ac8fe (patch) | |
| tree | d84b46d3d4d248865d26d03df2c2506c4f8dd125 /scripts | |
| parent | 1451c8f90cab6a28216872f017083a77dad54be1 (diff) | |
Fixing menu and version detection code for express upgrade
On branch development
Your branch is up to date with 'origin/development'.
Changes to be committed:
modified: copy.sh
modified: scripts/copy_menu.sh
modified: scripts/tui_menu.py
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/copy_menu.sh | 17 | ||||
| -rwxr-xr-x | scripts/tui_menu.py | 70 |
2 files changed, 53 insertions, 34 deletions
diff --git a/scripts/copy_menu.sh b/scripts/copy_menu.sh index 212cab84..258c2fae 100755 --- a/scripts/copy_menu.sh +++ b/scripts/copy_menu.sh @@ -29,11 +29,18 @@ show_copy_menu() { __self_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" __repo_dir="${SCRIPT_DIR:-$(cd "${__self_dir}/.." 2>/dev/null && pwd)}" local py_menu="${__repo_dir}/scripts/tui_menu.py" - if command -v python3 >/dev/null 2>&1 && [ -f "$py_menu" ]; then - if choice=$(python3 "$py_menu" --express-supported "$express_supported"); then - # shellcheck disable=SC2034 # used by parent script after sourcing this file - COPY_MENU_CHOICE="$choice" - return 0 +if command -v python3 >/dev/null 2>&1 && [ -f "$py_menu" ]; then + # Allow forcing backend via COPY_TUI_BACKEND=auto|textual|curses|basic + if [ -n "$COPY_TUI_BACKEND" ]; then + if choice=$(python3 "$py_menu" --express-supported "$express_supported" --backend "$COPY_TUI_BACKEND"); then + COPY_MENU_CHOICE="$choice" + return 0 + fi + else + if choice=$(python3 "$py_menu" --express-supported "$express_supported"); then + COPY_MENU_CHOICE="$choice" + return 0 + fi fi fi diff --git a/scripts/tui_menu.py b/scripts/tui_menu.py index abf35751..d57ba1ac 100755 --- a/scripts/tui_menu.py +++ b/scripts/tui_menu.py @@ -35,20 +35,26 @@ HELP_TEXT = ( def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--express-supported", default="0", choices=["0", "1"], help="Whether Express is allowed (1) or not (0)") + parser.add_argument("--backend", default=os.environ.get("COPY_TUI_BACKEND", "auto"), choices=["auto", "textual", "curses", "basic"], help="Choose UI backend") args = parser.parse_args() express_supported = args.express_supported == "1" + backend = args.backend - # Try Textual first + if backend == "textual": + return run_textual(express_supported) + if backend == "curses": + return run_curses(express_supported) + if backend == "basic": + return run_basic(express_supported) + + # auto: Try Textual, then curses, then basic try: return run_textual(express_supported) - except Exception: # noqa: BLE001 - silently fall back + except Exception: pass - - # Then try curses try: return run_curses(express_supported) except Exception: - # Final fallback to a very simple stdin prompt to avoid breaking workflows return run_basic(express_supported) @@ -180,7 +186,7 @@ def run_curses(express_supported: bool) -> int: h, w = stdscr.getmaxyx() title = "KooL's Hyprland Dotfiles" stdscr.attron(curses.A_BOLD) - stdscr.addstr(1, (w - len(title)) // 2, title) + stdscr.addstr(1, max(2, (w - len(title)) // 2), title) stdscr.attroff(curses.A_BOLD) y = 4 @@ -190,40 +196,36 @@ def run_curses(express_supported: bool) -> int: rest = name[1:] if i == idx: stdscr.attron(curses.A_REVERSE) - if disabled: - color = curses.color_pair(2) - else: - color = curses.color_pair(1) # First letter styled - stdscr.attron(color | curses.A_BOLD) + stdscr.attron(curses.color_pair(1) | curses.A_BOLD) stdscr.addstr(y, 4, hk) - stdscr.attroff(color | curses.A_BOLD) + stdscr.attroff(curses.color_pair(1) | curses.A_BOLD) + if disabled: + stdscr.attron(curses.A_DIM) stdscr.addstr(y, 5, rest) if disabled: msg = " (requires newer installed dots)" - stdscr.attron(curses.color_pair(2)) - stdscr.addstr(y, 5 + len(rest), msg) - stdscr.attroff(curses.color_pair(2)) + stdscr.addstr(y, 5 + len(rest), msg, curses.A_DIM) + stdscr.attroff(curses.A_DIM) if i == idx: stdscr.attroff(curses.A_REVERSE) y += 2 - info = "Enter=Select ↑/↓=Move Mouse=Click h/?=Help q=Quit" - stdscr.addstr(h - 2, 2, info) + info = "Enter=Select Up/Down=Move Mouse=Click h/?=Help q=Quit" + stdscr.addstr(h - 2, 2, info[: max(0, w - 4)]) if show_help: box_w = min(w - 6, 76) box_h = min(12, h - 6) - bx = (w - box_w) // 2 - by = (h - box_h) // 2 - # simple box + bx = max(2, (w - box_w) // 2) + by = max(2, (h - box_h) // 2) for yy in range(by, by + box_h): - stdscr.addstr(yy, bx, " " * box_w, curses.color_pair(3)) + stdscr.addstr(yy, bx, " " * max(0, box_w), curses.color_pair(3)) stdscr.attron(curses.A_BOLD) stdscr.addstr(by, bx + 2, "Help") stdscr.attroff(curses.A_BOLD) - for i, line in enumerate(HELP_TEXT.splitlines()[: box_h - 3]): - stdscr.addstr(by + 2 + i, bx + 2, line) + for i, line in enumerate(HELP_TEXT.splitlines()[: max(0, box_h - 3)]): + stdscr.addstr(by + 2 + i, bx + 2, line[: max(0, box_w - 4)]) stdscr.addstr(by + box_h - 2, bx + 2, "Press q or Esc to close help") stdscr.refresh() @@ -232,9 +234,18 @@ def run_curses(express_supported: bool) -> int: curses.curs_set(0) curses.mousemask(1) curses.start_color() - curses.init_pair(1, curses.COLOR_CYAN, -1) - curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_BLACK) - curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_BLUE) + try: + curses.use_default_colors() + except Exception: + pass + try: + curses.init_pair(1, curses.COLOR_CYAN, -1) + except Exception: + curses.init_pair(1, curses.COLOR_CYAN, 0) + try: + curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_BLUE) + except Exception: + curses.init_pair(3, curses.COLOR_WHITE, 0) idx = 0 showing_help = False @@ -257,7 +268,6 @@ def run_curses(express_supported: bool) -> int: elif ch == curses.KEY_MOUSE: try: _, mx, my, _, _ = curses.getmouse() - # map click row to item base_y = 4 if my >= base_y: clicked = (my - base_y) // 2 @@ -280,8 +290,10 @@ def run_curses(express_supported: bool) -> int: else: return name else: - # hotkeys by first letter - key = chr(ch).lower() if 0 <= ch < 256 else "" + try: + key = chr(ch).lower() if 0 <= ch < 256 else "" + except Exception: + key = "" mapping = {"i": "Install", "u": "Upgrade", "e": "Express", "d": "Update", "q": "Quit", "h": "Help"} if key in mapping: name = mapping[key] |
