diff --git a/README.md b/README.md index a92b90c..410e91d 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,20 @@ brew tap simonbs/wut https://github.com/simonbs/wut.git brew install wut ``` -You'll need Git on your machine. After installation, add shell integration to your `~/.zshrc` or `~/.bashrc`: +You'll need Git on your machine. After installation, add shell integration: +**Bash/Zsh** - Add to `~/.bashrc` or `~/.zshrc`: ```sh eval "$(wut init)" ``` +**Fish** - Add to `~/.config/fish/config.fish`: +```fish +wut init | source +``` + +`wut init` uses the `$SHELL` environment variable to detect the shell. You can pass in `--zsh`, `--bash` or `--fish` to override the autodetection. + This enables automatic directory changing when you run `wut new` or `wut go`. Without it, these commands will prompt you to set up shell integration. ## 🧭 Usage diff --git a/cmd/wut/cmd_init.go b/cmd/wut/cmd_init.go index b7c44e1..848e60f 100644 --- a/cmd/wut/cmd_init.go +++ b/cmd/wut/cmd_init.go @@ -8,8 +8,33 @@ import ( "github.com/simonbs/wut/src/worktree" ) -func cmdInit() { +func cmdInit(args []string) { + shell := "" + for _, arg := range args { + switch arg { + case "--fish": + shell = "fish" + case "--bash": + shell = "bash" + case "--zsh": + shell = "zsh" + } + } + if shell == "" { + shell = detectShell() + } + binPath, _ := os.Executable() + + switch shell { + case "fish": + printFishWrapper(binPath) + default: + printBashZshWrapper(binPath) + } +} + +func printBashZshWrapper(binPath string) { wrapper := `wut() { local wut_bin="` + binPath + `" export WUT_WRAPPER_ACTIVE=1 @@ -63,6 +88,42 @@ fi` fmt.Println(wrapper) } +func printFishWrapper(binPath string) { + wrapper := `function wut + set -l wut_bin "` + binPath + `" + set -x WUT_WRAPPER_ACTIVE 1 + set -l output ($wut_bin $argv 2>&1) + set -l exit_code $status + set -l cd_marker (printf "%s\n" $output | grep "^__WUT_CD__:" | head -1) + if test -n "$cd_marker" + set -l target_dir (string replace "__WUT_CD__:" "" "$cd_marker") + if test -d "$target_dir" + cd "$target_dir" + end + set -l filtered (printf "%s\n" $output | grep -v "^__WUT_CD__:") + if test -n "$filtered" + printf "%s\n" $filtered + end + else + if test (count $output) -gt 0 + printf "%s\n" $output + end + end + return $exit_code +end + +# Subcommands +complete -c wut -f -n "__fish_use_subcommand" -a "new" -d "Create new worktree" +complete -c wut -f -n "__fish_use_subcommand" -a "list" -d "List worktrees" +complete -c wut -f -n "__fish_use_subcommand" -a "go" -d "Go to worktree" +complete -c wut -f -n "__fish_use_subcommand" -a "path" -d "Print worktree path" +complete -c wut -f -n "__fish_use_subcommand" -a "rm" -d "Remove worktree" + +# Branch completions for go/path/rm +complete -c wut -f -n "__fish_seen_subcommand_from go path rm" -a "(` + binPath + ` --completions branches 2>/dev/null)"` + fmt.Println(wrapper) +} + func cmdCompletions(args []string) { if len(args) < 1 { return diff --git a/cmd/wut/help.go b/cmd/wut/help.go index 23655db..d81d9e5 100644 --- a/cmd/wut/help.go +++ b/cmd/wut/help.go @@ -31,9 +31,23 @@ func printUsage() { fmt.Println(" wut rm [--force] 🗑 Remove a worktree") if !context.IsWrapperActive() { + dotfile := "" + command := "" + switch detectShell() { + case "bash": + dotfile = "~/.bashrc" + command = "eval \"$(wut init)\"" + case "fish": + dotfile = "~/.config/fish/config.fish" + command = "wut init | source" + case "zsh": + dotfile = "~/.zshrc" + command = "eval \"$(wut init)\"" + } + fmt.Println() - fmt.Println("⚠️ Add shell integration to ~/.zshrc or ~/.bashrc:") + fmt.Println("⚠️ Add shell integration to " + dotfile + ":") fmt.Println() - fmt.Println(" eval \"$(wut init)\"") + fmt.Println(" " + command) } } diff --git a/cmd/wut/main.go b/cmd/wut/main.go index 5744d3f..2789540 100644 --- a/cmd/wut/main.go +++ b/cmd/wut/main.go @@ -18,7 +18,7 @@ func main() { switch cmd { case "init": - cmdInit() + cmdInit(args) case "new": cmdNew(args) case "list": diff --git a/cmd/wut/utils.go b/cmd/wut/utils.go index 3c07f96..7db4275 100644 --- a/cmd/wut/utils.go +++ b/cmd/wut/utils.go @@ -18,3 +18,14 @@ func tildify(path string) string { } return path } + +func detectShell() string { + shell := os.Getenv("SHELL") + if strings.Contains(shell, "fish") { + return "fish" + } + if strings.Contains(shell, "zsh") { + return "zsh" + } + return "bash" +}