# ============================================================================ # Tmuxinator Workspace Management # ============================================================================ # Tmux workspace management with per-pane commands, environment variables, # and complex layouts via tmuxinator. # # Features: # - Project scaffolding with sensible defaults # - Multiple built-in templates (dev, ops, web, data, minimal) # - Fuzzy search for projects # # Requirements: # - tmuxinator (gem install tmuxinator or pacman -S tmuxinator) # - tmux # ============================================================================ source "${0:A:h}/../lib/bootstrap.zsh" 2>/dev/null || \ source "$HOME/.dotfiles/zsh/lib/bootstrap.zsh" 2>/dev/null # ============================================================================ # Configuration # ============================================================================ typeset -g TMUXINATOR_CONFIG_DIR="${TMUXINATOR_CONFIG_DIR:-$HOME/.config/tmuxinator}" typeset -g TMUXINATOR_ENABLED="${TMUXINATOR_ENABLED:-auto}" # auto, true, false # ============================================================================ # Detection & Initialization # ============================================================================ _txi_check() { [[ "$TMUXINATOR_ENABLED" == "false" ]] && return 1 df_require_cmd tmuxinator "tmuxinator (gem install tmuxinator)" 2>/dev/null || return 1 return 0 } _txi_init() { df_ensure_dir "$TMUXINATOR_CONFIG_DIR" } _txi_project_exists() { local name="$1" [[ -f "$TMUXINATOR_CONFIG_DIR/${name}.yml" ]] } # ============================================================================ # Project Management # ============================================================================ # Create a new tmuxinator project # Usage: txi-new [template] txi-new() { local name="$1" local template="${2:-dev}" [[ -z "$name" ]] && { echo "Usage: txi-new [template]"; return 1; } _txi_check || return 1 _txi_init if _txi_project_exists "$name"; then df_print_warning "Project '$name' already exists" df_confirm "Overwrite?" || return 1 fi df_print_func_name "New Tmuxinator Project: ${name}" local project_file="$TMUXINATOR_CONFIG_DIR/${name}.yml" case "$template" in dev) _txi_template_dev "$name" > "$project_file" ;; ops) _txi_template_ops "$name" > "$project_file" ;; web) _txi_template_web "$name" > "$project_file" ;; data) _txi_template_data "$name" > "$project_file" ;; minimal) _txi_template_minimal "$name" > "$project_file" ;; *) df_print_warning "Unknown template: $template" df_print_info "Available: dev, ops, web, data, minimal" _txi_template_dev "$name" > "$project_file" ;; esac df_print_success "Created: $project_file" df_print_info "Edit with: txi-edit $name" df_print_info "Start with: txi $name" } # Edit a tmuxinator project # Usage: txi-edit txi-edit() { local name="$1" [[ -z "$name" ]] && { txi-list; return 1; } _txi_check || return 1 local project_file="$TMUXINATOR_CONFIG_DIR/${name}.yml" if [[ ! -f "$project_file" ]]; then df_print_error "Project not found: $name" df_confirm "Create it?" && txi-new "$name" || return 1 fi ${EDITOR:-vim} "$project_file" } # List tmuxinator projects txi-list() { _txi_check || return 1 _txi_init df_print_func_name "Tmuxinator Projects" local found=false for project in "$TMUXINATOR_CONFIG_DIR"/*.yml(N); do [[ -f "$project" ]] || continue found=true local name=$(basename "$project" .yml) local root=$(grep -m1 "^root:" "$project" 2>/dev/null | sed 's/root:[[:space:]]*//') df_print_indent "● $name" [[ -n "$root" && "$root" != "~" ]] && df_print_indent " └─ $root" done [[ "$found" != true ]] && df_print_info "No projects. Create with: txi-new " } # Delete a tmuxinator project # Usage: txi-delete txi-delete() { local name="$1" [[ -z "$name" ]] && { echo "Usage: txi-delete "; return 1; } _txi_check || return 1 local project_file="$TMUXINATOR_CONFIG_DIR/${name}.yml" if [[ ! -f "$project_file" ]]; then df_print_error "Project not found: $name" return 1 fi df_confirm "Delete project '$name'?" || return 1 rm "$project_file" df_print_success "Deleted: $name" } # Start/attach to a tmuxinator project # Usage: txi txi() { local name="$1" [[ -z "$name" ]] && { txi-list; return 1; } _txi_check || return 1 if ! _txi_project_exists "$name"; then df_print_error "Project not found: $name" df_print_info "Create with: txi-new $name" return 1 fi # Check if session already exists if tmux has-session -t "$name" 2>/dev/null; then df_print_info "Attaching to existing session: $name" if [[ -z "$TMUX" ]]; then tmux attach -t "$name" else tmux switch-client -t "$name" fi else df_print_step "Starting project: $name" tmuxinator start "$name" fi } # Stop a tmuxinator session # Usage: txi-stop txi-stop() { local name="$1" [[ -z "$name" ]] && { echo "Usage: txi-stop "; return 1; } _txi_check || return 1 tmuxinator stop "$name" 2>/dev/null && df_print_success "Stopped: $name" || df_print_error "Session not running: $name" } # Fuzzy search and start project txif() { _txi_check || return 1 df_require_cmd fzf || return 1 _txi_init local projects=() for project in "$TMUXINATOR_CONFIG_DIR"/*.yml(N); do [[ -f "$project" ]] && projects+=("$(basename "$project" .yml)") done [[ ${#projects[@]} -eq 0 ]] && { df_print_info "No projects"; return 1; } local sel=$(printf '%s\n' "${projects[@]}" | fzf $(df_fzf_opts) --prompt='Tmuxinator > ') [[ -n "$sel" ]] && txi "$sel" } # ============================================================================ # Template Generators # ============================================================================ _txi_template_dev() { local name="$1" cat << EOF # ${name} - Development Workspace name: ${name} root: ~/projects/${name} # Optional: pre-commands before windows are created # pre_window: nvm use default windows: - editor: layout: main-vertical panes: - # Editor pane - opens vim/nvim - # Terminal pane - server: panes: - # Server/dev server pane - logs: panes: - # Log watching pane - # Additional monitoring EOF } _txi_template_ops() { local name="$1" cat << EOF # ${name} - Operations/Monitoring Workspace name: ${name} root: ~ windows: - monitoring: layout: tiled panes: - htop - # System logs - # Network monitoring - # Disk usage - services: layout: even-horizontal panes: - # Service management - # Container management - ssh: layout: tiled panes: - # SSH session 1 - # SSH session 2 - # SSH session 3 - # SSH session 4 EOF } _txi_template_web() { local name="$1" cat << EOF # ${name} - Web Development Workspace name: ${name} root: ~/projects/${name} # Uncomment and adjust for your stack # pre_window: nvm use 18 windows: - editor: layout: main-vertical panes: - # \${EDITOR:-vim} . - # Terminal - server: panes: - # npm run dev # or: python manage.py runserver - frontend: layout: even-horizontal panes: - # npm run watch - # Browser sync / tailwind watch - database: panes: - # Database client or psql/mysql - git: panes: - # Git operations EOF } _txi_template_data() { local name="$1" cat << EOF # ${name} - Data Science Workspace name: ${name} root: ~/projects/${name} # Uncomment to activate conda/venv # pre_window: source venv/bin/activate windows: - jupyter: panes: - # jupyter lab - code: layout: main-vertical panes: - # Editor - # Python REPL: python or ipython - data: panes: - # Data exploration / file management - terminal: panes: - # General terminal EOF } _txi_template_minimal() { local name="$1" cat << EOF # ${name} - Minimal Workspace name: ${name} root: ~ windows: - main: panes: - # Main pane EOF } # ============================================================================ # Available Templates # ============================================================================ txi-templates() { df_print_func_name "Tmuxinator Templates" echo "" df_print_indent "dev Development (editor + terminal + server + logs)" df_print_indent "ops Operations (monitoring + services + SSH grid)" df_print_indent "web Web development (editor + server + frontend + db)" df_print_indent "data Data science (jupyter + code + data + terminal)" df_print_indent "minimal Single window, single pane" echo "" df_print_info "Usage: txi-new myproject dev" } # ============================================================================ # Help # ============================================================================ txi-help() { df_print_func_name "Tmuxinator Commands" cat << 'EOF' Project Management: txi Start/attach to project txi-new [tmpl] Create new project (templates: dev, ops, web, data, minimal) txi-edit Edit project configuration txi-list List all projects txi-delete Delete project txi-stop Stop running session txif Fuzzy search and start Templates: txi-templates Show available templates Configuration: Projects stored in: ~/.config/tmuxinator/ EOF } # ============================================================================ # Aliases # ============================================================================ alias txil='txi-list' alias txin='txi-new' alias txie='txi-edit' alias txid='txi-delete' alias txis='txi-stop' alias txit='txi-templates' alias txih='txi-help' # ============================================================================ # Initialize # ============================================================================ _txi_init