package main import ( "fmt" "os" ) /* this parses the command line arguements using alex flint's go-arg */ var argv args type args struct { Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch git branches"` Config *ConfigCmd `arg:"subcommand:config" help:"show your .config/forge/ settings"` Dirty *EmptyCmd `arg:"subcommand:dirty" help:"check if your git repos are dirty"` GitReset *EmptyCmd `arg:"subcommand:hard-reset" help:"hard reset your user git branches"` List *FindCmd `arg:"subcommand:list" help:"just show a table of the current state"` Patch *PatchCmd `arg:"subcommand:patch" help:"examine and make patch sets"` GitPull *FindCmd `arg:"subcommand:pull" help:"run 'git pull'"` Rescan *EmptyCmd `arg:"subcommand:rescan" help:"recreate the git protobuf repos.pb file"` URL string `arg:"--connect" help:"gowebd url"` Bash bool `arg:"--bash" help:"generate bash completion"` BashAuto []string `arg:"--auto-complete" help:"does the actual autocompletion"` } type EmptyCmd struct { } type PatchCmd struct { List *EmptyCmd `arg:"subcommand:list" help:"list available patches"` Show *EmptyCmd `arg:"subcommand:show" help:"show a specific patch"` } type ConfigAddCmd struct { Path string `arg:"--path" help:"absolute path of the git repo"` GoPath string `arg:"--gopath" help:"GO path of the git repo"` Directory bool `arg:"--directory" default:"false" help:"repo is a directory to match against"` ReadOnly bool `arg:"--readonly" default:"false" help:"repo is readonly"` Writable bool `arg:"--writable" default:"false" help:"repo is writable"` Favorite bool `arg:"--favorite" default:"false" help:"forge will always go-clone or git clone this"` Private bool `arg:"--private" default:"false" help:"repo can not be published"` Interesting bool `arg:"--interesting" default:"false" help:"something you decided was cool"` Master string `arg:"--master" help:"the git 'master' or 'main' branch name"` Devel string `arg:"--devel" help:"the git devel branch name"` User string `arg:"--user" help:"the git user branch name"` } type ConfigCmd struct { Add *ConfigAddCmd `arg:"subcommand:add" help:"add a config setting"` Fix *EmptyCmd `arg:"subcommand:fix" help:"fix .config/forge/ and/or repos.pb protobuf file"` List *EmptyCmd `arg:"subcommand:list" help:"list your config settings"` Delete string `arg:"--delete" help:"delete this repo"` Register string `arg:"--register" help:"register your git URL (foo.com/mystuff) or (github.com/foo/bar)"` } type CheckoutCmd struct { User *FindCmd `arg:"subcommand:user" help:"git checkout user"` Devel *FindCmd `arg:"subcommand:devel" help:"git checkout devel"` Master *FindCmd `arg:"subcommand:master" help:"git checkout master"` } type FindCmd struct { All bool `arg:"--all" help:"select every repo (the default)"` Mine bool `arg:"--mine" help:"your repos as defined in the forge config"` Favorites bool `arg:"--favorites" help:"your repos configured as favorites"` Private bool `arg:"--private" help:"your private repos from your .config/forge/"` Dirty bool `arg:"--dirty" help:"only use dirty git repos"` // ReadOnly bool `arg:"--readonly" help:"include read-only repos"` } func (args) Version() string { return "forge " + VERSION + " Built on " + BUILDTIME } func (a args) Description() string { return ` forge -- in the spirit of things like sourceforge This supports GO projects so far. It will work from ~/go/src or where your go.work file is. Since I mostly use ~/go/src, that has been tested more. Examples: forge # opens the GUI forge list # show every repo state forge dirty # check for dirty git repos forge pull # run 'git pull' in every repo forge checkout # switch git branches forge config add --private --path /opt/bob # add a private repo /opt/bob forge config add --directory --writable \ --gopath 'go.wit.com/user/bob' # directory contains r/w repos forge config add --private --writeable \ --gopath 'go.wit.com/user/bob/work' # a GO repo that can not be published ` } // prints help to STDERR func (args) doBashHelp() { name := "forge" if argv.BashAuto[1] != "''" { // if this is not blank, then the user has typed something return } if argv.BashAuto[0] != name { // if this is not the name of the command, the user already started doing something return } if argv.BashAuto[0] == name { me.pp.WriteHelp(os.Stderr) return } fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "hello world") fmt.Fprintln(os.Stderr, "") } func (args) doBashHelpDebug() { fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "hello world") var more string p0 := "0" + argv.BashAuto[0] p1 := "1" + argv.BashAuto[1] p2 := "2" + argv.BashAuto[2] if len(argv.BashAuto[1]) >= 0 { more = "more" } else { more = "less" } p1a := fmt.Sprintf("1a.%s.%+v.\n", argv.BashAuto[1], len(argv.BashAuto[1])) fmt.Fprintln(os.Stderr, "pull something else", argv.BashAuto, len(argv.BashAuto), p0, p1, p2, p1a, "end", more) fmt.Fprintln(os.Stderr, "") } func (args) doBashAuto() { name := "forge" argv.doBashHelp() switch argv.BashAuto[0] { case "checkout": fmt.Println("user devel master") case "config": fmt.Println("add fix list delete") case "list": fmt.Println("--all --mine --favorites --private") case "pull": fmt.Println("--all --mine --favorites --private") case "patch": fmt.Println("--list --submit --show") case "dirty": case "user": case "devel": case "master": default: if argv.BashAuto[0] == name { // list the subcommands here fmt.Println("--bash checkout config dirty hard-reset list patch pull rescan") } } os.Exit(0) } // complete -F forge --bash forge func (args) doBash() { name := "forge" fmt.Println("# add this in your bashrc:") fmt.Println("") fmt.Println("# todo: add this to go-arg as a 'hidden' go-arg option --bash") fmt.Println("#") fmt.Println("# todo: make this output work/parse with:") fmt.Println("# complete -C " + name + " --bash go") fmt.Println("") fmt.Println("_" + name + "_complete()") fmt.Println("{") fmt.Println(" # sets local to this func vars") fmt.Println(" local cur prev all") fmt.Println(" cur=${COMP_WORDS[COMP_CWORD]}") fmt.Println(" prev=${COMP_WORDS[COMP_CWORD-1]}") fmt.Println(" all=${COMP_WORDS[@]}") fmt.Println("") fmt.Println(" # this is where we generate the go-arg output") fmt.Println(" GOARGS=$(" + name + " --auto-complete $prev \\'$cur\\' $all)") fmt.Println("") fmt.Println(" # this compares the command line input from the user") fmt.Println(" # to whatever strings we output") fmt.Println(" COMPREPLY=( $(compgen -W \"$GOARGS\" -- $cur) ) # THIS WORKS") fmt.Println(" return 0") fmt.Println("}") fmt.Println("complete -F _" + name + "_complete " + name) fmt.Println("") fmt.Println("# copy and paste the above into your bash shell should work") os.Exit(0) }