diff --git a/cmd/gen.go b/cmd/gen.go new file mode 100644 index 00000000..083e39c6 --- /dev/null +++ b/cmd/gen.go @@ -0,0 +1,12 @@ +package cmd + +import "github.com/spf13/cobra" + +var genCmd = &cobra.Command{ + Use: "gen", + Short: "A collection of useful generators", +} + +func init() { + rootCmd.AddCommand(genCmd) +} diff --git a/cmd/gencompletion.go b/cmd/gencompletion.go new file mode 100644 index 00000000..cb403767 --- /dev/null +++ b/cmd/gencompletion.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "os" + + "github.com/rs/zerolog" + "github.com/spf13/cobra" + + "github.com/drakkan/sftpgo/logger" +) + +var genCompletionCmd = &cobra.Command{ + Use: "completion [bash|zsh|fish|powershell]", + Short: "Generate shell completion script to the stdout", + Long: `To load completions: + +Bash: + +$ source <(sftpgo completion bash) + +# To load completions for each session, execute once: +Linux: + $ sftpgo completion bash > /etc/bash_completion.d/sftpgo-completion.bash +MacOS: + $ sftpgo completion bash > /usr/local/etc/bash_completion.d/sftpgo-completion.bash + +Zsh: + +$ source <(sftpgo completion zsh) + +# To load completions for each session, execute once: +$ sftpgo completion zsh > "${fpath[1]}/_sftpgo" + +Fish: + +$ sftpgo completion fish | source + +# To load completions for each session, execute once: +$ sftpgo completion fish > ~/.config/fish/completions/sftpgo.fish +`, + DisableFlagsInUseLine: true, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + Args: cobra.ExactValidArgs(1), + Run: func(cmd *cobra.Command, args []string) { + var err error + logger.DisableLogger() + logger.EnableConsoleLogger(zerolog.DebugLevel) + switch args[0] { + case "bash": + err = cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + err = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + err = cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + err = cmd.Root().GenPowerShellCompletion(os.Stdout) + } + if err != nil { + logger.WarnToConsole("Unable to generate shell completion script: %v", err) + os.Exit(1) + } + }, +} + +func init() { + genCmd.AddCommand(genCompletionCmd) +} diff --git a/cmd/genman.go b/cmd/genman.go new file mode 100644 index 00000000..0142070a --- /dev/null +++ b/cmd/genman.go @@ -0,0 +1,52 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/rs/zerolog" + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" + + "github.com/drakkan/sftpgo/logger" + "github.com/drakkan/sftpgo/version" +) + +var ( + manDir string + genManCmd = &cobra.Command{ + Use: "man", + Short: "Generate man pages for SFTPGo CLI", + Long: `This command automatically generates up-to-date man pages of SFTPGo's +command-line interface. By default, it creates the man page files +in the "man" directory under the current directory. +`, + Run: func(cmd *cobra.Command, args []string) { + logger.DisableLogger() + logger.EnableConsoleLogger(zerolog.DebugLevel) + if _, err := os.Stat(manDir); os.IsNotExist(err) { + err = os.Mkdir(manDir, os.ModePerm) + if err != nil { + logger.WarnToConsole("Unable to generate man page files: %v", err) + os.Exit(1) + } + } + header := &doc.GenManHeader{ + Section: "1", + Manual: "SFTPGo Manual", + Source: fmt.Sprintf("SFTPGo %v", version.Get().Version), + } + cmd.Root().DisableAutoGenTag = true + err := doc.GenManTree(cmd.Root(), header, manDir) + if err != nil { + logger.WarnToConsole("Unable to generate man page files: %v", err) + os.Exit(1) + } + }, + } +) + +func init() { + genManCmd.Flags().StringVarP(&manDir, "dir", "d", "man", "The directory to write the man pages") + genCmd.AddCommand(genManCmd) +} diff --git a/cmd/root.go b/cmd/root.go index 7ed0efcc..ff1d3eaf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -55,7 +55,7 @@ var ( rootCmd = &cobra.Command{ Use: "sftpgo", - Short: "Full featured and highly configurable SFTP server", + Short: "Fully featured and highly configurable SFTP server", } ) diff --git a/docs/full-configuration.md b/docs/full-configuration.md index fb71c429..9ee9e492 100644 --- a/docs/full-configuration.md +++ b/docs/full-configuration.md @@ -9,6 +9,7 @@ Usage: sftpgo [command] Available Commands: + gen A collection of useful generators help Help about any command initprovider Initializes the configured data provider portable Serve a single directory @@ -36,6 +37,8 @@ Log file can be rotated on demand sending a `SIGUSR1` signal on Unix based syste If you don't configure any private host key, the daemon will use `id_rsa` and `id_ecdsa` in the configuration directory. If these files don't exist, the daemon will attempt to autogenerate them (if the user that executes SFTPGo has write access to the `config-dir`). The server supports any private key format supported by [`crypto/ssh`](https://github.com/golang/crypto/blob/master/ssh/keys.go#L33). +The `gen` command allows to generate completion scripts for your shell and man pages. Currently the man pages visual representation is wrong, take a look at this upstream [bug](https://github.com/spf13/cobra/issues/1049) for more details. + ## Configuration file The configuration file contains the following sections: diff --git a/go.sum b/go.sum index f6cb70a6..9cf4921b 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -291,9 +292,11 @@ github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg= github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=