diff --git a/common/.config/zsh/modules/tmux-project-manager.zsh b/common/.config/zsh/modules/tmux-project-manager.zsh index 5c9d73f..23f2112 100644 --- a/common/.config/zsh/modules/tmux-project-manager.zsh +++ b/common/.config/zsh/modules/tmux-project-manager.zsh @@ -1 +1 @@ -alias tpm="tmux-project-manager" +alias tpm="project-manager" diff --git a/lib/project_manager/core.sh b/lib/project_manager/core.sh new file mode 100755 index 0000000..58283f0 --- /dev/null +++ b/lib/project_manager/core.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +get_current_session() { + if [ -n "${TMUX:-}" ]; then + tmux display-message -p "#S" 2>/dev/null || true + fi +} + +validate_session_name() { + local name="$1" + if [[ -z "$name" || "$name" == */* || "$name" == .* ]]; then + printf 'Invalid session name: %s\n' "$name" >&2 + return 1 + fi + return 0 +} + +session_exists() { + local session="$1" + tmux has-session -t "$session" 2>/dev/null +} + +connect_session() { + local session="$1" + if [ -n "${TMUX:-}" ]; then + tmux switch-client -t "$session" + else + tmux attach-session -t "$session" + fi +} + +create_session() { + local session="$1" + local dir="$2" + + mkdir -p "$dir" || return 1 + + if [ -n "${TMUX:-}" ]; then + tmux new-session -d -s "$session" -c "$dir" || return 1 + tmux switch-client -t "$session" + else + tmux new-session -s "$session" -c "$dir" + fi +} diff --git a/lib/project_manager/restore.sh b/lib/project_manager/restore.sh new file mode 100755 index 0000000..566ad06 --- /dev/null +++ b/lib/project_manager/restore.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +ensure_session_restored() { + if tmux list-sessions >/dev/null 2>&1; then + return 0 + fi + + local resurrect_dir="${XDG_DATA_HOME:-$HOME/.local/share}/tmux/resurrect" + [[ ! -d "$resurrect_dir" ]] && resurrect_dir="$HOME/.tmux/resurrect" + local last_resurrect="$resurrect_dir/last" + + if [[ -e "$last_resurrect" || -L "$last_resurrect" ]]; then + local restore_script="$HOME/.tmux/plugins/tmux-resurrect/scripts/restore.sh" + + if [[ -f "$restore_script" ]]; then + printf "\e[33m⚡ Restoring tmux sessions...\e[0m\r" + + tmux new-session -d -s "__resurrect_temp__" 2>/dev/null || true + + tmux run-shell "$restore_script" >/dev/null 2>&1 || true + + local count=0 + while [ $count -lt 25 ]; do + local total_sessions + total_sessions=$(tmux list-sessions -F '#S' 2>/dev/null | grep -v '^__resurrect_temp__$' | wc -l) + if [ "$total_sessions" -gt 0 ]; then + break + fi + sleep 0.1 + ((count++)) + done + + tmux kill-session -t "__resurrect_temp__" 2>/dev/null || true + + printf "%*s\r" 40 "" + fi + fi +} + diff --git a/lib/project_manager/ui.sh b/lib/project_manager/ui.sh new file mode 100755 index 0000000..5388da1 --- /dev/null +++ b/lib/project_manager/ui.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +select_project_fzf() { + local current_session="$1" + local list_helper="$2" + local preview_script="$3" + + "$list_helper" "$current_session" | + fzf \ + --prompt="Project> " \ + --print-query \ + --no-multi \ + --height=100% \ + --layout=reverse \ + --border \ + --preview="$preview_script {}" \ + --preview-window='right:65%:wrap' \ + --bind="ctrl-d:execute-silent(tmux kill-session -t '{}')+reload($list_helper '$current_session')" \ + --header='CTRL-D: Delete | ENTER: Attach/Switch' +} diff --git a/packages/arch.txt b/packages/arch.txt index 8d70210..116eacc 100644 --- a/packages/arch.txt +++ b/packages/arch.txt @@ -36,3 +36,5 @@ shellcheck yamllint lua-language-server stylua + +inetutils diff --git a/packages/debian.txt b/packages/debian.txt index 98c1f93..1155593 100644 --- a/packages/debian.txt +++ b/packages/debian.txt @@ -36,3 +36,4 @@ shellcheck yamllint lua-language-server +hostname diff --git a/scripts/project-manager b/scripts/project-manager new file mode 100755 index 0000000..4892727 --- /dev/null +++ b/scripts/project-manager @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -euo pipefail + +#------------------------------------- +# Base Directories & Library Loader +#------------------------------------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DOTFILES_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +LIB_DIR="$DOTFILES_DIR/lib/project_manager" +PREVIEW_SCRIPT="$SCRIPT_DIR/tmux-session-preview" + +# Load modules +source "$LIB_DIR/core.sh" +source "$LIB_DIR/restore.sh" +source "$LIB_DIR/ui.sh" + +#------------------------------------- +# Configuration +#------------------------------------- +PROJECT_DIR="${PROJECT_DIR:-$HOME/w}" +SESSION_LIST_HELPER="$SCRIPT_DIR/tmux-session-list" + +#------------------------------------- +# Main Application Entypoint +#------------------------------------- +main() { + mkdir -p "$PROJECT_DIR" + + ensure_session_restored + + local current_session + current_session="$(get_current_session)" + + local input + input="$(select_project_fzf "$current_session" "$SESSION_LIST_HELPER" "$PREVIEW_SCRIPT")" || true + + [ -z "$input" ] && return 0 + + local query selected name + query="$(printf '%s\n' "$input" | sed -n '1p')" + selected="$(printf '%s\n' "$input" | sed -n '2p')" + name="${selected:-$query}" + + [ -z "$name" ] && return 1 + validate_session_name "$name" || return 1 + + local session="$name" + local dir="$PROJECT_DIR/$name" + + if session_exists "$session" ;then + connect_session "$session" + else + create_session "$session" "$dir" + fi +} + +main diff --git a/scripts/tmux-project-manager b/scripts/tmux-project-manager deleted file mode 100755 index 76f8e58..0000000 --- a/scripts/tmux-project-manager +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env bash - -list_sessions() { - local current_session="${1:-}" - - tmux list-sessions -F '#S' 2>/dev/null | - sort -u | - grep -vxF "$current_session" -} - -tproj() { - local projects_dir="/home/mohos/w" - local current_session="" - local input - local query - local selected - local name - local dir - local session - - mkdir -p "$projects_dir" - - if [ -n "${TMUX:-}" ]; then - current_session=$(tmux display-message -p '#S') - fi - - input=$( - list_sessions "$current_session" | - fzf \ - --prompt='Project> ' \ - --print-query \ - --no-multi \ - --height=100% \ - --layout=reverse \ - --border \ - --preview=' - session="{}" - - printf "\033[1;36mSession:\033[0m %s\n\n" "$session" - - tmux display-message \ - -p \ - -t "${session}:0.0" \ - "Path: #{pane_current_path}" 2>/dev/null - - printf "\n\033[1;36mWindows:\033[0m\n" - - tmux list-windows \ - -t "$session" \ - -F " #{window_index}: #{window_name}" 2>/dev/null - - printf "\n\033[1;36mPane output:\033[0m\n" - - tmux capture-pane \ - -p \ - -e \ - -t "${session}:0.0" \ - -S -80 2>/dev/null - ' \ - --preview-window='right:40%:wrap' \ - --bind="ctrl-d:execute-silent(tmux kill-session -t '{}')+reload(/home/mohos/.dotfiles/scripts/tmux-session-list '$current_session')" \ - --header='CTRL-D: Delete | ENTER: Attach/Switch' - -) || true - - [ -z "$input" ] && return 0 - - query=$(printf '%s\n' "$input" | sed -n '1p') - selected=$(printf '%s\n' "$input" | sed -n '2p') - - name="${selected:-$query}" - - [ -z "$name" ] && return 1 - - if [[ "$name" == */* || "$name" == .* ]]; then - printf 'Invalid session name: %s\n' "$name" >&2 - return 1 - fi - - session="$name" - dir="$projects_dir/$name" - - if tmux has-session -t "$session" 2>/dev/null; then - if [ -n "${TMUX:-}" ]; then - tmux switch-client -t "$session" - else - tmux attach-session -t "$session" - fi - - return 0 - fi - - mkdir -p "$dir" || return 1 - - if [ -n "${TMUX:-}" ]; then - tmux new-session -d -s "$session" -c "$dir" || return 1 - tmux switch-client -t "$session" - else - tmux new-session -s "$session" -c "$dir" - fi -} - -tproj diff --git a/scripts/tmux-session-list b/scripts/tmux-session-list index 100348a..12e1da7 100755 --- a/scripts/tmux-session-list +++ b/scripts/tmux-session-list @@ -1,5 +1,9 @@ #!/usr/bin/env bash -current="$1" -tmux list-sessions -F '#S' 2>/dev/null | grep -vxF "$current" +set -euo pipefail + +current="${1:-}" +tmux list-sessions -F '#S' 2>/dev/null | + sort -u | + grep -vxF "$current" || true diff --git a/scripts/tmux-session-preview b/scripts/tmux-session-preview new file mode 100755 index 0000000..b2b568b --- /dev/null +++ b/scripts/tmux-session-preview @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -u + +session="${1:-}" + +if [[ -z "$session" ]] || ! tmux has-session -t "$session" 2>/dev/null; then + printf '\033[2mSession is no loger available.\033[0m\n' + exit 0 +fi + +printf '\033[1;36mSession:\033[0m %s\n\n' "$session" + + +printf '\033[1;36mPath:\033[0m' +tmux display-message \ + -p \ + -t "${session}:" \ + '#{pane_current_path}' 2>/dev/null || true + +printf '\033[1;36mWindows:\033[0m\n' +tmux list-windows \ + -t "$session" \ + -F ' #{window_index}: #{window_name} #{?window_active,(active),}' \ + 2>/dev/null || ture + +printf '\033[1;36mPane Output:\033[0m' +tmux capture-pane \ + -p \ + -e \ + -t "${session}:" \ + -S -30 \ + 2>/dev/null || true +