aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorDon Williams <don.e.williams@gmail.com>2026-01-15 01:56:42 -0500
committerDon Williams <don.e.williams@gmail.com>2026-01-15 01:56:42 -0500
commit0886304d0fe31f88343391f5405465f90d2ac8fe (patch)
treed84b46d3d4d248865d26d03df2c2506c4f8dd125 /scripts
parent1451c8f90cab6a28216872f017083a77dad54be1 (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-xscripts/copy_menu.sh17
-rwxr-xr-xscripts/tui_menu.py70
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]
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage