370 lines
10 KiB
Bash
Executable File
370 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
PROJECT_ROOTS=(
|
|
"$HOME/Projekte"
|
|
"$HOME/Projects"
|
|
"$HOME/Code"
|
|
"$HOME/Developer"
|
|
"$HOME/dev"
|
|
"$HOME/test"
|
|
)
|
|
|
|
notify() {
|
|
notify-send " Dev Menue" "$1" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
pick() {
|
|
wofi --dmenu --prompt "$1" --insensitive
|
|
}
|
|
|
|
terminal_hold() {
|
|
local title="$1"
|
|
shift
|
|
|
|
if command -v kitty >/dev/null 2>&1; then
|
|
kitty --title "$title" sh -lc "$*; printf '\n'; read -r -p 'Enter zum Schliessen... ' _"
|
|
else
|
|
notify "kitty ist nicht installiert."
|
|
fi
|
|
}
|
|
|
|
shell_quote() {
|
|
printf '%q' "$1"
|
|
}
|
|
|
|
code_cmd() {
|
|
if command -v code >/dev/null 2>&1; then
|
|
printf '%s\n' code
|
|
elif command -v codium >/dev/null 2>&1; then
|
|
printf '%s\n' codium
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
docker_available() {
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
notify "Docker ist nicht installiert."
|
|
return 1
|
|
fi
|
|
|
|
if ! docker info >/dev/null 2>&1; then
|
|
notify "Docker laeuft nicht oder ist nicht erreichbar."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
has_compose() {
|
|
local project="$1"
|
|
|
|
[[ -f "$project/compose.yml" ||
|
|
-f "$project/compose.yaml" ||
|
|
-f "$project/docker-compose.yml" ||
|
|
-f "$project/docker-compose.yaml" ]]
|
|
}
|
|
|
|
project_label() {
|
|
local project="$1"
|
|
local marker=""
|
|
|
|
if [[ -d "$project/.git" ]]; then
|
|
marker+=" "
|
|
fi
|
|
|
|
if has_compose "$project"; then
|
|
marker+=" "
|
|
fi
|
|
|
|
printf '%s%s' "$marker" "${project#$HOME/}"
|
|
}
|
|
|
|
pick_project() {
|
|
local roots=()
|
|
local projects=()
|
|
local labels=()
|
|
local root project choice
|
|
|
|
for root in "${PROJECT_ROOTS[@]}"; do
|
|
[[ -d "$root" ]] && roots+=("$root")
|
|
done
|
|
|
|
if ((${#roots[@]} == 0)); then
|
|
notify "Keine Projektordner gefunden."
|
|
return 1
|
|
fi
|
|
|
|
mapfile -t projects < <(
|
|
{
|
|
find "${roots[@]}" -maxdepth 4 -type d -name .git -printf '%h\n' 2>/dev/null
|
|
find "${roots[@]}" -maxdepth 3 -type d \( -name node_modules -o -name vendor \) -prune -o \
|
|
-type f \( -name compose.yml -o -name compose.yaml -o -name docker-compose.yml -o -name docker-compose.yaml -o -name package.json -o -name Cargo.toml -o -name pyproject.toml -o -name go.mod \) \
|
|
-printf '%h\n' 2>/dev/null
|
|
} |
|
|
sort -u
|
|
)
|
|
|
|
if ((${#projects[@]} == 0)); then
|
|
notify "Keine Projekte gefunden."
|
|
return 1
|
|
fi
|
|
|
|
for project in "${projects[@]}"; do
|
|
labels+=("$(project_label "$project")")
|
|
done
|
|
|
|
choice="$(printf '%s\n' "${labels[@]}" | pick "📁 Projekt")"
|
|
[[ -z "${choice:-}" ]] && return 1
|
|
|
|
for i in "${!labels[@]}"; do
|
|
if [[ "$choice" == "${labels[$i]}" ]]; then
|
|
printf '%s\n' "${projects[$i]}"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
open_project_browser() {
|
|
local project="$1"
|
|
local choice url
|
|
|
|
choice="$(
|
|
printf '%s\n' \
|
|
"🌐 http://localhost:3000" \
|
|
"🌐 http://localhost:5173" \
|
|
"🌐 http://localhost:8000" \
|
|
"🌐 http://localhost:8080" \
|
|
"🌐 http://localhost:5000" \
|
|
"🌐 http://localhost:4200" \
|
|
"📂 Projektordner im Browser" |
|
|
pick "🌐 Projekt im Browser"
|
|
)"
|
|
|
|
case "$choice" in
|
|
*"Projektordner"*)
|
|
xdg-open "$project" >/dev/null 2>&1 &
|
|
;;
|
|
*"http"*)
|
|
url="${choice#* }"
|
|
xdg-open "$url" >/dev/null 2>&1 &
|
|
;;
|
|
esac
|
|
}
|
|
|
|
project_menu() {
|
|
local project project_q choice editor
|
|
|
|
project="$(pick_project)" || return 0
|
|
project_q="$(shell_quote "$project")"
|
|
|
|
choice="$(
|
|
printf '%s\n' \
|
|
"📂 Projekt oeffnen (Code)" \
|
|
"🌐 Projekt im Browser oeffnen" \
|
|
"🐳 Docker Compose starten" \
|
|
"🛑 Docker stoppen" \
|
|
"🔄 Container neu starten" \
|
|
"📜 Logs anzeigen" \
|
|
"📦 Git Repo Status anzeigen" |
|
|
pick "📁 $(basename "$project")"
|
|
)"
|
|
|
|
case "$choice" in
|
|
*"Projekt oeffnen"*)
|
|
if editor="$(code_cmd)"; then
|
|
"$editor" "$project" >/dev/null 2>&1 &
|
|
else
|
|
notify "VS Code/Codium ist nicht installiert."
|
|
fi
|
|
;;
|
|
*"Browser"*)
|
|
open_project_browser "$project"
|
|
;;
|
|
*"Docker Compose starten"*)
|
|
docker_available || return 0
|
|
if has_compose "$project"; then
|
|
terminal_hold "Docker Compose: $(basename "$project")" "cd $project_q && docker compose up -d && docker compose ps"
|
|
else
|
|
notify "Kein Docker-Compose File im Projekt."
|
|
fi
|
|
;;
|
|
*"Docker stoppen"*)
|
|
docker_available || return 0
|
|
if has_compose "$project"; then
|
|
terminal_hold "Docker Stop: $(basename "$project")" "cd $project_q && docker compose stop && docker compose ps"
|
|
else
|
|
notify "Kein Docker-Compose File im Projekt."
|
|
fi
|
|
;;
|
|
*"Container neu starten"*)
|
|
docker_available || return 0
|
|
if has_compose "$project"; then
|
|
terminal_hold "Docker Restart: $(basename "$project")" "cd $project_q && docker compose restart && docker compose ps"
|
|
else
|
|
notify "Kein Docker-Compose File im Projekt."
|
|
fi
|
|
;;
|
|
*"Logs anzeigen"*)
|
|
docker_available || return 0
|
|
if has_compose "$project"; then
|
|
if command -v kitty >/dev/null 2>&1; then
|
|
kitty --title "Logs: $(basename "$project")" sh -lc "cd $project_q && docker compose logs -f --tail=200"
|
|
else
|
|
notify "kitty ist nicht installiert."
|
|
fi
|
|
else
|
|
notify "Kein Docker-Compose File im Projekt."
|
|
fi
|
|
;;
|
|
*"Git Repo Status"*)
|
|
if [[ -d "$project/.git" ]]; then
|
|
terminal_hold "Git Status: $(basename "$project")" "cd $project_q && git status --short --branch"
|
|
else
|
|
notify "Kein Git Repository."
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
pick_container() {
|
|
local containers=()
|
|
local labels=()
|
|
local line name status choice
|
|
|
|
docker_available || return 1
|
|
|
|
mapfile -t containers < <(docker ps -a --format '{{.Names}}|{{.Status}}' | sort)
|
|
if ((${#containers[@]} == 0)); then
|
|
notify "Keine Docker Container gefunden."
|
|
return 1
|
|
fi
|
|
|
|
for line in "${containers[@]}"; do
|
|
name="${line%%|*}"
|
|
status="${line#*|}"
|
|
labels+=("🐳 $name · $status")
|
|
done
|
|
|
|
choice="$(printf '%s\n' "${labels[@]}" | pick "🐳 Container")"
|
|
[[ -z "${choice:-}" ]] && return 1
|
|
|
|
for i in "${!labels[@]}"; do
|
|
if [[ "$choice" == "${labels[$i]}" ]]; then
|
|
printf '%s\n' "${containers[$i]%%|*}"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
docker_menu() {
|
|
local choice container running_ids all_ids
|
|
|
|
choice="$(
|
|
printf '%s\n' \
|
|
"▶️ Alle Container starten" \
|
|
"⏹️ Alle stoppen" \
|
|
"🔄 Einzelnen Container neu starten" \
|
|
"📊 docker stats" \
|
|
"📜 Logs anzeigen" \
|
|
"🧹 Cleanup dangling images" |
|
|
pick "🐳 Docker Control"
|
|
)"
|
|
|
|
case "$choice" in
|
|
*"Alle Container starten"*)
|
|
docker_available || return 0
|
|
all_ids="$(docker ps -aq)"
|
|
if [[ -n "$all_ids" ]]; then
|
|
terminal_hold "Docker Start" "docker start $all_ids && docker ps"
|
|
else
|
|
notify "Keine Container gefunden."
|
|
fi
|
|
;;
|
|
*"Alle stoppen"*)
|
|
docker_available || return 0
|
|
running_ids="$(docker ps -q)"
|
|
if [[ -n "$running_ids" ]]; then
|
|
terminal_hold "Docker Stop" "docker stop $running_ids && docker ps -a"
|
|
else
|
|
notify "Keine laufenden Container."
|
|
fi
|
|
;;
|
|
*"Einzelnen Container neu starten"*)
|
|
container="$(pick_container)" || return 0
|
|
terminal_hold "Docker Restart: $container" "docker restart '$container' && docker ps -a --filter name='^/$container$'"
|
|
;;
|
|
*"docker stats"*)
|
|
docker_available || return 0
|
|
if command -v kitty >/dev/null 2>&1; then
|
|
kitty --title "docker stats" sh -lc "docker stats"
|
|
else
|
|
notify "kitty ist nicht installiert."
|
|
fi
|
|
;;
|
|
*"Logs anzeigen"*)
|
|
container="$(pick_container)" || return 0
|
|
if command -v kitty >/dev/null 2>&1; then
|
|
kitty --title "Logs: $container" sh -lc "docker logs -f --tail=200 '$container'"
|
|
else
|
|
notify "kitty ist nicht installiert."
|
|
fi
|
|
;;
|
|
*"Cleanup dangling images"*)
|
|
docker_available || return 0
|
|
terminal_hold "Docker Cleanup" "docker image prune -f"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
choice="$(
|
|
printf '%s\n' \
|
|
"📁 Projekt Management" \
|
|
" Homelab Controlcenter" \
|
|
"🐳 Docker Control" \
|
|
" Terminal" \
|
|
" Projektordner" \
|
|
" VS Code / Codium" \
|
|
" Git GUI" |
|
|
pick " Dev Menue"
|
|
)"
|
|
|
|
case "$choice" in
|
|
*"Projekt Management"*)
|
|
project_menu
|
|
;;
|
|
*"Homelab Controlcenter"*)
|
|
"$SCRIPT_DIR/homelab-control.sh"
|
|
;;
|
|
*"Docker Control"*)
|
|
docker_menu
|
|
;;
|
|
*"Terminal"*)
|
|
kitty
|
|
;;
|
|
*"Projektordner"*)
|
|
nautilus
|
|
;;
|
|
*"VS Code"*|*"Codium"*)
|
|
if editor="$(code_cmd)"; then
|
|
"$editor" >/dev/null 2>&1 &
|
|
else
|
|
notify "VS Code/Codium ist nicht installiert."
|
|
fi
|
|
;;
|
|
*"Git GUI"*)
|
|
if command -v gitg >/dev/null 2>&1; then
|
|
gitg
|
|
elif command -v git-cola >/dev/null 2>&1; then
|
|
git-cola
|
|
else
|
|
notify "gitg oder git-cola ist nicht installiert."
|
|
fi
|
|
;;
|
|
esac
|