From 5e6fbc9ebaf814635b8db9e103fa0b816c5817d9 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 2 May 2025 16:47:35 +0200 Subject: [PATCH] feat(home-manager): add tmux sessions with script --- modules/home-manager/cli/tmux/default.nix | 19 ++- .../cli/tmux/files/create-tmux-session.sh | 147 ++++++++++++++++++ 2 files changed, 163 insertions(+), 3 deletions(-) create mode 100755 modules/home-manager/cli/tmux/files/create-tmux-session.sh diff --git a/modules/home-manager/cli/tmux/default.nix b/modules/home-manager/cli/tmux/default.nix index c837e3e..a1c329a 100644 --- a/modules/home-manager/cli/tmux/default.nix +++ b/modules/home-manager/cli/tmux/default.nix @@ -7,8 +7,17 @@ in { options.modules.cli.tmux = { enable = mkEnableOption "enable Tmux"; + extraConfig = mkOption { + type = types.lines; + default = ''''; + description = '' + user related Tmux options, wee be concatenated with options defined + in the module. + ''; + }; }; config = mkIf cfg.enable { + home.file.".local/bin/create-tmux-session".source = ./files/create-tmux-session.sh; programs.tmux = { enable = true; aggressiveResize = true; @@ -21,6 +30,8 @@ in prefix = "C-a"; terminal = "tmux-256color"; extraConfig = '' + set -g detach-on-destroy off + set -g display-time 1500 bind -n -N "Select pane to the left of the active pane" M-h select-pane -L bind -n -N "Select pane below the active pane" M-j select-pane -D @@ -31,8 +42,10 @@ in bind -n -r -N "Resize the pane down by 5" M-J resize-pane -D 5 bind -n -r -N "Resize the pane up by 5" M-K resize-pane -U 5 bind -n -r -N "Resize the pane right by 5" M-L resize-pane -R 5 - bind -n -n M-n split-window -h -c "#{pane_current_path}" - bind -n -n M-N split-window -v -c "#{pane_current_path}" + bind -n M-n split-window -h -c "#{pane_current_path}" + bind -n M-N split-window -v -c "#{pane_current_path}" + + bind -n M-0 run 'create-tmux-session -s config -p nix "run:nvim ." vsplit' # Theme set -g status-interval 2 @@ -58,7 +71,7 @@ in set -g status-left-length 100 set -g status-left '#[bg=colour0, fg=colour6]  #S ' set -g status-right ' ' - ''; + '' + cfg.extraConfig; plugins = with pkgs; [ tmuxPlugins.tmux-fzf ]; diff --git a/modules/home-manager/cli/tmux/files/create-tmux-session.sh b/modules/home-manager/cli/tmux/files/create-tmux-session.sh new file mode 100755 index 0000000..3184124 --- /dev/null +++ b/modules/home-manager/cli/tmux/files/create-tmux-session.sh @@ -0,0 +1,147 @@ +#!/usr/bin/env bash +set -e +set -o pipefail + +DEBUG=0 +declare -a COMMANDS + +error() { + local message + printf -v message "\e[31mERROR:\e[0m %s\n" "$1" + >&2 printf "%b" "${message}" +} + +debug() { + local message + if [[ $DEBUG -eq 1 ]]; then + printf -v message "\e[3;34mDEBUG:\e[0m %s\n" "$*" + >&2 printf "%b" "$message" + fi +} + +process_args() { + until [[ -z $1 ]]; do + case $1 in + -s | --session-name | --session) + SESSION="$2" + shift + ;; + -p | --project-name | --window) + PROJECT="$2" + shift + ;; + -d | --debug) + DEBUG=1 + ;; + *) + COMMANDS+=("$1") + ;; + esac + shift + done +} + +has_session() { + local session_name="${1}" + tmux has-session -t "${session_name}" 2>/dev/null +} + +get_project_path() { + local identifier="${1}" + debug "get project path with identifier '$identifier'" + if [[ -z "$identifier" ]]; then + CURRENT_PATH=$(ghq list -p | fzf) + else + CURRENT_PATH=$(ghq list -p -e "$identifier") + fi +} + +is_running_in_tmux() { + debug "check if running in tmux" + if [[ -z $TMUX ]]; then + error "This script should run in a running instance of Tmux" + exit 10 + fi +} + +check_script_inputs() { + debug "check script inputs" + if [[ -z "$SESSION" ]]; then + error "You must provide a session name" + exit 5 + fi +} + +process_commands() { + local input="$1" + debug "Process command '$input'" + local cmd arg + if [[ "$input" =~ ^.*:.*$ ]]; then + debug "command and parameter found" + arg=${input##*:} + cmd=${input%%:*} + else + debug "command found without parameter" + cmd="$input" + fi + if ! "tmux_${cmd}" "${arg}"; then + error "Command \`$cmd\` not exist" + fi +} + +tmux_vsplit() { + local size="${1:-20}" + debug "execute vsplit with size '${size}'" + tmux split-window -t "$SESSION" -c "$CURRENT_PATH" -v -p "$size" +} + +tmux_hsplit() { + local size="${1:-20}" + debug "execute hsplit with size '${size}'" + tmux split-window -t "$SESSION" -c "$CURRENT_PATH" -h -p "$size" +} + +tmux_neww() { + local name="$1" + debug "execute neww with name '${name}'" + local command=(tmux new-window -t "$SESSION" -c "$CURRENT_PATH") + if [[ -n "$name" ]]; then + command+=(-n "$name") + fi + "${command[@]}" +} + +tmux_run() { + local shell_command="$1" + debug "execute run with command '${shell_command}'" + if [[ -z "$shell_command" ]]; then + error "tmux-run need a command" + else + tmux send-keys -t "$SESSION" "$shell_command" "C-m" + fi +} + +project() { + local arg="$1" + debug "execute project with arg '${arg}'" + get_project_path "$arg" +} + +main() { + process_args "$@" + is_running_in_tmux + check_script_inputs + if ! has_session "$SESSION"; then + get_project_path "${PROJECT:-$SESSION}" + tmux new-session -ds "${SESSION}" -c "${CURRENT_PATH}" -n "${PROJECT}" + + # Process commands passed with command line + for command in "${COMMANDS[@]}"; do + process_commands "$command" + done + fi + + tmux switch-client -t "${SESSION}" +} + +main "${@}"