diff --git a/bin/toolbox b/bin/toolbox new file mode 100755 index 0000000..d0f7c58 --- /dev/null +++ b/bin/toolbox @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +""" +toolbox — interaktiver Terminal-Tool-Launcher +Läuft auf macOS (iTerm2) und Linux (Xubuntu/xfce4-terminal, gnome-terminal, …) +""" + +import subprocess +import shutil +import sys +import os +import platform +from dataclasses import dataclass, field + +IS_MAC = platform.system() == "Darwin" +IS_LINUX = platform.system() == "Linux" + + +@dataclass +class Tool: + category: str + name: str + description: str + command: str + binary: str # Binary für Verfügbarkeitscheck + new_tab: bool = True # TUI → neuer Tab, Output-Tools → inline + mac: bool = True # auf macOS anzeigen + linux: bool = True # auf Linux anzeigen + + +TOOLS = [ + # --- Git --- + Tool("Git", "lazygit", "Git TUI: stagen, committen, pushen, rebasen", "lazygit", "lazygit"), + Tool("Git", "gitcheck", "Status aller Repos prüfen", "~/git-check-all.sh", "git", new_tab=False), + Tool("Git", "gitsync", "Alle Repos mit Gitea synchronisieren", "~/git-projekte/dotfiles-rene/bin/git-sync-all.sh", "git", new_tab=False), + Tool("Git", "git log", "Commit-History (mit delta, side-by-side)", "git log -p", "git", new_tab=False), + Tool("Git", "git diff", "Änderungen anzeigen (mit delta)", "git diff", "git", new_tab=False), + + # --- Navigation & Dateien --- + Tool("Dateien", "yazi", "Terminal-Dateimanager (q = quit)", "yazi", "yazi"), + Tool("Dateien", "fzf", "Fuzzy-Finder (Ctrl+T Dateien, Ctrl+R History)", "fzf", "fzf"), + Tool("Dateien", "ncdu", "Interaktive Festplattennutzung", "ncdu ~", "ncdu"), + Tool("Dateien", "duf", "Übersicht freier Speicherplatz", "duf", "duf", new_tab=False), + Tool("Dateien", "fd", "Schnelles find (Beispiel: fd .py)", "fd", "fd", new_tab=False), + Tool("Dateien", "rg", "Blitzschnelles grep (Beispiel: rg TODO)", "rg", "rg", new_tab=False), + + # --- Anzeige --- + Tool("Anzeige", "bat", "cat mit Syntax-Highlighting", "bat", "bat", new_tab=False), + Tool("Anzeige", "eza -la", "Modernes ls mit Details, Farben, Git-Status", "eza -la", "eza", new_tab=False), + Tool("Anzeige", "eza -T", "Verzeichnisbaum", "eza -T", "eza", new_tab=False), + Tool("Anzeige", "delta", "Schöne Git-Diffs (wird automatisch verwendet)", "git diff HEAD~1 | delta", "delta", new_tab=False), + + # --- System & Monitoring --- + Tool("System", "btop", "Systemmonitor (CPU/RAM/Netz/Prozesse)", "btop", "btop"), + Tool("System", "fastfetch", "Systeminfo Übersicht", "fastfetch", "fastfetch", new_tab=False), + Tool("System", "temps", "CPU/GPU-Temperatur + Akku (Mac)", "sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1", + "sudo", new_tab=False, linux=False), + + # --- Netzwerk --- + Tool("Netzwerk", "nmap", "Netzwerk-Scanner (Beispiel: nmap 10.47.11.0/24)", "nmap -sn 10.47.11.0/24", "nmap", new_tab=False), + + # --- Berechnung --- + Tool("Rechnen", "units", "Einheitenumrechnung (Beispiel: units '1 kWh' MJ)", "units", "units"), + Tool("Rechnen", "python3", "Python REPL für schnelle Berechnungen", "python3", "python3"), + + # --- KI --- + Tool("KI", "ki-chat", "Offline-KI interaktiver Chat", "ki interactive", "ki"), + Tool("KI", "ki-agent", "Offline-KI Agent-Modus (Datei-/Shell-Zugriff)", "ki interactive --agent-mode", "ki"), + Tool("KI", "ki-commit", "Commit-Message mit KI generieren", "ki commit", "ki", new_tab=False), + Tool("KI", "ki-diff", "Git-Diff mit KI erklären lassen", "ki diff", "ki", new_tab=False), + + # --- Screensaver / Spass --- + Tool("Spass", "cmatrix", "Matrix-Regen (q = quit)", "cmatrix -sab", "cmatrix"), + Tool("Spass", "asciiquarium", "Aquarium im Terminal (q = quit)", "asciiquarium", "asciiquarium"), + Tool("Spass", "pipes.sh", "Animierte Rohre (q = quit)", "pipes.sh -t 0 -p 4", "pipes.sh"), + Tool("Spass", "cbonsai", "Wachsender Bonsai-Baum (q = quit)", "cbonsai -l", "cbonsai"), + Tool("Spass", "nms", "Sneakers-Entschlüsselungseffekt", "ls -la | nms", "nms", new_tab=False), +] + + +# --- Binaries die auf Linux anders heissen --- +LINUX_ALIASES = { + "fd": "fdfind", + "bat": "batcat", +} + + +def is_available(tool: Tool) -> bool: + if IS_MAC and not tool.mac: + return False + if IS_LINUX and not tool.linux: + return False + binary = tool.binary + if IS_LINUX: + binary = LINUX_ALIASES.get(binary, binary) + return shutil.which(binary) is not None + + +def resolve_command(command: str) -> str: + """Passt Befehle für Linux an (bat→batcat etc.).""" + if IS_LINUX: + for mac_bin, linux_bin in LINUX_ALIASES.items(): + if command.startswith(mac_bin + " ") or command == mac_bin: + command = linux_bin + command[len(mac_bin):] + return command + + +def detect_linux_terminal() -> list[str]: + """Findet einen verfügbaren Terminal-Emulator auf Linux.""" + candidates = [ + (["xfce4-terminal", "--tab", "-e"], "xfce4-terminal"), + (["gnome-terminal", "--tab", "--"], "gnome-terminal"), + (["kitty", "bash", "-c"], "kitty"), + (["alacritty", "-e"], "alacritty"), + (["xterm", "-e"], "xterm"), + ] + for args, binary in candidates: + if shutil.which(binary): + return args + return [] + + +def open_new_tab(command: str): + """Öffnet Befehl in neuem Tab — macOS oder Linux.""" + if IS_MAC: + script = f''' + tell application "iTerm2" + activate + tell current window + create tab with default profile + tell current session + write text "{command}" + end tell + end tell + end tell + ''' + subprocess.run(["osascript", "-e", script], capture_output=True) + else: + terminal_args = detect_linux_terminal() + if terminal_args: + subprocess.Popen(terminal_args + [f"bash -c '{command}; exec bash'"]) + else: + # Fallback: inline + os.system(command) + + +def run_inline(command: str): + os.system(command) + + +def main(): + available = [t for t in TOOLS if is_available(t)] + + if not shutil.which("fzf"): + print("fzf nicht gefunden – bitte installieren:") + print(" macOS: brew install fzf") + print(" Linux: sudo apt install fzf") + sys.exit(1) + + fzf_lines = [ + f"{t.category:<12} {t.name:<20} {t.description}" + for t in available + ] + + result = subprocess.run( + [ + "fzf", + "--ansi", + "--height=70%", + "--layout=reverse", + "--border=rounded", + "--prompt= Tools > ", + "--header= Kategorie Name Beschreibung\n ─────────────────────────────────────────────────────────────", + "--color=header:italic:cyan,prompt:green,pointer:green", + ], + input="\n".join(fzf_lines), + text=True, + capture_output=True, + ) + + if result.returncode != 0 or not result.stdout.strip(): + sys.exit(0) + + chosen_line = result.stdout.strip() + chosen_tool = None + for i, line in enumerate(fzf_lines): + if line == chosen_line: + chosen_tool = available[i] + break + + if not chosen_tool: + sys.exit(0) + + command = resolve_command(chosen_tool.command) + print(f"\n▶ {chosen_tool.name} — {command}\n") + + if chosen_tool.new_tab: + open_new_tab(command) + else: + run_inline(command) + + +if __name__ == "__main__": + main() diff --git a/zsh/.zshrc b/zsh/.zshrc index 8284b72..ef97a07 100644 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -97,8 +97,11 @@ alias ki-tl='ki tl' alias fetch="fastfetch" alias temps="sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1" -# Cheat-Sheet: alle Tools, Aliases und Skripte auf einen Blick -tools() { +# Interaktiver Tool-Launcher (fzf + iTerm2/xfce4-terminal) +alias tools='toolbox' + +# Cheat-Sheet: statische Referenz (tools-ref für Vollübersicht) +tools-ref() { cat <<'TOOLS' ╔══════════════════════════════════════════════════════════════╗ @@ -225,6 +228,8 @@ tools() { TOOLS } +# Kurzform +alias tr='tools-ref' # Terminal-Screensaver: zufaellig cmatrix oder asciiquarium nach 5 Min Idle TMOUT=300