Implement a more simplified and extendable project launcher

This commit is contained in:
Yan Lin 2025-08-01 13:47:43 +02:00
parent 6a9414a8ca
commit 29ba35a57c
7 changed files with 293 additions and 216 deletions

View file

@ -1,12 +1,11 @@
#!/bin/bash
# Universal project launcher - reads project config and launches appropriate template
# Universal project launcher - reads project config and launches dynamic windows
# Usage: project-launcher.sh PROJECT_NAME
PROJECT_NAME="$1"
CONFIG_DIR="$(dirname "$0")/../config"
PROJECTS_JSON="$CONFIG_DIR/projects.json"
TEMPLATES_DIR="$(dirname "$0")/templates"
# Check if tmux session is running
is_session_running() {
@ -25,15 +24,15 @@ if [ -z "$PROJECT_NAME" ]; then
fi
# Parse and display projects with descriptions
jq -r '.projects | to_entries[] | "\(.key)|\(.value.description)|\(.value.template)|\(.value.name)"' "$PROJECTS_JSON" 2>/dev/null | \
while IFS='|' read -r name desc template session_name; do
jq -r '.projects | to_entries[] | "\(.key)|\(.value.description)|\(.value.session)"' "$PROJECTS_JSON" 2>/dev/null | \
while IFS='|' read -r name desc session_name; do
# Check if session is running and format accordingly
if is_session_running "$session_name"; then
printf " \033[1;32m%-12s\033[0m \033[2m[%-8s]\033[0m %s\033[1;32m • Running\033[0m\n" \
"$name" "$template" "$desc"
printf " \033[1;32m%-12s\033[0m %s\033[1;32m • Running\033[0m\n" \
"$name" "$desc"
else
printf " \033[1;32m%-12s\033[0m \033[2m[%-8s]\033[0m %s\n" \
"$name" "$template" "$desc"
printf " \033[1;32m%-12s\033[0m %s\n" \
"$name" "$desc"
fi
done
@ -62,13 +61,18 @@ if [ "$PROJECT_CONFIG" = "null" ]; then
exit 1
fi
TEMPLATE=$(echo "$PROJECT_CONFIG" | jq -r '.template')
SESSION_NAME=$(echo "$PROJECT_CONFIG" | jq -r '.name')
CODE_PATH=$(echo "$PROJECT_CONFIG" | jq -r '.codePath')
CONTENT_PATH=$(echo "$PROJECT_CONFIG" | jq -r '.contentPath // empty')
PAPER_PATH=$(echo "$PROJECT_CONFIG" | jq -r '.paperPath // empty')
SERVER=$(echo "$PROJECT_CONFIG" | jq -r '.server // empty')
REMOTE_DIR=$(echo "$PROJECT_CONFIG" | jq -r '.remoteDir // empty')
SESSION_NAME=$(echo "$PROJECT_CONFIG" | jq -r '.session')
DESCRIPTION=$(echo "$PROJECT_CONFIG" | jq -r '.description // empty')
# Check if session already exists and attach if it does
if is_session_running "$SESSION_NAME"; then
printf "\033[1;32mAttaching to existing session: %s\033[0m\n" "$SESSION_NAME"
tmux attach-session -t "$SESSION_NAME"
exit 0
fi
# Update papis cache
papis cache reset > /dev/null 2>&1
# Create directories if they don't exist
create_directory() {
@ -87,55 +91,118 @@ create_directory() {
fi
}
# Ensure required directories exist
create_directory "$CODE_PATH" "code"
create_directory "$CONTENT_PATH" "content"
create_directory "$PAPER_PATH" "paper"
# Get windows configuration
WINDOWS=$(echo "$PROJECT_CONFIG" | jq -c '.windows[]' 2>/dev/null)
# Record directories in zoxide for smart navigation
[ -n "$CODE_PATH" ] && [ "$CODE_PATH" != "null" ] && [ -d "$CODE_PATH" ] && zoxide add "$CODE_PATH" 2>/dev/null || true
[ -n "$CONTENT_PATH" ] && [ "$CONTENT_PATH" != "null" ] && [ -d "$CONTENT_PATH" ] && zoxide add "$CONTENT_PATH" 2>/dev/null || true
[ -n "$PAPER_PATH" ] && [ "$PAPER_PATH" != "null" ] && [ -d "$PAPER_PATH" ] && zoxide add "$PAPER_PATH" 2>/dev/null || true
# Check if session already exists and attach if it does
if is_session_running "$SESSION_NAME"; then
printf "\033[1;32mAttaching to existing session: %s\033[0m\n" "$SESSION_NAME"
tmux attach-session -t "$SESSION_NAME"
exit 0
if [ -z "$WINDOWS" ]; then
echo "Error: No windows configured for project '$PROJECT_NAME'"
exit 1
fi
# Update papis cache
papis cache reset > /dev/null 2>&1
# Get the first window configuration to create the session
FIRST_WINDOW=$(echo "$WINDOWS" | head -n 1)
FIRST_WINDOW_NAME=$(echo "$FIRST_WINDOW" | jq -r '.name')
FIRST_WINDOW_PATH=$(echo "$FIRST_WINDOW" | jq -r '.path')
# Create remote directory if server connection is configured
if [ -n "$SERVER" ] && [ -n "$REMOTE_DIR" ]; then
printf "\033[2mEnsuring remote directory exists: %s:%s\033[0m\n" "$SERVER" "$REMOTE_DIR"
if ssh "$SERVER" "mkdir -p \"$REMOTE_DIR\"" 2>/dev/null; then
printf "\033[2mRemote directory ready: %s:%s\033[0m\n" "$SERVER" "$REMOTE_DIR"
else
echo "Warning: Could not create or verify remote directory: $SERVER:$REMOTE_DIR"
echo "Please check SSH connection and permissions."
# Create directory for first window
create_directory "$FIRST_WINDOW_PATH" "$FIRST_WINDOW_NAME"
# Record directory in zoxide for smart navigation
[ -n "$FIRST_WINDOW_PATH" ] && [ "$FIRST_WINDOW_PATH" != "null" ] && [ -d "$FIRST_WINDOW_PATH" ] && zoxide add "$FIRST_WINDOW_PATH" 2>/dev/null || true
# Create session with first window
tmux new-session -d -s "$SESSION_NAME" -c "$FIRST_WINDOW_PATH"
# Initialize window counter
WINDOW_INDEX=1
# Process each window configuration
while IFS= read -r window_config; do
WINDOW_NAME=$(echo "$window_config" | jq -r '.name')
WINDOW_PATH=$(echo "$window_config" | jq -r '.path')
# Create directory if it doesn't exist (for subsequent windows)
if [ "$WINDOW_INDEX" -gt 1 ]; then
create_directory "$WINDOW_PATH" "$WINDOW_NAME"
# Record directory in zoxide for smart navigation
[ -n "$WINDOW_PATH" ] && [ "$WINDOW_PATH" != "null" ] && [ -d "$WINDOW_PATH" ] && zoxide add "$WINDOW_PATH" 2>/dev/null || true
fi
fi
# Launch appropriate template
case "$TEMPLATE" in
"basic")
exec "$TEMPLATES_DIR/basic.sh" "$SESSION_NAME" "$CODE_PATH"
;;
"research")
if [ -z "$PAPER_PATH" ]; then
echo "Error: Research template requires paperPath"
exit 1
fi
if [ -n "$SERVER" ] && [ -n "$REMOTE_DIR" ]; then
exec "$TEMPLATES_DIR/research.sh" "$SESSION_NAME" "$CODE_PATH" "$PAPER_PATH" "$SERVER" "$REMOTE_DIR"
# Check window options
NVIM_ENABLED=$(echo "$window_config" | jq -r '.nvim // true')
AI_ENABLED=$(echo "$window_config" | jq -r '.ai // false')
GIT_ENABLED=$(echo "$window_config" | jq -r '.git // false')
SHELL_ENABLED=$(echo "$window_config" | jq -r '.shell // false')
REMOTE_CONFIG=$(echo "$window_config" | jq -r '.remote // empty')
# Create nvim window (default behavior unless explicitly disabled)
if [ "$NVIM_ENABLED" != "false" ]; then
if [ "$WINDOW_INDEX" = 1 ]; then
# First window - rename the existing session window
tmux rename-window -t "$SESSION_NAME:$WINDOW_INDEX" "${WINDOW_NAME}-nvim"
else
exec "$TEMPLATES_DIR/research.sh" "$SESSION_NAME" "$CODE_PATH" "$PAPER_PATH"
# Subsequent windows - create new window
tmux new-window -t "$SESSION_NAME:$WINDOW_INDEX" -n "${WINDOW_NAME}-nvim" -c "$WINDOW_PATH"
fi
;;
*)
echo "Error: Unknown template '$TEMPLATE'"
exit 1
;;
esac
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" "nvim" C-m
sleep 0.5 # Brief delay to ensure nvim loads
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" " e"
WINDOW_INDEX=$((WINDOW_INDEX + 1))
fi
# Create AI window if enabled
if [ "$AI_ENABLED" = "true" ]; then
tmux new-window -t "$SESSION_NAME:$WINDOW_INDEX" -n "${WINDOW_NAME}-ai" -c "$WINDOW_PATH"
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" "claude -c" C-m
tmux split-window -t "$SESSION_NAME:$WINDOW_INDEX" -h -c "$WINDOW_PATH"
tmux split-window -t "$SESSION_NAME:$WINDOW_INDEX.2" -v -c "$WINDOW_PATH"
tmux select-pane -t "$SESSION_NAME:$WINDOW_INDEX.1"
WINDOW_INDEX=$((WINDOW_INDEX + 1))
fi
# Create git window if enabled
if [ "$GIT_ENABLED" = "true" ]; then
tmux new-window -t "$SESSION_NAME:$WINDOW_INDEX" -n "${WINDOW_NAME}-git" -c "$WINDOW_PATH"
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" "lazygit" C-m
tmux setw -t "$SESSION_NAME:$WINDOW_INDEX" monitor-activity off
WINDOW_INDEX=$((WINDOW_INDEX + 1))
fi
# Create shell window if enabled
if [ "$SHELL_ENABLED" = "true" ]; then
tmux new-window -t "$SESSION_NAME:$WINDOW_INDEX" -n "${WINDOW_NAME}-shell" -c "$WINDOW_PATH"
WINDOW_INDEX=$((WINDOW_INDEX + 1))
fi
# Create remote window if configured
if [ -n "$REMOTE_CONFIG" ] && [ "$REMOTE_CONFIG" != "null" ]; then
SERVER=$(echo "$REMOTE_CONFIG" | jq -r '.server // empty')
REMOTE_DIR=$(echo "$REMOTE_CONFIG" | jq -r '.remoteDir // empty')
if [ -n "$SERVER" ] && [ -n "$REMOTE_DIR" ]; then
# Ensure remote directory exists
printf "\033[2mEnsuring remote directory exists: %s:%s\033[0m\n" "$SERVER" "$REMOTE_DIR"
if ssh "$SERVER" "mkdir -p \"$REMOTE_DIR\"" 2>/dev/null; then
printf "\033[2mRemote directory ready: %s:%s\033[0m\n" "$SERVER" "$REMOTE_DIR"
else
echo "Warning: Could not create or verify remote directory: $SERVER:$REMOTE_DIR"
echo "Please check SSH connection and permissions."
fi
tmux new-window -t "$SESSION_NAME:$WINDOW_INDEX" -n "${WINDOW_NAME}-remote" -c "$WINDOW_PATH"
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" "alias r='ssh $SERVER -t \"cd $REMOTE_DIR && exec \\\$SHELL\"'" C-m
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX" "ssh $SERVER -t 'cd $REMOTE_DIR && exec \$SHELL'" C-m
tmux split-window -t "$SESSION_NAME:$WINDOW_INDEX" -h -c "$WINDOW_PATH"
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX.2" "alias r='ssh $SERVER -t \"cd $REMOTE_DIR && exec \\\$SHELL\"'" C-m
tmux send-keys -t "$SESSION_NAME:$WINDOW_INDEX.2" "ssh $SERVER -t 'cd $REMOTE_DIR && exec \$SHELL'" C-m
tmux select-pane -t "$SESSION_NAME:$WINDOW_INDEX.1"
WINDOW_INDEX=$((WINDOW_INDEX + 1))
fi
fi
done <<< "$WINDOWS"
# Select the first window
tmux select-window -t "$SESSION_NAME:1"
# Attach to session
tmux attach-session -t "$SESSION_NAME"