From 15623b0ff3506d2b43441a97126f56eb838f64f6 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:37:45 +0330 Subject: [PATCH 1/7] chore(zsh): Chenge alias project manager after chenging name 'tmux project manager' to 'project manager' should chenging alias until work command in zsh Ref: #14 --- common/.config/zsh/modules/tmux-project-manager.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" From 16b4f3164ba93936961aa98262c7d4a6e3ee6604 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:39:05 +0330 Subject: [PATCH 2/7] feat(pm): core tmux managment in project manager This file collection of tmux managment command. Ref: #14 --- lib/project_manager/core.sh | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 lib/project_manager/core.sh 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 +} From 621cd94910ffbe7ecaced0f6e4d03a0c148f5a5d Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:40:03 +0330 Subject: [PATCH 3/7] feat(pm): restor tmux session module Management and handel restor session tmux in start tmux server. Ref: #14 --- lib/project_manager/restore.sh | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100755 lib/project_manager/restore.sh 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 +} + From c52a09c5b75db17bed751799dc9baa67f09a8b83 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:41:04 +0330 Subject: [PATCH 4/7] feat(pm): ui project mangement Handel UI/UX for working with project manager. Ref: #14 --- lib/project_manager/ui.sh | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100755 lib/project_manager/ui.sh diff --git a/lib/project_manager/ui.sh b/lib/project_manager/ui.sh new file mode 100755 index 0000000..593fcdd --- /dev/null +++ b/lib/project_manager/ui.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +generate_preview_cmd() { + cat << 'EOF' +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 + +EOF +} + +select_project_fzf() { + local current_session="$1" + local list_helper="$2" + local preview_cmd + preview_cmd="$(generate_preview_cmd)" + + "$list_helper" "$current_session" | + fzf \ + --prompt="Project> " \ + --print-query \ + --no-multi \ + --height=100% \ + --layout=reverse \ + --border \ + --preview="$preview_cmd" \ + --preview-window='right:40%:wrap' \ + --bind="ctrl-d:execute-silent(tmux kill-session -t '{}')+reload($list_helper '$current_session')" \ + --header='CTRL-D: Delete | ENTER: Attach/Switch' +} From e73b3836df4e1e1903194cd0a7fc387d1d39b0d7 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:41:53 +0330 Subject: [PATCH 5/7] ci(pm): Add hostname tools for requirement project manager Ref: #14 --- packages/arch.txt | 2 ++ packages/debian.txt | 1 + 2 files changed, 3 insertions(+) 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 From 0f712593bb4a6f696d7b46c34ead84c4cbef6296 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 30 Aug 2026 20:42:36 +0330 Subject: [PATCH 6/7] feat(pm): Entry point file for use project manager Closes: #14 --- scripts/project-manager | 57 +++++++++++++++++++ scripts/tmux-project-manager | 103 ----------------------------------- scripts/tmux-session-list | 8 ++- 3 files changed, 63 insertions(+), 105 deletions(-) create mode 100755 scripts/project-manager delete mode 100755 scripts/tmux-project-manager diff --git a/scripts/project-manager b/scripts/project-manager new file mode 100755 index 0000000..4a0c7f4 --- /dev/null +++ b/scripts/project-manager @@ -0,0 +1,57 @@ +#!/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" + +# 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")" || 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 From eb96b67a7f98cd8a01ef0f9e167c96c09a10ee24 Mon Sep 17 00:00:00 2001 From: mohammad Date: Tue, 1 Sep 2026 15:04:50 +0330 Subject: [PATCH 7/7] bug(tpm): Fixed fzf preview in tpm (project manger) - Delete previw part from ui file in lib folde - Add `tmux-session-preview` script for rendering preview in fzf - Update `project-manger` script for read preview script Ref: #7 --- lib/project_manager/ui.sh | 32 +++----------------------------- scripts/project-manager | 3 ++- scripts/tmux-session-preview | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 30 deletions(-) create mode 100755 scripts/tmux-session-preview diff --git a/lib/project_manager/ui.sh b/lib/project_manager/ui.sh index 593fcdd..5388da1 100755 --- a/lib/project_manager/ui.sh +++ b/lib/project_manager/ui.sh @@ -1,35 +1,9 @@ #!/usr/bin/env bash -generate_preview_cmd() { - cat << 'EOF' -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 - -EOF -} - select_project_fzf() { local current_session="$1" local list_helper="$2" - local preview_cmd - preview_cmd="$(generate_preview_cmd)" + local preview_script="$3" "$list_helper" "$current_session" | fzf \ @@ -39,8 +13,8 @@ select_project_fzf() { --height=100% \ --layout=reverse \ --border \ - --preview="$preview_cmd" \ - --preview-window='right:40%:wrap' \ + --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/scripts/project-manager b/scripts/project-manager index 4a0c7f4..4892727 100755 --- a/scripts/project-manager +++ b/scripts/project-manager @@ -8,6 +8,7 @@ set -euo pipefail 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" @@ -32,7 +33,7 @@ main() { current_session="$(get_current_session)" local input - input="$(select_project_fzf "$current_session" "$SESSION_LIST_HELPER")" || true + input="$(select_project_fzf "$current_session" "$SESSION_LIST_HELPER" "$PREVIEW_SCRIPT")" || true [ -z "$input" ] && return 0 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 +