package prep // initializes logging and command line options import ( "fmt" "os" "path/filepath" "strings" "go.wit.com/dev/alexflint/arg" "go.wit.com/lib/gui/shell" "go.wit.com/log" ) var argBash ArgsBash /* This struct can be used with the go-arg package. These are the generic default command line arguments for the 'GUI' package */ type ArgsBash struct { Bash bool `arg:"--bash" help:"generate bash completion"` } var myBash *BashAuto type BashAuto struct { id int // should be unique hidden bool // don't update the toolkits when it's hidden Auto func([]string) appName string // a good way to track the name of the binary ? } func dumpjunk() { fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, os.Args) os.Exit(0) } // argname is the name of the executable func Bash(argname string, autocomplete func([]string)) *BashAuto { if len(os.Args) > 1 && os.Args[1] == "--bash" { doBash(argname) os.Exit(0) } if len(os.Args) > 1 && os.Args[1] == "--auto-complete" { autocomplete(os.Args[2:]) os.Exit(0) } arg.Register(&argBash) myBash = new(BashAuto) myBash.appName = argname // parse go.Arg here? return myBash } // print out auto complete debugging info func AutoDebug(pb *Auto) { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "AUTO DEBUG: arg0='%s' arg1='%s' partial='%s' argv=%v\n", pb.Arg0, pb.Arg1, pb.Partial, pb.Argv) // fmt.Println("--all --gui --verbose --force") } // returns the last command (is blank if the current arg is not blank) func GetLast(cur string, argv []string) string { if cur != "''" { return "" } for _, s := range argv { if strings.HasPrefix(s, "-") { continue } return s } return "" } func parseArgv(argname string) *Auto { newauto := new(Auto) newauto.Argname = argname if len(os.Args) == 0 { return newauto } if len(os.Args) > 1 && os.Args[1] == "--bash" { newauto.SetupAuto = true return newauto } // set debug flag if os.Getenv("AUTOCOMPLETE_VERBOSE") == "true" { newauto.Debug = true } for _, s := range os.Args { if s == "--debug" { newauto.Debug = true } } // should we do auto complete here? if len(os.Args) > 1 && os.Args[1] == "--auto-complete" { newauto.IsAuto = true newauto.Arg0 = os.Args[0] newauto.Arg1 = os.Args[1] newauto.Partial = os.Args[2] newauto.Argv = os.Args[3:] return newauto } return newauto } // also try to parse/send cur (?) func Bash2(argname string, autocomplete func(*Auto)) { newauto := parseArgv(argname) if newauto.SetupAuto { doBash2(argname) os.Exit(0) } if newauto.Debug { // dump debug info AutoDebug(newauto) } if len(os.Args) > 1 && os.Args[1] == "--auto-complete" { autocomplete(newauto) os.Exit(0) } arg.Register(&argBash) } // returns the name of the executable registered for shell autocomplete func AppName() string { return myBash.appName } // makes a bash autocomplete file for your command func doBash(argname string) { fmt.Println(makeBashCompletionText(argname)) homeDir, err := os.UserHomeDir() if err != nil { log.Printf("%v\n", err) os.Exit(0) } filename := filepath.Join(homeDir, ".local/share/bash-completion/completions", argname) if shell.Exists(filename) { log.Println(filename, "file already exists") os.Exit(0) } basedir, _ := filepath.Split(filename) if !shell.IsDir(basedir) { os.MkdirAll(basedir, os.ModePerm) } if f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err == nil { f.Write([]byte(makeBashCompletionText(argname))) f.Close() log.Println("bash file created:", filename) log.Println("restart bash") } else { log.Info(filename, err) } os.Exit(0) } // makes a bash autocomplete file for your command func doBash2(argname string) { fmt.Println(makeBashCompletionText2(argname)) homeDir, err := os.UserHomeDir() if err != nil { log.Printf("%v\n", err) os.Exit(0) } filename := filepath.Join(homeDir, ".local/share/bash-completion/completions", argname) if shell.Exists(filename) { log.Println(filename, "file already exists") os.Exit(0) } basedir, _ := filepath.Split(filename) if !shell.IsDir(basedir) { os.MkdirAll(basedir, os.ModePerm) } if f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err == nil { f.Write([]byte(makeBashCompletionText2(argname))) f.Close() log.Println("bash file created:", filename) log.Println("restart bash") } else { log.Info(filename, err) } os.Exit(0) } /* // prints help to STDERR // TODO: move everything below this to go-args func (args) doBashHelp() { if argv.BashAuto[1] != "''" { // if this is not blank, then the user has typed something return } if argv.BashAuto[0] != ARGNAME { // if this is not the name of the command, the user already started doing something return } if argv.BashAuto[0] == ARGNAME { me.pp.WriteHelp(os.Stderr) return } fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "hello world") fmt.Fprintln(os.Stderr, "") } */ func makeBashCompletionText(argname string) string { var out string out += fmt.Sprintf("# add this in your bashrc:\n") out += fmt.Sprintf("\n") out += fmt.Sprintf("# todo: add this to go-arg as a 'hidden' go-arg option --bash\n") out += fmt.Sprintf("#\n") out += fmt.Sprintf("# Put the below in the file: ~/.local/share/bash-completion/completions/%s\n", argname) out += fmt.Sprintf("#\n") out += fmt.Sprintf("# todo: make this output work/parse with:\n") out += fmt.Sprintf("# complete -C %s --bash go\n", argname) out += fmt.Sprintf("\n") out += fmt.Sprintf("_%s_complete()\n", argname) out += fmt.Sprintf("{\n") out += fmt.Sprintf(" # sets local to this func vars\n") out += fmt.Sprintf(" local cur prev all\n") out += fmt.Sprintf(" cur=${COMP_WORDS[COMP_CWORD]}\n") out += fmt.Sprintf(" prev=${COMP_WORDS[COMP_CWORD-1]}\n") out += fmt.Sprintf(" all=${COMP_WORDS[@]}\n") out += fmt.Sprintf("\n") out += fmt.Sprintf(" # this is where we generate the go-arg output\n") out += fmt.Sprintf(" GOARGS=$(%s --auto-complete $prev \\'$cur\\' $all)\n", argname) out += fmt.Sprintf("\n") out += fmt.Sprintf(" # this compares the command line input from the user\n") out += fmt.Sprintf(" # to whatever strings we output\n") out += fmt.Sprintf(" COMPREPLY=( $(compgen -W \"$GOARGS\" -- $cur) ) # THIS WORKS\n") out += fmt.Sprintf(" return 0\n") out += fmt.Sprintf("}\n") out += fmt.Sprintf("complete -F _%s_complete %s\n", argname, argname) out += fmt.Sprintf("\n") out += fmt.Sprintf("# copy and paste the above into your bash shell should work\n") return out } func makeBashCompletionText2(argname string) string { var out string out += fmt.Sprintf("# add this in your bashrc:\n") out += fmt.Sprintf("\n") out += fmt.Sprintf("# todo: add this to go-arg as a 'hidden' go-arg option --bash\n") out += fmt.Sprintf("#\n") out += fmt.Sprintf("# Put the below in the file: ~/.local/share/bash-completion/completions/%s\n", argname) out += fmt.Sprintf("#\n") out += fmt.Sprintf("# todo: make this output work/parse with:\n") out += fmt.Sprintf("# complete -C %s --bash go\n", argname) out += fmt.Sprintf("\n") out += fmt.Sprintf("_%s_complete()\n", argname) out += fmt.Sprintf("{\n") out += fmt.Sprintf(" # sets local to this func vars\n") out += fmt.Sprintf(" local cur prev all\n") out += fmt.Sprintf(" cur=${COMP_WORDS[COMP_CWORD]}\n") out += fmt.Sprintf(" # prev=${COMP_WORDS[COMP_CWORD-1]}\n") out += fmt.Sprintf(" all=${COMP_WORDS[@]}\n") out += fmt.Sprintf("\n") out += fmt.Sprintf(" # this is where we generate the go-arg output\n") out += fmt.Sprintf(" GOARGS=$(%s --auto-complete \\'$cur\\' $all)\n", argname) out += fmt.Sprintf("\n") out += fmt.Sprintf(" # this compares the command line input from the user\n") out += fmt.Sprintf(" # to whatever strings we output\n") out += fmt.Sprintf(" COMPREPLY=( $(compgen -W \"$GOARGS\" -- $cur) ) # THIS WORKS\n") out += fmt.Sprintf(" return 0\n") out += fmt.Sprintf("}\n") out += fmt.Sprintf("complete -F _%s_complete %s\n", argname, argname) out += fmt.Sprintf("\n") out += fmt.Sprintf("# copy and paste the above into your bash shell should work\n") return out }