github.com/devwanda/aphelion-staking@v0.33.9/libs/cli/helper.go (about) 1 package cli 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 11 "github.com/spf13/cobra" 12 ) 13 14 // WriteConfigVals writes a toml file with the given values. 15 // It returns an error if writing was impossible. 16 func WriteConfigVals(dir string, vals map[string]string) error { 17 data := "" 18 for k, v := range vals { 19 data += fmt.Sprintf("%s = \"%s\"\n", k, v) 20 } 21 cfile := filepath.Join(dir, "config.toml") 22 return ioutil.WriteFile(cfile, []byte(data), 0666) 23 } 24 25 // RunWithArgs executes the given command with the specified command line args 26 // and environmental variables set. It returns any error returned from cmd.Execute() 27 func RunWithArgs(cmd Executable, args []string, env map[string]string) error { 28 oargs := os.Args 29 oenv := map[string]string{} 30 // defer returns the environment back to normal 31 defer func() { 32 os.Args = oargs 33 for k, v := range oenv { 34 os.Setenv(k, v) 35 } 36 }() 37 38 // set the args and env how we want them 39 os.Args = args 40 for k, v := range env { 41 // backup old value if there, to restore at end 42 oenv[k] = os.Getenv(k) 43 err := os.Setenv(k, v) 44 if err != nil { 45 return err 46 } 47 } 48 49 // and finally run the command 50 return cmd.Execute() 51 } 52 53 // RunCaptureWithArgs executes the given command with the specified command 54 // line args and environmental variables set. It returns string fields 55 // representing output written to stdout and stderr, additionally any error 56 // from cmd.Execute() is also returned 57 func RunCaptureWithArgs(cmd Executable, args []string, env map[string]string) (stdout, stderr string, err error) { 58 oldout, olderr := os.Stdout, os.Stderr // keep backup of the real stdout 59 rOut, wOut, _ := os.Pipe() 60 rErr, wErr, _ := os.Pipe() 61 os.Stdout, os.Stderr = wOut, wErr 62 defer func() { 63 os.Stdout, os.Stderr = oldout, olderr // restoring the real stdout 64 }() 65 66 // copy the output in a separate goroutine so printing can't block indefinitely 67 copyStd := func(reader *os.File) *(chan string) { 68 stdC := make(chan string) 69 go func() { 70 var buf bytes.Buffer 71 // io.Copy will end when we call reader.Close() below 72 io.Copy(&buf, reader) 73 stdC <- buf.String() 74 }() 75 return &stdC 76 } 77 outC := copyStd(rOut) 78 errC := copyStd(rErr) 79 80 // now run the command 81 err = RunWithArgs(cmd, args, env) 82 83 // and grab the stdout to return 84 wOut.Close() 85 wErr.Close() 86 stdout = <-*outC 87 stderr = <-*errC 88 return stdout, stderr, err 89 } 90 91 // NewCompletionCmd returns a cobra.Command that generates bash and zsh 92 // completion scripts for the given root command. If hidden is true, the 93 // command will not show up in the root command's list of available commands. 94 func NewCompletionCmd(rootCmd *cobra.Command, hidden bool) *cobra.Command { 95 flagZsh := "zsh" 96 cmd := &cobra.Command{ 97 Use: "completion", 98 Short: "Generate shell completion scripts", 99 Long: fmt.Sprintf(`Generate Bash and Zsh completion scripts and print them to STDOUT. 100 101 Once saved to file, a completion script can be loaded in the shell's 102 current session as shown: 103 104 $ . <(%s completion) 105 106 To configure your bash shell to load completions for each session add to 107 your $HOME/.bashrc or $HOME/.profile the following instruction: 108 109 . <(%s completion) 110 `, rootCmd.Use, rootCmd.Use), 111 RunE: func(cmd *cobra.Command, _ []string) error { 112 zsh, err := cmd.Flags().GetBool(flagZsh) 113 if err != nil { 114 return err 115 } 116 if zsh { 117 return rootCmd.GenZshCompletion(cmd.OutOrStdout()) 118 } 119 return rootCmd.GenBashCompletion(cmd.OutOrStdout()) 120 }, 121 Hidden: hidden, 122 Args: cobra.NoArgs, 123 } 124 125 cmd.Flags().Bool(flagZsh, false, "Generate Zsh completion script") 126 127 return cmd 128 }