toolbox: Kategorie-Navigation, neues Fenster, tools-Symlink
- Zweistufiges Menü: Kategorie → Tool (mit Esc zurück) - Preview-Pane zeigt Beschreibung + Befehl beim Navigieren - Öffnet immer in neuem Fenster mit current profile im aktuellen Verzeichnis - macOS: iTerm2 new window, Linux: xfce4-terminal/gnome-terminal/kitty/alacritty - Alias tools=toolbox entfernt (tools läuft jetzt als eigenständiges Binary) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c5915545ec
commit
562ebb64f2
2 changed files with 169 additions and 133 deletions
299
bin/toolbox
299
bin/toolbox
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
toolbox — interaktiver Terminal-Tool-Launcher
|
toolbox — interaktiver Terminal-Tool-Launcher mit Kategorie-Navigation
|
||||||
Läuft auf macOS (iTerm2) und Linux (Xubuntu/xfce4-terminal, gnome-terminal, …)
|
Läuft auf macOS (iTerm2) und Linux (Xubuntu/xfce4-terminal, gnome-terminal, …)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -9,195 +9,234 @@ import shutil
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
from dataclasses import dataclass, field
|
import shlex
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
IS_MAC = platform.system() == "Darwin"
|
IS_MAC = platform.system() == "Darwin"
|
||||||
IS_LINUX = platform.system() == "Linux"
|
IS_LINUX = platform.system() == "Linux"
|
||||||
|
|
||||||
|
CURRENT_DIR = os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Tool:
|
class Tool:
|
||||||
category: str
|
category: str
|
||||||
name: str
|
name: str
|
||||||
description: str
|
description: str
|
||||||
command: str
|
command: str
|
||||||
binary: str # Binary für Verfügbarkeitscheck
|
binary: str
|
||||||
new_tab: bool = True # TUI → neuer Tab, Output-Tools → inline
|
mac: bool = True
|
||||||
mac: bool = True # auf macOS anzeigen
|
linux: bool = True
|
||||||
linux: bool = True # auf Linux anzeigen
|
|
||||||
|
|
||||||
|
|
||||||
TOOLS = [
|
TOOLS = [
|
||||||
# --- Git ---
|
# --- Git ---
|
||||||
Tool("Git", "lazygit", "Git TUI: stagen, committen, pushen, rebasen", "lazygit", "lazygit"),
|
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", "gitcheck", "Status aller Repos prüfen", "~/git-check-all.sh", "git"),
|
||||||
Tool("Git", "gitsync", "Alle Repos mit Gitea synchronisieren", "~/git-projekte/dotfiles-rene/bin/git-sync-all.sh", "git", new_tab=False),
|
Tool("Git", "gitsync", "Alle Repos mit Gitea synchronisieren", "~/git-projekte/dotfiles-rene/bin/git-sync-all.sh", "git"),
|
||||||
Tool("Git", "git log", "Commit-History (mit delta, side-by-side)", "git log -p", "git", new_tab=False),
|
Tool("Git", "git log", "Commit-History (mit delta, side-by-side)", "git log -p", "git"),
|
||||||
Tool("Git", "git diff", "Änderungen anzeigen (mit delta)", "git diff", "git", new_tab=False),
|
Tool("Git", "git diff", "Änderungen anzeigen (mit delta)", "git diff", "git"),
|
||||||
|
|
||||||
# --- Navigation & Dateien ---
|
# --- Navigation & Dateien ---
|
||||||
Tool("Dateien", "yazi", "Terminal-Dateimanager (q = quit)", "yazi", "yazi"),
|
Tool("Dateien", "yazi", "Terminal-Dateimanager (q = quit)", "yazi", "yazi"),
|
||||||
Tool("Dateien", "fzf", "Fuzzy-Finder (Ctrl+T Dateien, Ctrl+R History)", "fzf", "fzf"),
|
Tool("Dateien", "fzf", "Fuzzy-Finder: Dateien und History durchsuchen", "fzf", "fzf"),
|
||||||
Tool("Dateien", "ncdu", "Interaktive Festplattennutzung", "ncdu ~", "ncdu"),
|
Tool("Dateien", "ncdu", "Interaktive Festplattennutzung", "ncdu ~", "ncdu"),
|
||||||
Tool("Dateien", "duf", "Übersicht freier Speicherplatz", "duf", "duf", new_tab=False),
|
Tool("Dateien", "duf", "Übersicht freier Speicherplatz", "duf", "duf"),
|
||||||
Tool("Dateien", "fd", "Schnelles find (Beispiel: fd .py)", "fd", "fd", new_tab=False),
|
Tool("Dateien", "fd", "Schnelles find (Beispiel: fd .py)", "fd", "fd"),
|
||||||
Tool("Dateien", "rg", "Blitzschnelles grep (Beispiel: rg TODO)", "rg", "rg", new_tab=False),
|
Tool("Dateien", "rg", "Blitzschnelles grep (Beispiel: rg TODO)", "rg", "rg"),
|
||||||
|
|
||||||
# --- Anzeige ---
|
# --- Anzeige ---
|
||||||
Tool("Anzeige", "bat", "cat mit Syntax-Highlighting", "bat", "bat", new_tab=False),
|
Tool("Anzeige", "bat", "cat mit Syntax-Highlighting", "bat", "bat"),
|
||||||
Tool("Anzeige", "eza -la", "Modernes ls mit Details, Farben, Git-Status", "eza -la", "eza", new_tab=False),
|
Tool("Anzeige", "eza -la", "Modernes ls mit Details, Farben, Git-Status", "eza -la", "eza"),
|
||||||
Tool("Anzeige", "eza -T", "Verzeichnisbaum", "eza -T", "eza", new_tab=False),
|
Tool("Anzeige", "eza -T", "Verzeichnisbaum", "eza -T", "eza"),
|
||||||
Tool("Anzeige", "delta", "Schöne Git-Diffs (wird automatisch verwendet)", "git diff HEAD~1 | delta", "delta", new_tab=False),
|
Tool("Anzeige", "delta", "Schöne Git-Diffs (wird automatisch verwendet)", "git diff HEAD~1 | delta", "delta"),
|
||||||
|
|
||||||
# --- System & Monitoring ---
|
# --- System & Monitoring ---
|
||||||
Tool("System", "btop", "Systemmonitor (CPU/RAM/Netz/Prozesse)", "btop", "btop"),
|
Tool("System", "btop", "Systemmonitor: CPU, RAM, Netz, Prozesse", "btop", "btop"),
|
||||||
Tool("System", "fastfetch", "Systeminfo Übersicht", "fastfetch", "fastfetch", new_tab=False),
|
Tool("System", "fastfetch", "Systeminfo-Übersicht", "fastfetch", "fastfetch"),
|
||||||
Tool("System", "temps", "CPU/GPU-Temperatur + Akku (Mac)", "sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1",
|
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),
|
"sudo", linux=False),
|
||||||
|
|
||||||
# --- Netzwerk ---
|
# --- Netzwerk ---
|
||||||
Tool("Netzwerk", "nmap", "Netzwerk-Scanner (Beispiel: nmap 10.47.11.0/24)", "nmap -sn 10.47.11.0/24", "nmap", new_tab=False),
|
Tool("Netzwerk", "nmap", "Netzwerk-Scanner (Beispiel: nmap 10.47.11.0/24)", "nmap -sn 10.47.11.0/24", "nmap"),
|
||||||
|
|
||||||
# --- Berechnung ---
|
# --- Berechnung ---
|
||||||
Tool("Rechnen", "units", "Einheitenumrechnung (Beispiel: units '1 kWh' MJ)", "units", "units"),
|
Tool("Rechnen", "units", "Einheitenumrechnung (Beispiel: units 1kWh MJ)", "units", "units"),
|
||||||
Tool("Rechnen", "python3", "Python REPL für schnelle Berechnungen", "python3", "python3"),
|
Tool("Rechnen", "python3", "Python REPL für schnelle Berechnungen", "python3", "python3"),
|
||||||
|
|
||||||
# --- KI ---
|
# --- KI ---
|
||||||
Tool("KI", "ki-chat", "Offline-KI interaktiver Chat", "ki interactive", "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-agent", "Offline-KI Agent-Modus: Datei- und 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-commit", "Commit-Message mit KI generieren", "ki commit", "ki"),
|
||||||
Tool("KI", "ki-diff", "Git-Diff mit KI erklären lassen", "ki diff", "ki", new_tab=False),
|
Tool("KI", "ki-diff", "Git-Diff mit KI erklären lassen", "ki diff", "ki"),
|
||||||
|
|
||||||
# --- Screensaver / Spass ---
|
# --- Screensaver / Spass ---
|
||||||
Tool("Spass", "cmatrix", "Matrix-Regen (q = quit)", "cmatrix -sab", "cmatrix"),
|
Tool("Spass", "cmatrix", "Matrix-Regen (q = quit)", "cmatrix -sab", "cmatrix"),
|
||||||
Tool("Spass", "asciiquarium", "Aquarium im Terminal (q = quit)", "asciiquarium", "asciiquarium"),
|
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", "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", "cbonsai", "Wachsender Bonsai-Baum (q = quit)", "cbonsai -l", "cbonsai"),
|
||||||
Tool("Spass", "nms", "Sneakers-Entschlüsselungseffekt", "ls -la | nms", "nms", new_tab=False),
|
Tool("Spass", "nms", "Sneakers-Entschlüsselungseffekt", "ls -la | nms", "nms"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# --- Binaries die auf Linux anders heissen ---
|
|
||||||
LINUX_ALIASES = {
|
LINUX_ALIASES = {
|
||||||
"fd": "fdfind",
|
"fd": "fdfind",
|
||||||
"bat": "batcat",
|
"bat": "batcat",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FZF_BASE = [
|
||||||
|
"fzf", "--ansi",
|
||||||
|
"--height=80%", "--layout=reverse", "--border=rounded",
|
||||||
|
"--color=header:italic:cyan,prompt:green,pointer:green,border:blue",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def is_available(tool: Tool) -> bool:
|
def is_available(tool: Tool) -> bool:
|
||||||
if IS_MAC and not tool.mac:
|
if IS_MAC and not tool.mac:
|
||||||
return False
|
return False
|
||||||
if IS_LINUX and not tool.linux:
|
if IS_LINUX and not tool.linux:
|
||||||
return False
|
return False
|
||||||
binary = tool.binary
|
binary = LINUX_ALIASES.get(tool.binary, tool.binary) if IS_LINUX else tool.binary
|
||||||
if IS_LINUX:
|
|
||||||
binary = LINUX_ALIASES.get(binary, binary)
|
|
||||||
return shutil.which(binary) is not None
|
return shutil.which(binary) is not None
|
||||||
|
|
||||||
|
|
||||||
def resolve_command(command: str) -> str:
|
def resolve_command(cmd: str) -> str:
|
||||||
"""Passt Befehle für Linux an (bat→batcat etc.)."""
|
|
||||||
if IS_LINUX:
|
if IS_LINUX:
|
||||||
for mac_bin, linux_bin in LINUX_ALIASES.items():
|
for mac_bin, linux_bin in LINUX_ALIASES.items():
|
||||||
if command.startswith(mac_bin + " ") or command == mac_bin:
|
if cmd == mac_bin or cmd.startswith(mac_bin + " "):
|
||||||
command = linux_bin + command[len(mac_bin):]
|
return linux_bin + cmd[len(mac_bin):]
|
||||||
return command
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
def detect_linux_terminal() -> list[str]:
|
def open_new_window(command: str) -> None:
|
||||||
"""Findet einen verfügbaren Terminal-Emulator auf Linux."""
|
"""Öffnet den Befehl in einem neuen Fenster im aktuellen Verzeichnis."""
|
||||||
candidates = [
|
full_cmd = f"cd {shlex.quote(CURRENT_DIR)} && {command}"
|
||||||
(["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:
|
if IS_MAC:
|
||||||
script = f'''
|
escaped = full_cmd.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
tell application "iTerm2"
|
script = (
|
||||||
activate
|
'tell application "iTerm2"\n'
|
||||||
tell current window
|
' activate\n'
|
||||||
create tab with default profile
|
' set w to (create window with current profile)\n'
|
||||||
tell current session
|
' tell current session of w\n'
|
||||||
write text "{command}"
|
f' write text "{escaped}"\n'
|
||||||
end tell
|
' end tell\n'
|
||||||
end tell
|
'end tell\n'
|
||||||
end tell
|
)
|
||||||
'''
|
|
||||||
subprocess.run(["osascript", "-e", script], capture_output=True)
|
subprocess.run(["osascript", "-e", script], capture_output=True)
|
||||||
else:
|
return
|
||||||
terminal_args = detect_linux_terminal()
|
|
||||||
if terminal_args:
|
|
||||||
subprocess.Popen(terminal_args + [f"bash -c '{command}; exec bash'"])
|
|
||||||
else:
|
|
||||||
# Fallback: inline
|
|
||||||
os.system(command)
|
|
||||||
|
|
||||||
|
# Linux: Terminal-Emulator nach Verfügbarkeit
|
||||||
def run_inline(command: str):
|
bash_cmd = f"{command}; exec bash"
|
||||||
os.system(command)
|
candidates = [
|
||||||
|
("xfce4-terminal", ["xfce4-terminal",
|
||||||
|
f"--working-directory={CURRENT_DIR}",
|
||||||
def main():
|
"-e", f"bash -c {shlex.quote(bash_cmd)}"]),
|
||||||
available = [t for t in TOOLS if is_available(t)]
|
("gnome-terminal", ["gnome-terminal",
|
||||||
|
f"--working-directory={CURRENT_DIR}",
|
||||||
if not shutil.which("fzf"):
|
"--", "bash", "-c", bash_cmd]),
|
||||||
print("fzf nicht gefunden – bitte installieren:")
|
("kitty", ["kitty", "--directory", CURRENT_DIR,
|
||||||
print(" macOS: brew install fzf")
|
"bash", "-c", bash_cmd]),
|
||||||
print(" Linux: sudo apt install fzf")
|
("alacritty", ["alacritty", "--working-directory", CURRENT_DIR,
|
||||||
sys.exit(1)
|
"-e", "bash", "-c", bash_cmd]),
|
||||||
|
("xterm", ["xterm", "-e",
|
||||||
fzf_lines = [
|
f"bash -c {shlex.quote(full_cmd + '; exec bash')}"]),
|
||||||
f"{t.category:<12} {t.name:<20} {t.description}"
|
|
||||||
for t in available
|
|
||||||
]
|
]
|
||||||
|
for binary, args in candidates:
|
||||||
|
if shutil.which(binary):
|
||||||
|
subprocess.Popen(args)
|
||||||
|
return
|
||||||
|
|
||||||
|
os.system(full_cmd) # Fallback: inline
|
||||||
|
|
||||||
|
|
||||||
|
def fzf_run(items: list[str], extra_args: list[str]) -> str | None:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[
|
_FZF_BASE + extra_args,
|
||||||
"fzf",
|
input="\n".join(items),
|
||||||
"--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,
|
text=True,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
)
|
)
|
||||||
|
return result.stdout.strip() if result.returncode == 0 and result.stdout.strip() else None
|
||||||
|
|
||||||
if result.returncode != 0 or not result.stdout.strip():
|
|
||||||
|
def main() -> None:
|
||||||
|
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)
|
||||||
|
|
||||||
|
available = [t for t in TOOLS if is_available(t)]
|
||||||
|
categories = list(dict.fromkeys(t.category for t in available))
|
||||||
|
ALL = "★ Alle Tools"
|
||||||
|
|
||||||
|
# Kategorie-Vorschau: Anzahl verfügbarer Tools pro Kategorie
|
||||||
|
cat_counts = {c: sum(1 for t in available if t.category == c) for c in categories}
|
||||||
|
cat_items = [f"{ALL} ({len(available)})"] + [
|
||||||
|
f"{c} ({cat_counts[c]})" for c in categories
|
||||||
|
]
|
||||||
|
|
||||||
|
# Preview für Kategorien: Tools der markierten Kategorie anzeigen
|
||||||
|
# {1} = Kategoriename (erstes Wort), fzf-Feldreferenz
|
||||||
|
cat_preview = (
|
||||||
|
"cat << 'CATEOF'\n" # Dummy — wir nutzen awk auf die Eingabeliste
|
||||||
|
)
|
||||||
|
# Einfacherer Ansatz: kein Preview auf Kategorie-Ebene, nur auf Tool-Ebene
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# ── Schritt 1: Kategorie wählen ──────────────────────────────────────
|
||||||
|
cat_choice = fzf_run(
|
||||||
|
cat_items,
|
||||||
|
[
|
||||||
|
"--prompt= Kategorie > ",
|
||||||
|
"--header= toolbox · Kategorie wählen (Esc = beenden)",
|
||||||
|
"--no-preview",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
if not cat_choice:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if cat_choice.startswith(ALL[:3]): # "★ Alle …"
|
||||||
|
filtered, cat_label = available, "Alle Tools"
|
||||||
|
else:
|
||||||
|
cat_label = cat_choice.split(" (")[0] # Name ohne "(N)"
|
||||||
|
filtered = [t for t in available if t.category == cat_label]
|
||||||
|
|
||||||
|
# ── Schritt 2: Tool wählen ───────────────────────────────────────────
|
||||||
|
# Felder TAB-getrennt: name \t description \t command
|
||||||
|
tool_lines = [f"{t.name}\t{t.description}\t{t.command}" for t in filtered]
|
||||||
|
|
||||||
|
# Preview zeigt Beschreibung + Befehl für das markierte Tool.
|
||||||
|
# {2} und {3} sind fzf-Feldreferenzen (TAB-Delimiter), werden von fzf
|
||||||
|
# korrekt gequotet, bevor sie in den Shell-Befehl eingefügt werden.
|
||||||
|
preview = r"printf '\n \033[1m%s\033[0m\n\n \033[33m$\033[0m %s\n' {2} {3}"
|
||||||
|
|
||||||
|
chosen = fzf_run(
|
||||||
|
tool_lines,
|
||||||
|
[
|
||||||
|
f"--prompt= {cat_label} > ",
|
||||||
|
f"--header= ‹ {cat_label} (Esc = zurück zur Kategorie)",
|
||||||
|
"--delimiter=\t",
|
||||||
|
"--with-nth=1,2",
|
||||||
|
f"--preview={preview}",
|
||||||
|
"--preview-window=bottom:5:wrap",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
if not chosen:
|
||||||
|
continue # Esc → zurück zur Kategorie-Auswahl
|
||||||
|
|
||||||
|
parts = chosen.split("\t")
|
||||||
|
if len(parts) < 3:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tool_name, _, tool_cmd = parts[0], parts[1], parts[2]
|
||||||
|
command = resolve_command(tool_cmd)
|
||||||
|
print(f"\n▶ {tool_name} — {command}\n")
|
||||||
|
open_new_window(command)
|
||||||
sys.exit(0)
|
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__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -97,9 +97,6 @@ alias ki-tl='ki tl'
|
||||||
alias fetch="fastfetch"
|
alias fetch="fastfetch"
|
||||||
alias temps="sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1"
|
alias temps="sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1"
|
||||||
|
|
||||||
# Interaktiver Tool-Launcher (fzf + iTerm2/xfce4-terminal)
|
|
||||||
alias tools='toolbox'
|
|
||||||
|
|
||||||
# Cheat-Sheet: statische Referenz (tools-ref für Vollübersicht)
|
# Cheat-Sheet: statische Referenz (tools-ref für Vollübersicht)
|
||||||
tools-ref() {
|
tools-ref() {
|
||||||
cat <<'TOOLS'
|
cat <<'TOOLS'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue