1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ShellHookKind {
10 Zsh,
11 Bash,
12 Fish,
13}
14
15pub fn shell_hook_snippet(kind: ShellHookKind) -> &'static str {
19 match kind {
20 ShellHookKind::Zsh | ShellHookKind::Bash => ZSH_BASH_SNIPPET,
21 ShellHookKind::Fish => FISH_SNIPPET,
22 }
23}
24
25const ZSH_BASH_SNIPPET: &str = r#"# heddle shell hook — installed via `heddle shell init zsh` (or bash)
28# Wraps `heddle start`, `heddle thread switch`, and `heddle thread cd`
29# so they auto-cd into the target thread's worktree.
30# Also defines `__heddle_ps1`, a compact prompt segment helper.
31heddle() {
32 case "$1 $2" in
33 "start "*)
34 local path
35 path=$(command heddle start "${@:2}" --print-cd-path 2>/dev/null) || {
36 command heddle "$@"
37 return $?
38 }
39 cd "$path" && printf 'heddle: %s\n' "$path"
40 ;;
41 "thread switch "*)
42 local path
43 path=$(command heddle thread switch "${@:3}" --print-cd-path 2>/dev/null) || {
44 command heddle "$@"
45 return $?
46 }
47 cd "$path" && printf 'heddle: %s\n' "$path"
48 ;;
49 "thread cd "*)
50 local path
51 path=$(command heddle thread cd "${@:3}") || return $?
52 cd "$path"
53 ;;
54 *)
55 command heddle "$@"
56 ;;
57 esac
58}
59
60__heddle_ps1() {
61 local segment
62 segment=$(command heddle shell prompt 2>/dev/null) || return 0
63 [ -n "$segment" ] && printf '(%s)' "$segment"
64}
65"#;
66
67const FISH_SNIPPET: &str = r#"# heddle shell hook — installed via `heddle shell init fish`
69# Wraps `heddle start`, `heddle thread switch`, and `heddle thread cd`
70# so they auto-cd into the target thread's worktree.
71# Also defines `__heddle_ps1`, a compact prompt segment helper.
72function heddle
73 switch "$argv[1] $argv[2]"
74 case 'start *'
75 set -l path (command heddle start $argv[2..] --print-cd-path 2>/dev/null)
76 if test $status -ne 0
77 command heddle $argv
78 return $status
79 end
80 cd "$path"; and printf 'heddle: %s\n' "$path"
81 case 'thread switch *'
82 set -l path (command heddle thread switch $argv[3..] --print-cd-path 2>/dev/null)
83 if test $status -ne 0
84 command heddle $argv
85 return $status
86 end
87 cd "$path"; and printf 'heddle: %s\n' "$path"
88 case 'thread cd *'
89 set -l path (command heddle thread cd $argv[3..])
90 if test $status -ne 0
91 return $status
92 end
93 cd "$path"
94 case '*'
95 command heddle $argv
96 end
97end
98
99function __heddle_ps1
100 set -l segment (command heddle shell prompt 2>/dev/null)
101 if test -n "$segment"
102 printf '(%s)' "$segment"
103 end
104end
105"#;
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn zsh_and_bash_share_the_same_body() {
113 assert!(std::ptr::eq(
114 shell_hook_snippet(ShellHookKind::Zsh),
115 shell_hook_snippet(ShellHookKind::Bash)
116 ));
117 let body = shell_hook_snippet(ShellHookKind::Zsh);
118 assert!(body.contains("heddle() {"));
119 assert!(body.contains("__heddle_ps1()"));
120 }
121
122 #[test]
123 fn fish_uses_fish_function_syntax() {
124 let body = shell_hook_snippet(ShellHookKind::Fish);
125 assert!(body.contains("function heddle"));
126 assert!(body.contains("$argv"));
127 assert!(body.contains("function __heddle_ps1"));
128 }
129}