246 lines
8.2 KiB
Nix
246 lines
8.2 KiB
Nix
{ 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";
|
|
};
|
|
};
|
|
}
|