This is an automated email from the ASF dual-hosted git repository. hoshea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git
The following commit(s) were added to refs/heads/master by this push: new c54499d Support auto-completion for bash and powershell (#108) c54499d is described below commit c54499dbc130dce02473b133f9dc9cb8be24e364 Author: Team317 <52828870+tom-da...@users.noreply.github.com> AuthorDate: Mon Aug 16 20:03:12 2021 +0800 Support auto-completion for bash and powershell (#108) --- README.md | 34 ++++++++++++++ cmd/swctl/main.go | 8 ++++ internal/commands/completion/bash.go | 58 ++++++++++++++++++++++++ internal/commands/completion/completion.go | 31 +++++++++++++ internal/commands/completion/powershell.go | 71 ++++++++++++++++++++++++++++++ 5 files changed, 202 insertions(+) diff --git a/README.md b/README.md index 7db37e3..7b0efac 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,40 @@ Then copy the `./bin/swctl-latest-(darwin|linux|windows)-amd64` to your `PATH` d You can also copy it to any directory you like, then add that directory to `PATH`. **We recommend you to rename the `swctl-latest-(darwin|linux|windows)-amd64` to `swctl`.** +## Autocompletion + +`swctl` provides auto-completion support for bash and powershell, which can save you a lot of typing. + +### Bash + +The swctl completion script for bash can be generated with the command `swctl completion bash`. Sourcing the completion script in your shell enables swctl auto-completion: + +```shell +swctl completion bash > bash_autocomplete && + sudo cp ./bash_autocomplete /etc/bash_completion.d/swctl && + echo >> ~/.bashrc && + echo "export PROG=swctl" >> ~/.bashrc +``` + +After reloading your shell, swctl auto-completion should be working. + +### powershell + +Similarly, run the following command in your powershell terminal to enable auto-completion: + +```shell +set-executionpolicy remotesigned -Scope CurrentUser +swctl completion powershell >> $profile +``` + +If you get an error like `OpenError: (:) [Out-File], DirectoryNotFoundException`, then you need to run the following command to create `$profile` file: + +```shell +New-Item -Type file -Force $profile +``` + +After reloading your shell, swctl auto-completion should be working. + # Commands Commands in SkyWalking CLI are organized into two levels, in the form of `swctl --option <level1> --option <level2> --option`, diff --git a/cmd/swctl/main.go b/cmd/swctl/main.go index 9d5b262..2ca1733 100644 --- a/cmd/swctl/main.go +++ b/cmd/swctl/main.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" + "github.com/apache/skywalking-cli/internal/commands/completion" "github.com/apache/skywalking-cli/internal/commands/dashboard" "github.com/apache/skywalking-cli/internal/commands/dependency" "github.com/apache/skywalking-cli/internal/commands/endpoint" @@ -125,6 +126,7 @@ func main() { event.Command, logs.Command, profile.Command, + completion.Command, dependency.Command, } @@ -137,6 +139,12 @@ func main() { app.Flags = flags app.CommandNotFound = util.CommandNotFound + // Enable auto-completion. + app.EnableBashCompletion = true + cli.BashCompletionFlag = cli.BoolFlag{ + Name: "auto_complete", + Hidden: true, + } if err := app.Run(os.Args); err != nil { log.Fatalln(err) } diff --git a/internal/commands/completion/bash.go b/internal/commands/completion/bash.go new file mode 100644 index 0000000..aed8075 --- /dev/null +++ b/internal/commands/completion/bash.go @@ -0,0 +1,58 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package completion + +import ( + "fmt" + + "github.com/urfave/cli" +) + +var bashCommand = cli.Command{ + Name: "bash", + Aliases: []string{"b"}, + Usage: "Output shell completion code for bash", + ArgsUsage: "[parameters...]", + Action: func(ctx *cli.Context) error { + fmt.Print(bashScript) + return nil + }, +} + +const bashScript = ` +: ${PROG:=$(basename ${BASH_SOURCE})} + +_cli_bash_autocomplete() { + if [[ "${COMP_WORDS[0]}" != "source" ]]; then + local cur opts base + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + if [[ "$cur" == "-"* ]]; then + opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --auto_complete ) + else + opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --auto_complete ) + fi + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + fi +} + +complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG +unset PROG + +` diff --git a/internal/commands/completion/completion.go b/internal/commands/completion/completion.go new file mode 100644 index 0000000..c5733e4 --- /dev/null +++ b/internal/commands/completion/completion.go @@ -0,0 +1,31 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package completion + +import ( + "github.com/urfave/cli" +) + +var Command = cli.Command{ + Name: "completion", + Usage: "Output shell completion code for bash and powershell", + Subcommands: []cli.Command{ + bashCommand, + powershellCommand, + }, +} diff --git a/internal/commands/completion/powershell.go b/internal/commands/completion/powershell.go new file mode 100644 index 0000000..1c08123 --- /dev/null +++ b/internal/commands/completion/powershell.go @@ -0,0 +1,71 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package completion + +import ( + "fmt" + + "github.com/urfave/cli" +) + +var powershellCommand = cli.Command{ + Name: "powershell", + Aliases: []string{"p"}, + Usage: "Output shell completion code for powershell", + ArgsUsage: "[parameters...]", + Action: func(ctx *cli.Context) error { + fmt.Print(powershellScript) + return nil + }, +} + +const powershellScript = ` +Register-ArgumentCompleter -Native -CommandName swctl -ScriptBlock { + param($commandName, $commands, $cursorPosition) + + $match = $($(complete $commands $cursorPosition) -split " ") + # Output matched commands one by one. + for($i=0; $i -lt ($match.Length-1); $i+=1){ + Write-Output $match[$i] + } +} +# Find all matching commands. +function complete($commands, $cursorPosition){ + # Get command line parameters. + $parameters = $($commands -split " ") + # Uncompleted parameters. + $uncomplete = $parameters[-1] + + # Get the parameters before $uncomplete. + $len = $parameters.Length-2 + if ("$commands".Length -ne $cursorPosition) { return "" } + $beforeCommands = $parameters[0..($len)] + + # Find the command prefixed with $uncomplete. + $match = "" + Invoke-Expression "$beforeCommands --auto_complete" | ForEach-Object { + $flag = 1 + for ($i=0; $i -lt $uncomplete.Length; $i = $i +1){ + if ($_[$i] -ne $uncomplete[$i]) { $flag = 0 } + } + if ($flag -eq 1) { $match+="$_ " } + } + return $match +} + +`