From 93c713590e24930ab22b1bc2fdd6b0781bb68bbc Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 19:03:16 +0000 Subject: [PATCH 1/2] feat: Implement UI/UX enhancements Co-authored-by: MnemOnicE <170563909+MnemOnicE@users.noreply.github.com> --- commando/ui/dashboard.py | 61 +++++++++++++++++++++++++++++++++------- commando/utils/io.py | 20 +++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/commando/ui/dashboard.py b/commando/ui/dashboard.py index d577615..5c7cde5 100644 --- a/commando/ui/dashboard.py +++ b/commando/ui/dashboard.py @@ -19,19 +19,20 @@ clear_screen, pause, save_json, + get_category_color, + format_badge, ) def print_dashboard(session_history, pending_imports): clear_screen() - print(f"{CYAN}{BOLD}=============================================={RESET}") - print(f"{CYAN}{BOLD} Terminal Command Explorer & Tutor {RESET}") - print(f"{CYAN}{BOLD}=============================================={RESET}") + print(f"{CYAN}{BOLD}╔════════════════════════════════════════════════════╗{RESET}") + print(f"{CYAN}{BOLD}║ Terminal Command Explorer & Tutor ║{RESET}") + print(f"{CYAN}{BOLD}╚════════════════════════════════════════════════════╝{RESET}\n") if session_history: - print( - f"{MAGENTA}Recent: {', '.join(list(session_history.keys())[-5:])}{RESET}\n" - ) + recent = list(session_history.keys())[-5:] + print(f"{MAGENTA}{BOLD}Recent:{RESET} {', '.join(recent)}\n") print(f" {GREEN}[1]{RESET} Explore Random Command") print(f" {GREEN}[2]{RESET} Explore by Category") @@ -44,8 +45,9 @@ def print_dashboard(session_history, pending_imports): f" {CYAN}[7]{RESET} Review Pending Imports ({len(pending_imports)} waiting)" ) print(f" {MAGENTA}[8]{RESET} Install Bash Hook") + print(f" {GREEN}[9]{RESET} View Stats & Mastery") print(f" {RED}[0]{RESET} Exit & Quiz Mode") - print(f"{YELLOW}Or type a command to search (e.g., ls, nano){RESET}\n") + print(f"\n{YELLOW}Or type a command to search (e.g., ls, nano){RESET}\n") def view_debug_log(): @@ -64,6 +66,41 @@ def view_debug_log(): pause() + +def view_stats_and_mastery(state_manager): + clear_screen() + session_history = state_manager.session_history + if not session_history: + print(f"{YELLOW}No stats available yet. Start exploring commands!{RESET}") + pause() + return + + print(f"{MAGENTA}★ User Stats & Mastery ★{RESET}\n") + print(f"Total commands explored: {len(session_history)}") + + # Sort history by mastery level (score) descending, then by name + sorted_history = sorted(session_history.items(), key=lambda x: (-x[1], x[0])) + + print(f"\n{CYAN}{BOLD}Command Mastery:{RESET}") + for cmd, score in sorted_history: + # Mastery goes up to 5 + score = min(5, max(0, score)) + filled = "█" * score + empty = "░" * (5 - score) + bar = f"{filled}{empty}" + + # Color coding the progress bar + if score >= 4: + bar_color = GREEN + elif score >= 2: + bar_color = YELLOW + else: + bar_color = RED + + print(f" {bar_color}[{bar}]{RESET} {BOLD}{cmd}{RESET}") + + pause() + def factory_reset(state_manager): clear_screen() print(f"{RED}★ Factory Reset ★{RESET}\n") @@ -122,7 +159,7 @@ def explore_category(state_manager): if 0 <= idx < len(categories): selected_cat = categories[idx] clear_screen() - print(f"{YELLOW}--- {selected_cat} Commands ---{RESET}\n") + print(f"{YELLOW}--- {format_badge(selected_cat)} Commands ---{RESET}\n") for cmd, data in all_known.items(): if data["category"] == selected_cat: print(f" • {CYAN}{BOLD}{cmd}{RESET}: {data['desc']}") @@ -147,7 +184,8 @@ def manage_imports(state_manager): short_desc = ( (data["desc"][:60] + "...") if len(data["desc"]) > 60 else data["desc"] ) - print(f" • {CYAN}{BOLD}{cmd}{RESET}: {short_desc}") + badge = format_badge(data.get("category", "Custom")) + print(f" • {badge} {CYAN}{BOLD}{cmd}{RESET}: {short_desc}") print(f"\n{YELLOW}Options:{RESET}") print(f" - Type a command name to {RED}DELETE{RESET} it from the database.") @@ -261,7 +299,7 @@ def review_pending_imports(state_manager): clear_screen() data = pending_imports[cmd] print(f"{CYAN}Command:{RESET} {cmd}") - print(f"Category: [{MAGENTA}{data['category']}{RESET}]") + print(f"Category: {format_badge(data['category'])}") print(f"Explanation: {data['desc']}") print(f"Example: {data['example']}") print( @@ -407,6 +445,9 @@ def main_loop(state_manager, search_command_fn, auto_scan_fn): elif raw_input == "8": install_bash_hook() continue + elif raw_input == "9": + view_stats_and_mastery(state_manager) + continue elif raw_input == "0" or raw_input.lower() == "done": choice = ( input( diff --git a/commando/utils/io.py b/commando/utils/io.py index 92a4fd5..6140c44 100644 --- a/commando/utils/io.py +++ b/commando/utils/io.py @@ -81,3 +81,23 @@ def pause(): input(f"\n{YELLOW}Press Enter to continue...{RESET}") except (EOFError, KeyboardInterrupt): print() + + +def get_category_color(category): + cat_lower = category.lower() + if "file" in cat_lower or "disk" in cat_lower: + return CYAN + elif "network" in cat_lower or "web" in cat_lower: + return MAGENTA + elif "process" in cat_lower or "system" in cat_lower: + return RED + elif "navig" in cat_lower or "search" in cat_lower: + return GREEN + elif "text" in cat_lower or "edit" in cat_lower: + return YELLOW + else: + return BOLD + +def format_badge(category): + color = get_category_color(category) + return f"[{color}{category}{RESET}]" From 0c00dbdd26c45146cd383861896636b8d1320af6 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 19:18:19 +0000 Subject: [PATCH 2/2] fix: Address PR comments - Refactored `get_category_color` to use independent if statements - Updated mastery display loop to use `display_score` instead of redefining `score`, and replaced elif chains with ifs - Updated `session_history` dictionary inserts to pop the key first so it's moved to the end, correctly tracking the most recently used items. Co-authored-by: MnemOnicE <170563909+MnemOnicE@users.noreply.github.com> --- commando/core/audit.py | 5 ++++- commando/ui/dashboard.py | 19 ++++++++++++------- commando/utils/io.py | 11 +++++------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/commando/core/audit.py b/commando/core/audit.py index f89202f..8c15c86 100644 --- a/commando/core/audit.py +++ b/commando/core/audit.py @@ -44,7 +44,10 @@ def search_command( all_known = state_manager.get_all_known_commands() if not headless: - session_history[base_command] = session_history.get(base_command, 0) + 1 + val = session_history.get(base_command, 0) + 1 + if base_command in session_history: + session_history.pop(base_command) + session_history[base_command] = val state_manager.save_history() if base_command in all_known: diff --git a/commando/ui/dashboard.py b/commando/ui/dashboard.py index 5c7cde5..7559d88 100644 --- a/commando/ui/dashboard.py +++ b/commando/ui/dashboard.py @@ -84,17 +84,17 @@ def view_stats_and_mastery(state_manager): print(f"\n{CYAN}{BOLD}Command Mastery:{RESET}") for cmd, score in sorted_history: # Mastery goes up to 5 - score = min(5, max(0, score)) - filled = "█" * score - empty = "░" * (5 - score) + display_score = min(5, max(0, score)) + filled = "█" * display_score + empty = "░" * (5 - display_score) bar = f"{filled}{empty}" # Color coding the progress bar - if score >= 4: + if display_score >= 4: bar_color = GREEN - elif score >= 2: + if 2 <= display_score < 4: bar_color = YELLOW - else: + if display_score < 2: bar_color = RED print(f" {bar_color}[{bar}]{RESET} {BOLD}{cmd}{RESET}") @@ -260,10 +260,15 @@ def run_quiz(state_manager): if ans == q_cmd: print(f"{GREEN}Correct!{RESET}\n") - session_history[q_cmd] = min(5, session_history.get(q_cmd, 0) + 1) + val = min(5, session_history.get(q_cmd, 0) + 1) + if q_cmd in session_history: + session_history.pop(q_cmd) + session_history[q_cmd] = val score += 1 else: print(f"{RED}Incorrect.{RESET} The answer was '{BOLD}{q_cmd}{RESET}'.\n") + if q_cmd in session_history: + session_history.pop(q_cmd) session_history[q_cmd] = 0 save_json(HISTORY_FILE, session_history) diff --git a/commando/utils/io.py b/commando/utils/io.py index 6140c44..e58a6bb 100644 --- a/commando/utils/io.py +++ b/commando/utils/io.py @@ -87,16 +87,15 @@ def get_category_color(category): cat_lower = category.lower() if "file" in cat_lower or "disk" in cat_lower: return CYAN - elif "network" in cat_lower or "web" in cat_lower: + if "network" in cat_lower or "web" in cat_lower: return MAGENTA - elif "process" in cat_lower or "system" in cat_lower: + if "process" in cat_lower or "system" in cat_lower: return RED - elif "navig" in cat_lower or "search" in cat_lower: + if "navig" in cat_lower or "search" in cat_lower: return GREEN - elif "text" in cat_lower or "edit" in cat_lower: + if "text" in cat_lower or "edit" in cat_lower: return YELLOW - else: - return BOLD + return BOLD def format_badge(category): color = get_category_color(category)