{ config, pkgs, lib, ... }: let cfg = config.dot.tmux; projectSelector = pkgs.writeScriptBin "projectSelector" '' #!${pkgs.zsh}/bin/zsh # Configuration PRO_BASE_DIR="$HOME/pro" PRO_BLACKLIST=("lost+found" ".git" "node_modules") # 1. Build the list of projects list="misc" if [[ -d "$PRO_BASE_DIR" ]]; then for dir in "$PRO_BASE_DIR"/*(/N); do name=$(basename "$dir") # Check against blacklist if [[ ! ''${PRO_BLACKLIST[(r)''${name}]} == ''${name} ]]; then list+="\n$name" fi done fi # 2. Open fzf (Multi-select: Tab to mark, Enter to confirm) selected=$(echo -e "$list" | ${pkgs.fzf}/bin/fzf -m --header="Select projects" --reverse) [[ -z "$selected" ]] && exit 0 # 3. Process selections # Convert newline-separated string to array selected_array=("''${(@f)selected}") total=''${#selected_array[@]} i=0 for arg in "''${selected_array[@]}"; do ((i++)) target="" s_name="" if [[ "$arg" == "misc" ]]; then target="$HOME" s_name="misc" else target="$PRO_BASE_DIR/$arg" s_name=$(basename "$target" | tr '.' '_') fi # Background load all but the last selection if [[ $i -lt $total ]]; then if [[ -f "$target/.tmuxp.yaml" || -f "$target/.tmuxp.yml" ]]; then ${pkgs.tmuxp}/bin/tmuxp load --yes -d "$target" else if ! ${pkgs.tmux}/bin/tmux has-session -t "$s_name" 2>/dev/null; then ${pkgs.tmux}/bin/tmux new-session -d -s "$s_name" -c "$target" fi fi else # Last item: Foreground switch/attach if [[ -f "$target/.tmuxp.yaml" || -f "$target/.tmuxp.yml" ]]; then ${pkgs.tmuxp}/bin/tmuxp load --yes "$target" else if ! ${pkgs.tmux}/bin/tmux has-session -t "$s_name" 2>/dev/null; then ${pkgs.tmux}/bin/tmux new-session -d -s "$s_name" -c "$target" fi if [[ -n "$TMUX" ]]; then ${pkgs.tmux}/bin/tmux switch-client -t "$s_name" else ${pkgs.tmux}/bin/tmux attach-session -t "$s_name" fi fi fi done ''; in { options.dot.tmux = { workMode = lib.mkEnableOption "work-specific tmux configuration"; }; config = { programs.tmux = { enable = true; shortcut = "a"; mouse = true; keyMode = "vi"; escapeTime = 10; terminal = "screen-256color"; tmuxp.enable = true; extraConfig = '' set -g display-time 1500 unbind S bind S command-prompt "switch -t %1" bind-key , command-prompt -p "rename-window:" "rename-window '%%'" # Check if we are in vim is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" bind-key -n C-M-h if-shell "$is_vim" { send-keys C-M-h } { if -F "#{pane_at_left}" "previous-window" "select-pane -L" } bind-key -n C-M-j if-shell "$is_vim" { send-keys C-M-j } { if -F "#{pane_at_bottom}" "switch-client -n" "select-pane -D" } bind-key -n C-M-k if-shell "$is_vim" { send-keys C-M-k } { if -F "#{pane_at_top}" "switch-client -p" "select-pane -U" } bind-key -n C-M-l if-shell "$is_vim" { send-keys C-M-l } { if -F "#{pane_at_right}" "next-window" "select-pane -R" } bind '"' split-window -c "#{pane_current_path}" bind % split-window -h -c "#{pane_current_path}" bind c new-window -a -c "#{pane_current_path}" bind C-g display-popup -E -d "#{pane_current_path}" -xC -yC -w 95% -h 95% "lazygit" bind C-t display-popup -E -xC -yC -w 95% -h 95% "tasksquire" ${lib.optionalString cfg.workMode '' bind C-s display-popup -E "projectSelector" bind C-n display-popup -E -xC -yC -w 95% -h 95% -d "/mnt/c/Users/marti/Documents/notes/Work/" "vim quick_notes.md" bind C-p display-popup -E -xC -yC -w 95% -h 95% -d "/mnt/c/Users/marti/Documents/notes/Work/development/" "vim mbpr.md" ''} ####################################### # status line ####################################### set -g status-justify centre set -g status-left "#[bg=#808080,fg=#ffffff,bold] #S #[default]#[bg=#BCBCBC] #{-30:pane_title} " set -g status-left-length 40 set -g status-right "#[bg=#BCBCBC] %H:%M #[bg=#808080,fg=#ffffff] %d.%m.%y " # setw -g window-status-format " #W#F " # setw -g window-status-current-format " #W#F " setw -g window-status-format " #W " setw -g window-status-current-format " #W " setw -g window-status-separator "" ####################################### # colors, taken from vim-lucius ####################################### set -g status-style "bg=#DADADA,fg=#000000" setw -g window-status-style "bg=#BCBCBC,fg=#000000" setw -g window-status-current-style "bg=#808080,fg=#ffffff" setw -g window-status-activity-style "bg=#AFD7AF,fg=#000000" setw -g window-status-bell-style "bg=#AFD7AF,fg=#000000" #setw -g window-status-content-style "bg=#AFD7AF,fg=#000000" set -g pane-active-border-style "bg=#eeeeee,fg=#006699" set -g pane-border-style "bg=#eeeeee,fg=#999999" ''; }; programs.zsh.initExtra = lib.optionalString cfg.workMode '' # --- 1. Configuration --- export PRO_BASE_DIR="$HOME/pro" export PRO_BLACKLIST=("lost+found") # --- 2. The 'pro' function --- pro() { local total_args=$# local i=0 for arg in "$@"; do ((i++)) local target="" local s_name="" # Resolve the target directory and session name if [[ "$arg" == "misc" ]]; then target="$HOME" s_name="misc" elif [[ -d "$PRO_BASE_DIR/$arg" ]]; then target="$PRO_BASE_DIR/$arg" s_name=$(basename "$target" | tr '.' '_') elif [[ -d "$HOME/$arg" ]]; then target="$HOME/$arg" s_name=$(basename "$target" | tr '.' '_') else echo "Error: Project '$arg' not found in $PRO_BASE_DIR or $HOME" continue fi target=$(realpath "$target") # logic: If this is NOT the last argument, load it in the background. # If it IS the last argument, load/attach to it in the foreground. if [[ "$i" -lt "$total_args" ]]; then # BACKGROUND LOADING if [[ -f "$target/.tmuxp.yaml" || -f "$target/.tmuxp.yml" ]]; then tmuxp load --yes -d "$target" else if ! tmux has-session -t "$s_name" 2>/dev/null; then tmux new-session -d -s "$s_name" -c "$target" fi fi else # FOREGROUND ATTACHING (The "Winner") if [[ -f "$target/.tmuxp.yaml" || -f "$target/.tmuxp.yml" ]]; then # tmuxp load handles switching/attaching automatically tmuxp load --yes "$target" else if ! tmux has-session -t "$s_name" 2>/dev/null; then tmux new-session -d -s "$s_name" -c "$target" fi if [[ -n "$TMUX" ]]; then tmux switch-client -t "$s_name" else tmux attach-session -t "$s_name" fi fi fi done } # --- 3. Tab Completion --- _pro_completion() { local -a projects # Manually add the 'misc' alias to completion projects+=("misc") # Add directories from ~/pro/ if [[ -d "$PRO_BASE_DIR" ]]; then for dir in "$PRO_BASE_DIR"/*(/N); do local name=$(basename "$dir") # Nix escape for array check: if name not in blacklist if [[ ! ''${PRO_BLACKLIST[(r)''${name}]} == ''${name} ]]; then projects+=("''${name}") fi done fi _describe 'projects' projects } compdef _pro_completion pro ''; home.packages = lib.optional cfg.workMode projectSelector; home.shellAliases = { "o" = "tmuxp"; "ol" = "tmuxp load"; }; }; }