diff options
| author | Jeff Carr <[email protected]> | 2025-10-25 01:24:29 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-10-25 01:24:29 -0500 |
| commit | 27e0ddeaf127f561ca7fd5a8083ab52eba6ca2fb (patch) | |
| tree | 432ed35a59d85782153993ccc4c8932171eac65a | |
| parent | f7a1de79b1c115bddbf3d323a6fd7786d878efd9 (diff) | |
first stab at making an argv binary
| -rw-r--r-- | argv.Print.go | 10 | ||||
| -rw-r--r-- | argv.SendStrings.go | 8 | ||||
| -rw-r--r-- | argv.parseOsArgs.go | 2 | ||||
| -rw-r--r-- | argv.proto | 53 | ||||
| -rw-r--r-- | gui.go | 1 | ||||
| -rw-r--r-- | makeAutocompleteFiles.bash.go | 1 | ||||
| -rw-r--r-- | structs.go | 3 | ||||
| -rw-r--r-- | theMagicOfAutocomplete.go | 68 | ||||
| -rw-r--r-- | verifyApplication.go | 10 |
9 files changed, 93 insertions, 63 deletions
diff --git a/argv.Print.go b/argv.Print.go index 7cfbcff..ceab8a6 100644 --- a/argv.Print.go +++ b/argv.Print.go @@ -67,7 +67,17 @@ func (pb *Argv) PrintStderr() { } } +func (pb *Argv) PrintStdout() { + fmt.Fprintf(os.Stdout, "%s\n", pb.Stdout) +} + func (pb *Argv) PrintStderrExit() { pb.PrintStderr() + pb.PrintStdout() + os.Exit(0) +} + +func (pb *Argv) PrintStdoutExit() { + pb.PrintStdout() os.Exit(0) } diff --git a/argv.SendStrings.go b/argv.SendStrings.go index b523120..c890608 100644 --- a/argv.SendStrings.go +++ b/argv.SendStrings.go @@ -50,14 +50,14 @@ func (pb *Argv) SubCommand(cmd ...string) { } partial := strings.Trim(pb.Partial, "'") if me.debug { - // last working line: me.writeHelpForAutocomplete(os.Stderr, os.Stdout, partial, cmd...) + // last working line: me.writeHelpForAutocomplete(Stderr, Stdout, partial, cmd...) me.writeHelpForAutocompleteDebugFunc(partial, cmd...) - // me.pp.GetUsageForSubcommand(os.Stdout, os.Stderr, partial, cmd) - // me.pp.GetUsageForSubcommand(os.Stdout, nil, partial, cmd) + // me.pp.GetUsageForSubcommand(Stdout, Stderr, partial, cmd) + // me.pp.GetUsageForSubcommand(Stdout, nil, partial, cmd) } else { // last working: f, _ := os.OpenFile("/tmp/outlook", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - // last working: me.writeHelpForAutocomplete(f, os.Stdout, partial, cmd...) + // last working: me.writeHelpForAutocomplete(f, Stdout, partial, cmd...) me.writeHelpForAutocompleteFunc(partial, cmd...) } os.Exit(0) diff --git a/argv.parseOsArgs.go b/argv.parseOsArgs.go index bf73744..89750c9 100644 --- a/argv.parseOsArgs.go +++ b/argv.parseOsArgs.go @@ -47,7 +47,7 @@ func (pb *Argv) getSubSubCmd() string { func (pb *Argv) parseOsArgs() { // this shouldn't really happen. OS/POSIX error? if len(os.Args) == 0 { - // fmt.Fprintf(os.Stderr, "what OS is this?\n") + // fmt.Fprintf(Stderr, "what OS is this?\n") return } @@ -8,28 +8,41 @@ import "google/protobuf/timestamp.proto"; // Import the well-known type for Time import "google/protobuf/duration.proto"; // for duration message App { - string APPNAME = 1; - string VERSION = 2; - string BUILDTIME = 3; + string APPNAME = 1; + string VERSION = 2; + string BUILDTIME = 3; } -message Argv { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex` - google.protobuf.Timestamp ctime = 1; // when the user tried this autocomplete - google.protobuf.Duration duration = 2; // time since the last autocomplete - App appInfo = 3; - repeated string args = 4; // a copy of os.Args - repeated string real = 5; // what will really be sent to the application - string subcmd = 6; // the subcommand being processed. For "git pull <tab>", cmd would be "pull" - string partial = 7; // if the user has only partially inputed something - repeated string goargs = 8; // what to send to alex flint's go-args for help - bool fast = 9; // is autocomplete running quickly? - string stdout = 10; // all output is loaded here before being sent to the shell - string stderr = 11; // all output is loaded here before being sent to the shell +message StructEntry { + string structName = 2; // 'Force', 'Verbose', 'SortCmd' + string structType = 3; // 'string', 'int', '[]string', '*FindCmd' + string defaultVal = 4; // "true" + string helpText = 5; // "This will help you" + string matchText = 6; // "--help-me } -message Argvs { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex` - string uuid = 1; // `autogenpb:uuid:1e6e765c-0c77-4c81-a622-0d819bfcce9a` - string version = 2; // `autogenpb:version:v0.0.3` - repeated Argv argvs = 3; - string filename = 4; // `autogenpb:save` -- this enables autogenerated pb.Load() and pb.Save() +message ArgTree { + repeated StructEntry Structs = 1; // a tree of the argv structs in argv.go + string mainArgvName = 2; // name to use in main.go +} + +message Argv { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex` + google.protobuf.Timestamp ctime = 1; // when the user tried this autocomplete + google.protobuf.Duration duration = 2; // time since the last autocomplete + App appInfo = 3; + repeated string args = 4; // a copy of os.Args + repeated string real = 5; // what will really be sent to the application + string subcmd = 6; // the subcommand being processed. For "git pull <tab>", cmd would be "pull" + string partial = 7; // if the user has only partially inputed something + repeated string goargs = 8; // what to send to alex flint's go-args for help + bool fast = 9; // is autocomplete running quickly? + string stdout = 10; // all output is loaded here before being sent to the shell + string stderr = 11; // all output is loaded here before being sent to the shell +} + +message Argvs { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:nomutex` + string uuid = 1; // `autogenpb:uuid:1e6e765c-0c77-4c81-a622-0d819bfcce9a` + string version = 2; // `autogenpb:version:v0.0.3` + repeated Argv argvs = 3; + string filename = 4; // `autogenpb:save` -- this enables autogenerated pb.Load() and pb.Save() } @@ -36,5 +36,4 @@ func workInProgress() { fmt.Println(cobol.Time(s) + ": go.wit.com/apps/forge/argv.go") fmt.Println(cobol.Time(s) + ": go.wit.com/apps/forge/main.go") fmt.Println(cobol.Time(s) + ":") - // panic("deprecated") } diff --git a/makeAutocompleteFiles.bash.go b/makeAutocompleteFiles.bash.go index f0cc953..259d795 100644 --- a/makeAutocompleteFiles.bash.go +++ b/makeAutocompleteFiles.bash.go @@ -23,7 +23,6 @@ func MakeBashCompleteFiles(argname string) { filename := filepath.Join(homeDir, ".local/share/bash-completion/completions", argname) if config.Exists(filename) { fmt.Fprintln(os.Stderr, "# file already exists", filename) - // os.Exit(0) } basedir, _ := filepath.Split(filename) if !config.IsDir(basedir) { @@ -6,6 +6,7 @@ var me *AutoArgs // this is a work in progress type AutoArgs struct { pb *Argv // the protobuf for the current process + all *Argvs // the protobuf for the current process last *Argv // the pb from the last time the user tried autocomplete id int // should be unique Argv func([]string) // the function for shell autocomplete @@ -22,7 +23,7 @@ type AutoArgs struct { buildtime func() (string, string) // some examples autoFunc func(*Argv) // also a function for autocomplete guiFunc func() error // enables Gui functions - err error // store any errors from argv + Err error // store any errors from argv debug bool // is dubugging on? setupAuto bool // do shell autocomplete setup isAuto bool // try to do autocomplete diff --git a/theMagicOfAutocomplete.go b/theMagicOfAutocomplete.go index b48d1b9..5b5370b 100644 --- a/theMagicOfAutocomplete.go +++ b/theMagicOfAutocomplete.go @@ -17,8 +17,11 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) +// This function behaves oddly. It works in several different ways. It can: +// - Initialize a protobuf and returns it to the application +// - Help a user generate shell completion support & os.Exit +// - figures out what to print to Stdout & Stderr and then does os.Exit() func Autocomplete(dest any) *Argv { - var err error me = new(AutoArgs) // todo: redo this me.pb = new(Argv) @@ -27,7 +30,7 @@ func Autocomplete(dest any) *Argv { me.pb.Ctime = timestamppb.New(now) // makes sure the application has the - // needed functions defined, otherwise panics + // needed functions defined, otherwise dies verifyApplication(dest) // gets APPNAME, BUILDTIME and VERSION from the application @@ -40,10 +43,10 @@ func Autocomplete(dest any) *Argv { env.Init(me.pb.AppInfo.APPNAME, me.pb.AppInfo.VERSION, cobol.Time(me.pb.AppInfo.BUILDTIME), me.pb.Real, GoodExit, BadExit) // loads the argv autocomplete history file - all := NewArgvs() + me.all = NewArgvs() fullname := config.MakeCacheFilename("argv", me.pb.AppInfo.APPNAME) - err = config.LoadFromFilename(all, fullname) - if err != nil { + me.Err = config.LoadFromFilename(me.all, fullname) + if me.Err != nil { // there is no history. // todo: initialize the history file // todo: check if this is automatically done already @@ -76,25 +79,31 @@ func Autocomplete(dest any) *Argv { } } - // not autocompleting. return go-arg & the application - if !me.isAuto { - // save the pb & history - all.Clone(me.pb) - errors.Join(err, all.Save()) - - // me.pp = arg.MustParse(dest) - me.err = me.mustParseFunc() - return me.pb + if me.isAuto { + // do autocomplete and exit + doAutocomplete() + os.Exit(0) } - // EVERYTHING PAST HERE IS FOR AUTOCOMPLETE - // everything sent to STDOUT and STDERR matters past this point + // not autocompleting. return to the application + // save the pb & history + me.all.Clone(me.pb) + errors.Join(me.Err, me.all.Save()) + + // me.pp = arg.MustParse(dest) + me.Err = errors.Join(me.Err, me.mustParseFunc()) + return me.pb +} +// prints what is needed to Stdout & Stderr, then exits +// EVERYTHING PAST HERE IS FOR AUTOCOMPLETE +// everything sent to STDOUT and STDERR matters past this point +func doAutocomplete() { // set the duration since the last auto complete // find the last entry. this is dumb way to do it me.last = new(Argv) me.last.Ctime = timestamppb.New(time.Now().Add(-time.Second)) - for found := range all.IterAll() { + for found := range me.all.IterAll() { me.last = found } dur := time.Since(me.last.Ctime.AsTime()) @@ -103,15 +112,15 @@ func Autocomplete(dest any) *Argv { if me.debug { // dump debug info me.pb.PrintDebug() - all.PrintHistory() + me.all.PrintHistory() } // roll the autocomplete file - if all.Len() > 15 { - me.pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", all.Len(), all.Len()-90) - all.Argvs = all.Argvs[all.Len()-10:] - // newall.Autos = all.Autos[0:10] - // for _, found := range all.Autos[0:10] { + if me.all.Len() > 15 { + me.pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", me.all.Len(), me.all.Len()-90) + me.all.Argvs = me.all.Argvs[me.all.Len()-10:] + // newall.Autos = me.all.Autos[0:10] + // for _, found := range me.all.Autos[0:10] { // newall.Append(found) // } } @@ -180,15 +189,15 @@ func Autocomplete(dest any) *Argv { if len(flags) == 0 { // error is normal if there are no command line args } else { - if err != nil { + if me.Err != nil { // users has command line arguments that won't parse with go-args - me.pb.Debugf("DEBUG: Parse error: %v flags%v", err, flags) + me.pb.Debugf("DEBUG: Parse error: %v flags%v", me.Err, flags) } } // save now. this is near the end probably - all.Clone(me.pb) - errors.Join(err, all.Save()) + me.all.Clone(me.pb) + errors.Join(me.Err, me.all.Save()) if me.pb.Fast { if me.last.Fast { @@ -197,10 +206,10 @@ func Autocomplete(dest any) *Argv { } else { // this means the user is pressing tab. no longer doing stderr if me.pb.GetCmd() == "" { - // me.pp.WriteHelp(os.Stderr) + // me.pp.WriteHelp(Stderr) me.writeHelpFunc() } else { - // me.pp.WriteHelpForSubcommand(os.Stderr, me.pb.Cmd) + // me.pp.WriteHelpForSubcommand(Stderr, me.pb.Cmd) me.writeHelpForSubcommandFunc(me.pb.GetCmd()) } } @@ -218,5 +227,4 @@ func Autocomplete(dest any) *Argv { // if not, send "reset bash newline\n" to cause bash to redraw PS1 for the user } os.Exit(0) - return nil } diff --git a/verifyApplication.go b/verifyApplication.go index 9eaed32..7c79cd9 100644 --- a/verifyApplication.go +++ b/verifyApplication.go @@ -164,7 +164,7 @@ func helpWriteHelpForSubcommand() { fmt.Println("") fmt.Println("// add this funcgion: this will print the help") fmt.Println("func (args) WriteHelpForSubcommand() error {") - fmt.Println(" me.pp.WriteHelpForSubcommand(os.Stderr, me.argv.Cmd)") + fmt.Println(" me.pp.WriteHelpForSubcommand(Stderr, me.argv.Cmd)") fmt.Println(" return nil") fmt.Println("}") fmt.Println("") @@ -176,7 +176,7 @@ func helpWriteHelp() { fmt.Println("") fmt.Println("// add this funcgion: this will print the help") fmt.Println("func (args) WriteHelp() error {") - fmt.Println(" me.pp.WriteHelp(os.Stderr)") + fmt.Println(" me.pp.WriteHelp(Stderr)") fmt.Println(" return nil") fmt.Println("}") fmt.Println("") @@ -188,7 +188,7 @@ func helpWriteHelpForAutocompleteDebug() { fmt.Println("") fmt.Println("// this will print the help for the subcmd") fmt.Println("func (args) WriteHelpForAutocompleteDebug(part string, subcmd ...string) error {") - fmt.Println(" return argvpp.WriteHelpForAutocomplete(f, os.Stdout, part, subcmd...)") + fmt.Println(" return argvpp.WriteHelpForAutocomplete(f, Stdout, part, subcmd...)") fmt.Println("}") fmt.Println("") fmt.Println("cp ~/go/src/go.wit.com/apps/forge/argv.template.go .") @@ -197,12 +197,12 @@ func helpWriteHelpForAutocompleteDebug() { } // func (p *Parser) WriteHelpForAutocomplete(stderr io.Writer, stdout io.Writer, partial string, subcommand ...string) error { -// me.pp.WriteHelpForAutocomplete(os.Stderr, os.Stdout, partial, cmd...) +// me.pp.WriteHelpForAutocomplete(Stderr, Stdout, partial, cmd...) func helpWriteHelpForAutocomplete() { fmt.Println("") fmt.Println("// this will print the help for the subcmd") fmt.Println("func (args) WriteHelpForAutocomplete(part string, subcmd ...string) error {") - fmt.Println(" return argvpp.WriteHelpForAutocomplete(os.Stderr, os.Stdout, part, subcmd...)") + fmt.Println(" return argvpp.WriteHelpForAutocomplete(Stderr, Stdout, part, subcmd...)") fmt.Println("}") fmt.Println("") fmt.Println("Just copy the argv.template.go file from forge") |
