summaryrefslogtreecommitdiff
path: root/theMagicOfAutocomplete.go
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-25 01:24:29 -0500
committerJeff Carr <[email protected]>2025-10-25 01:24:29 -0500
commit27e0ddeaf127f561ca7fd5a8083ab52eba6ca2fb (patch)
tree432ed35a59d85782153993ccc4c8932171eac65a /theMagicOfAutocomplete.go
parentf7a1de79b1c115bddbf3d323a6fd7786d878efd9 (diff)
first stab at making an argv binary
Diffstat (limited to 'theMagicOfAutocomplete.go')
-rw-r--r--theMagicOfAutocomplete.go68
1 files changed, 38 insertions, 30 deletions
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
}