I am trying to understand how to create costume commands for go using the cobra (and viper) libraries and be able to use them.
Specifically I was trying to understand and make the example they provide work. The example is the following:
import(
"github.com/spf13/cobra"
"fmt"
"strings"
)
func main() {
var echoTimes int
var cmdPrint = &cobra.Command{
Use: "print [string to print]",
Short: "Print anything to the screen",
Long: `print is for printing anything back to the screen.
For many years people have printed back to the screen.
`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Print: " + strings.Join(args, " "))
},
}
var cmdEcho = &cobra.Command{
Use: "echo [string to echo]",
Short: "Echo anything to the screen",
Long: `echo is for echoing anything back.
Echo works a lot like print, except it has a child command.
`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Print: " + strings.Join(args, " "))
},
}
var cmdTimes = &cobra.Command{
Use: "times [# times] [string to echo]",
Short: "Echo anything to the screen more times",
Long: `echo things multiple times back to the user by providing
a count and a string.`,
Run: func(cmd *cobra.Command, args []string) {
for i:=0; i < echoTimes; i++ {
fmt.Println("Echo: " + strings.Join(args, " "))
}
},
}
cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input")
var rootCmd = &cobra.Command{Use: "app"}
rootCmd.AddCommand(cmdPrint, cmdEcho)
cmdEcho.AddCommand(cmdTimes)
rootCmd.Execute()
}
However, I have made the file for it, in package main
and I can't seem to make it work properly. I do understand that the rootCmd is not suppose to be executable. However, it seems to me that the Use field behaves inconsistently (as far as I can tell). I was trying to understand how commands actually run in the command line and compile the file in different ways to experiment this.
For example I compiled this file I named as cobra.go
with go build cobra.go
and now I have an executable cobra
.
If I do ./name
it behaves the same way as ./name help
and prints:
Usage:
app [command]
Available Commands:
print [string to print] Print anything to the screen
echo [string to echo] Echo anything to the screen
help [command] Help about any command
Available Flags:
--help=false: help for app
Use "app help [command]" for more information about that command.
However the description incorrectly says that to use it you must do "app help [command]".
If I do that ./app help print
(with only the cobra executable of course) it prints:
zsh: no such file or directory: ./app
if I do app help print
it also doesn't work (since it isn't found in PATH):
zsh: command not found: app
So my understanding is that, unless I build it with the same name as root, cobra will act funny.
So it means that the use field has to match the file name for the output of help to make sense and for us to be able to run its sub commands properly, right?
Also, how is one able to have (compile) multiple different "root" commands in the same project, if only one package main is allowed? If one has multiple "root" commands under main, it shouldn't work, right? I will try some of these ideas soon.
You could check how cobra is used is other projects (go-search).
For instance, the bitballoon-cli
project defines multiple commands, each in their own file, each in the main package. Like create.go
:
package main
import (
"github.com/BitBalloon/bitballoon-go"
"github.com/spf13/cobra"
"log"
)
var createCmd = &cobra.Command{
Use: "create",
Short: "create a new BitBalloon site",
Long: "creates a new BitBalloon site and returns an ID you can deploy to",
}
var siteName, customDomain, password, notificationEmail string
func init() {
createCmd.Run = create
createCmd.Flags().StringVarP(&siteName, "name", "n", "", "Name of the site (must be a valid subdomain: <name>.bitballoon.com)")
createCmd.Flags().StringVarP(&customDomain, "domain", "d", "", "Custom domain for the site (only works for premium sites)")
createCmd.Flags().StringVarP(&password, "password", "p", "", "Password for the site")
createCmd.Flags().StringVarP(¬ificationEmail, "email", "e", "", "Notification email for form submissions (only works for premium sites)")
}
func create(cmd *cobra.Command, args []string) {
// your function for this command
}
You could check if that way of defining and adding a command to your project works in your case.
4 years later, see the video "justforfunc #32: CLI tools with Cobra", by Francesc Campoy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With