From 2fabd7d367fc29a13608fdac611778780c3007e3 Mon Sep 17 00:00:00 2001 From: Amir Mohammad Fakhimi Date: Fri, 28 Jul 2023 18:34:06 +0330 Subject: [PATCH 1/5] add zsh support --- core/commands/commands.go | 26 +++++++++++++++++++++++++- core/commands/completion.go | 29 ++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/core/commands/commands.go b/core/commands/commands.go index 794e1a5920d..deacbacfe95 100644 --- a/core/commands/commands.go +++ b/core/commands/commands.go @@ -13,7 +13,7 @@ import ( "sort" "strings" - "github.com/ipfs/go-ipfs-cmds" + cmds "github.com/ipfs/go-ipfs-cmds" ) type commandEncoder struct { @@ -169,6 +169,30 @@ To install the completions permanently, they can be moved to return res.Emit(&buf) }, }, + "zsh": { + Helptext: cmds.HelpText{ + Tagline: "Generate zsh shell completions.", + ShortDescription: "Generates command completions for the zsh shell.", + LongDescription: ` +Generates command completions for the zsh shell. +The simplest way to see it working is write the completions +to a file and then source it: + > ipfs commands completion zsh > ipfs-completion.zsh + > source ./ipfs-completion.zsh +To install the completions permanently, they can be moved to +/etc/zsh/completions or sourced from your ~/.zshrc file. +`, + }, + NoRemote: true, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + var buf bytes.Buffer + if err := writeZshCompletions(root, &buf); err != nil { + return err + } + res.SetLength(uint64(buf.Len())) + return res.Emit(&buf) + }, + }, "fish": { Helptext: cmds.HelpText{ Tagline: "Generate fish shell completions.", diff --git a/core/commands/completion.go b/core/commands/completion.go index 8babaac36e3..2f5b8b61ea4 100644 --- a/core/commands/completion.go +++ b/core/commands/completion.go @@ -83,7 +83,7 @@ func commandToCompletions(name string, fullName string, cmd *cmds.Command) *comp return parsed } -var bashCompletionTemplate, fishCompletionTemplate *template.Template +var bashCompletionTemplate, fishCompletionTemplate, zshCompletionTemplate *template.Template func init() { commandTemplate := template.Must(template.New("command").Parse(` @@ -153,6 +153,28 @@ _ipfs() { {{ template "command" . }} } complete -o nosort -o nospace -o default -F _ipfs ipfs +`)) + + zshCompletionTemplate = template.Must(commandTemplate.New("root").Parse(`#!bin/zsh +autoload bashcompinit +bashcompinit +_ipfs_compgen() { +local oldifs="$IFS" +IFS=$'\n' +while read -r line; do + COMPREPLY+=("$line") +done < <(compgen "$@") +IFS="$oldifs" +} + +_ipfs() { +COMPREPLY=() +local index=1 +local argidx=0 +local word="${COMP_WORDS[COMP_CWORD]}" +{{ template "command" . }} +} +complete -o nosort -o nospace -o default -F _ipfs ipfs `)) fishCommandTemplate := template.Must(template.New("command").Parse(` @@ -221,3 +243,8 @@ func writeFishCompletions(cmd *cmds.Command, out io.Writer) error { cmds := commandToCompletions("ipfs", "", cmd) return fishCompletionTemplate.Execute(out, cmds) } + +func writeZshCompletions(cmd *cmds.Command, out io.Writer) error { + cmds := commandToCompletions("ipfs", "", cmd) + return zshCompletionTemplate.Execute(out, cmds) +} From 11a63f9db4d1a190a5c9438eb9e05860aa9a38d0 Mon Sep 17 00:00:00 2001 From: Amir Mohammad Fakhimi Date: Fri, 28 Jul 2023 18:35:44 +0330 Subject: [PATCH 2/5] add zsh to doc --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 9cdb8742937..9b5401abdc5 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,19 @@ IPFS is a global, versioned, peer-to-peer filesystem. It combines good ideas fro For more info see: https://docs.ipfs.tech/concepts/what-is-ipfs/ +# ZSH + +The zsh shell is also supported: + +The simplest way to "eval" the completions logic: + +```bash +> eval "$(ipfs commands completion zsh)" +``` + +To install the completions permanently, they can be moved to +`/etc/bash_completion.d` or sourced from your `~/.zshrc` file. + Before opening an issue, consider using one of the following locations to ensure you are opening your thread in the right place: - kubo (previously named go-ipfs) _implementation_ bugs in [this repo](https://github.com/ipfs/kubo/issues). - Documentation issues in [ipfs/docs issues](https://github.com/ipfs/ipfs-docs/issues). From 8a696df69ffa7a0c15d0fbf909f6157379760cde Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 17 Aug 2023 15:11:05 +0200 Subject: [PATCH 3/5] docs: move zsh details to command-completion.md --- README.md | 13 ------------- docs/command-completion.md | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9b5401abdc5..9cdb8742937 100644 --- a/README.md +++ b/README.md @@ -25,19 +25,6 @@ IPFS is a global, versioned, peer-to-peer filesystem. It combines good ideas fro For more info see: https://docs.ipfs.tech/concepts/what-is-ipfs/ -# ZSH - -The zsh shell is also supported: - -The simplest way to "eval" the completions logic: - -```bash -> eval "$(ipfs commands completion zsh)" -``` - -To install the completions permanently, they can be moved to -`/etc/bash_completion.d` or sourced from your `~/.zshrc` file. - Before opening an issue, consider using one of the following locations to ensure you are opening your thread in the right place: - kubo (previously named go-ipfs) _implementation_ bugs in [this repo](https://github.com/ipfs/kubo/issues). - Documentation issues in [ipfs/docs issues](https://github.com/ipfs/ipfs-docs/issues). diff --git a/docs/command-completion.md b/docs/command-completion.md index b84483e616e..207f611bf68 100644 --- a/docs/command-completion.md +++ b/docs/command-completion.md @@ -24,3 +24,16 @@ The simplest way to use the completions logic: To install the completions permanently, they can be moved to `/etc/fish/completions` or `~/.config/fish/completions` or sourced from your `~/.config/fish/config.fish` file. + +## ZSH + +The zsh shell is also supported: + +The simplest way to "eval" the completions logic: + +```bash +> eval "$(ipfs commands completion zsh)" +``` + +To install the completions permanently, they can be moved to +`/etc/bash_completion.d` or sourced from your `~/.zshrc` file. From c59e6bbf0befb4a77ab36d26255e466b9ec7e830 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 17 Aug 2023 15:37:40 +0200 Subject: [PATCH 4/5] feat: add completion test for zsh --- .github/workflows/gotest.yml | 2 ++ core/commands/commands.go | 3 +++ core/commands/commands_test.go | 1 + test/cli/completion_test.go | 26 ++++++++++++++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/.github/workflows/gotest.yml b/.github/workflows/gotest.yml index 08a741532f0..630160fbb82 100644 --- a/.github/workflows/gotest.yml +++ b/.github/workflows/gotest.yml @@ -35,6 +35,8 @@ jobs: go-version: 1.19.x - name: Check out Kubo uses: actions/checkout@v3 + - name: Install missing tools + run: sudo apt update && sudo apt install -y zsh - name: Restore Go cache uses: protocol/cache-go-action@v1 with: diff --git a/core/commands/commands.go b/core/commands/commands.go index deacbacfe95..249f0ffbe11 100644 --- a/core/commands/commands.go +++ b/core/commands/commands.go @@ -175,10 +175,13 @@ To install the completions permanently, they can be moved to ShortDescription: "Generates command completions for the zsh shell.", LongDescription: ` Generates command completions for the zsh shell. + The simplest way to see it working is write the completions to a file and then source it: + > ipfs commands completion zsh > ipfs-completion.zsh > source ./ipfs-completion.zsh + To install the completions permanently, they can be moved to /etc/zsh/completions or sourced from your ~/.zshrc file. `, diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index 0f2b0721b3c..af18ebecd83 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -25,6 +25,7 @@ func TestROCommands(t *testing.T) { "/commands/completion", "/commands/completion/bash", "/commands/completion/fish", + "/commands/completion/zsh", "/dag", "/dag/get", "/dag/resolve", diff --git a/test/cli/completion_test.go b/test/cli/completion_test.go index 0c40eb02b6e..548cb17a2ff 100644 --- a/test/cli/completion_test.go +++ b/test/cli/completion_test.go @@ -29,3 +29,29 @@ func TestBashCompletion(t *testing.T) { assert.NoError(t, res.Err) }) } + +func TestZshCompletion(t *testing.T) { + t.Parallel() + h := harness.NewT(t) + node := h.NewNode() + + res := node.IPFS("commands", "completion", "zsh") + + length := len(res.Stdout.String()) + if length < 100 { + t.Fatalf("expected a long Bash completion file, but got one of length %d", length) + } + + t.Run("completion file can be loaded in bash", func(t *testing.T) { + RequiresLinux(t) + + completionFile := h.WriteToTemp(res.Stdout.String()) + res = h.Runner.Run(harness.RunRequest{ + Path: "zsh", + Args: []string{"-c", fmt.Sprintf("autoload -Uz compinit && compinit && source %s && echo -E $_comps[ipfs]", completionFile)}, + }) + + assert.NoError(t, res.Err) + assert.NotEmpty(t, res.Stdout.String()) + }) +} From 99b43f3f2e54b4a821734450d3235690dd091c1c Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 17 Aug 2023 16:05:51 +0200 Subject: [PATCH 5/5] fix: add zsh to TestCommands --- core/commands/commands_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index af18ebecd83..a73a0338e50 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -103,6 +103,7 @@ func TestCommands(t *testing.T) { "/commands/completion", "/commands/completion/bash", "/commands/completion/fish", + "/commands/completion/zsh", "/config", "/config/edit", "/config/profile",