Skip to main content

git_worktree_manager/
shell_functions.rs

1/// Shell function generation for gw-cd.
2///
3/// Outputs shell-specific function definitions for bash/zsh/fish.
4/// Generate shell function for the specified shell.
5pub fn generate(shell: &str) -> Option<String> {
6    match shell {
7        "bash" | "zsh" => Some(BASH_ZSH_FUNCTION.to_string()),
8        "fish" => Some(FISH_FUNCTION.to_string()),
9        _ => None,
10    }
11}
12
13const BASH_ZSH_FUNCTION: &str = r#"# git-worktree-manager shell functions for bash/zsh
14# Source this file to enable shell functions:
15#   source <(gw _shell-function bash)
16
17# Navigate to a worktree by branch name
18gw-cd() {
19    local branch=""
20    local global_mode=0
21
22    while [ $# -gt 0 ]; do
23        case "$1" in
24            -g|--global) global_mode=1; shift ;;
25            -*) echo "Error: Unknown option '$1'" >&2; echo "Usage: gw-cd [-g|--global] [branch|repo:branch]" >&2; return 1 ;;
26            *) branch="$1"; shift ;;
27        esac
28    done
29
30    if [ $global_mode -eq 0 ] && [[ "$branch" == *:* ]]; then
31        global_mode=1
32    fi
33
34    local worktree_path
35
36    if [ -z "$branch" ]; then
37        if [ $global_mode -eq 1 ]; then
38            worktree_path=$(gw _path -g --interactive)
39        else
40            worktree_path=$(gw _path --interactive)
41        fi
42        if [ $? -ne 0 ]; then return 1; fi
43    elif [ $global_mode -eq 1 ]; then
44        worktree_path=$(gw _path -g "$branch")
45        if [ $? -ne 0 ]; then return 1; fi
46    else
47        worktree_path=$(git worktree list --porcelain 2>/dev/null | awk -v branch="$branch" '
48            /^worktree / { path=$2 }
49            /^branch / && $2 == "refs/heads/"branch { print path; exit }
50        ')
51    fi
52
53    if [ -z "$worktree_path" ]; then
54        echo "Error: No worktree found for branch '$branch'" >&2
55        return 1
56    fi
57
58    if [ -d "$worktree_path" ]; then
59        cd "$worktree_path" || return 1
60        echo "Switched to worktree: $worktree_path"
61    else
62        echo "Error: Worktree directory not found: $worktree_path" >&2
63        return 1
64    fi
65}
66
67_gw_cd_completion() {
68    local cur="${COMP_WORDS[COMP_CWORD]}"
69    local has_global=0
70    COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
71    local i
72    for i in "${COMP_WORDS[@]}"; do
73        case "$i" in -g|--global) has_global=1 ;; esac
74    done
75    if [[ "$cur" == -* ]]; then
76        COMPREPLY=($(compgen -W "-g --global" -- "$cur"))
77        return
78    fi
79    local branches
80    if [ $has_global -eq 1 ]; then
81        branches=$(gw _path --list-branches -g 2>/dev/null)
82    else
83        branches=$(git worktree list --porcelain 2>/dev/null | grep "^branch " | sed 's/^branch refs\/heads\///' | sort -u)
84    fi
85    COMPREPLY=($(compgen -W "$branches" -- "$cur"))
86}
87
88if [ -n "$BASH_VERSION" ]; then
89    complete -F _gw_cd_completion gw-cd
90fi
91
92if [ -n "$ZSH_VERSION" ]; then
93    _gw_cd_zsh() {
94        local has_global=0
95        local i
96        for i in "${words[@]}"; do
97            case "$i" in -g|--global) has_global=1 ;; esac
98        done
99        if [[ "$PREFIX" == -* ]]; then
100            local -a flags
101            flags=('-g:Search all registered repositories' '--global:Search all registered repositories')
102            _describe 'flags' flags
103            return
104        fi
105        local -a branches
106        if [ $has_global -eq 1 ]; then
107            branches=(${(f)"$(gw _path --list-branches -g 2>/dev/null)"})
108        else
109            branches=(${(f)"$(git worktree list --porcelain 2>/dev/null | grep '^branch ' | sed 's/^branch refs\/heads\///' | sort -u)"})
110        fi
111        compadd -a branches
112    }
113    compdef _gw_cd_zsh gw-cd
114fi
115"#;
116
117const FISH_FUNCTION: &str = r#"# git-worktree-manager shell functions for fish
118# Source this file to enable shell functions:
119#   gw _shell-function fish | source
120
121function gw-cd
122    set -l global_mode 0
123    set -l branch ""
124
125    for arg in $argv
126        switch $arg
127            case -g --global
128                set global_mode 1
129            case '-*'
130                echo "Error: Unknown option '$arg'" >&2
131                echo "Usage: gw-cd [-g|--global] [branch|repo:branch]" >&2
132                return 1
133            case '*'
134                set branch $arg
135        end
136    end
137
138    if test $global_mode -eq 0; and string match -q '*:*' -- "$branch"
139        set global_mode 1
140    end
141
142    set -l worktree_path
143
144    if test -z "$branch"
145        if test $global_mode -eq 1
146            set worktree_path (gw _path -g --interactive)
147        else
148            set worktree_path (gw _path --interactive)
149        end
150        if test $status -ne 0
151            return 1
152        end
153    else if test $global_mode -eq 1
154        set worktree_path (gw _path -g "$branch")
155        if test $status -ne 0
156            return 1
157        end
158    else
159        set worktree_path (git worktree list --porcelain 2>/dev/null | awk -v branch="$branch" '
160            /^worktree / { path=$2 }
161            /^branch / && $2 == "refs/heads/"branch { print path; exit }
162        ')
163    end
164
165    if test -z "$worktree_path"
166        if test -z "$branch"
167            echo "Error: No worktree found (not in a git repository?)" >&2
168        else
169            echo "Error: No worktree found for branch '$branch'" >&2
170        end
171        return 1
172    end
173
174    if test -d "$worktree_path"
175        cd "$worktree_path"; or return 1
176        echo "Switched to worktree: $worktree_path"
177    else
178        echo "Error: Worktree directory not found: $worktree_path" >&2
179        return 1
180    end
181end
182
183complete -c gw-cd -s g -l global -d 'Search all registered repositories'
184complete -c gw-cd -f -n '__fish_contains_opt -s g global' -a '(gw _path --list-branches -g 2>/dev/null)'
185complete -c gw-cd -f -n 'not __fish_contains_opt -s g global' -a '(git worktree list --porcelain 2>/dev/null | grep "^branch " | sed "s|^branch refs/heads/||" | sort -u)'
186"#;