summaryrefslogtreecommitdiff
path: root/theMagicOfAutocomplete.go
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-25 08:26:54 -0500
committerJeff Carr <[email protected]>2025-10-25 08:26:54 -0500
commitb95f2cab06e5de8fec71b0b991777f5d5cb1fa90 (patch)
tree821deba3f06e10e908a9f3990e434bf47b5da022 /theMagicOfAutocomplete.go
parent31e1d6afbe3ad9e39d0f0115b1ae3ddb0bb5de64 (diff)
isolate history handling
Diffstat (limited to 'theMagicOfAutocomplete.go')
-rw-r--r--theMagicOfAutocomplete.go163
1 files changed, 98 insertions, 65 deletions
diff --git a/theMagicOfAutocomplete.go b/theMagicOfAutocomplete.go
index 9c9010b..0e92af3 100644
--- a/theMagicOfAutocomplete.go
+++ b/theMagicOfAutocomplete.go
@@ -10,6 +10,7 @@ import (
"strings"
"time"
+ "github.com/google/uuid"
"go.wit.com/lib/cobol"
"go.wit.com/lib/config"
"go.wit.com/lib/env"
@@ -24,6 +25,7 @@ import (
func Autocomplete(dest any) *Argv {
me = new(AutoArgs) // todo: redo this
me.pb = new(Argv)
+ me.pb.Uuid = uuid.New().String()
// set the start time of the binary
now := time.Now()
@@ -42,28 +44,8 @@ func Autocomplete(dest any) *Argv {
// initializes the lib/env library
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
- me.all = NewArgvs()
- me.Err = config.CreateCacheDirPB(me.all, "argv", me.pb.AppInfo.APPNAME)
- if me.Err == nil {
- me.all.PrintHistory()
- } else {
- // there is no history.
- // todo: initialize the history file
- // todo: check if this is automatically done already
- //
- // ALWAYS KEEP THESE LINES AND THE panic()
- //
- // They are needed to debug autocomplete.
- //
- // This code is only executed when the user is hitting tab in the shell,
- // so this panic() is safe and can never be triggered by normal program execution.
- //
- me.debug = true
- me.pb.Stderr += fmt.Sprintf("config.CreateCacheDirPB() err(%v)\n", me.Err)
- me.pb.PrintStderr()
- panic("argvpb.Load() history file failed")
- }
+ // open the argv cache history file to figure out the timing
+ examineArgvHistory()
// try to register bash args for go-args
// arg.Register(&ArgvBash)
@@ -79,10 +61,10 @@ func Autocomplete(dest any) *Argv {
// user is trying to setup bash or zsh autocomplete
// --bash or --zsh is the first os.Args
if me.setupAuto {
- savePB()
// --bash or --zsh was passed. try to configure bash-completion
MakeAutocompleteFiles(me.pb.AppInfo.APPNAME)
// never forget to exit here or you will hate yourself and the choices you have made
+ savePB()
saveAndExit()
}
@@ -97,64 +79,41 @@ func Autocomplete(dest any) *Argv {
// do autocomplete and exit
savePB()
doAutocomplete()
- // todo: this never gets here. fix that
+ panic("blah")
+ savePB()
saveAndExit()
}
// not autocompleting. return to the application
// save the pb & history
- me.all.Clone(me.pb)
- errors.Join(me.Err, me.all.Save())
-
+ savePB()
// 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
+// doAutocomplete(): print what is needed to Stdout & Stderr, then exit
+//
// everything sent to STDOUT and STDERR matters past this point
+// any "junk" output, hidden fmt(), print() or log() statements are bad
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 me.all.IterAll() {
- me.last = found
+ if me.last.Fast {
+ // user is probably holding down the <TAB> key
+ me.debug = true
+ // me.fastcmd = me.pb.GetCmd()
+ if me.pb.GetCmd() != me.last.GetCmd() {
+ // do the smart something here
+ // probably debug == true && printStderr()
+ }
}
- dur := time.Since(me.last.Ctime.AsTime())
- me.pb.Duration = durationpb.New(dur)
if me.debug {
// dump debug info
- me.pb.PrintDebug()
- me.all.PrintHistory()
+ me.pb.PrintDebug(me.last.GetCmd())
+ // me.all.PrintHistory()
// me.pb.PrintStderr()
}
- // roll the autocomplete file
- 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)
- // }
- }
-
- // turn on debugging if duration < 200 milliseconds
- dur = me.pb.Duration.AsDuration()
- if dur < time.Millisecond*200 {
- me.debug = true
- me.pb.Fast = true
- // me.fastcmd = me.pb.GetCmd()
- if me.last.Fast {
- if me.pb.GetCmd() == me.last.GetCmd() {
- // do the smart something here
- }
- }
- }
-
flags := []string{}
for _, s := range me.pb.Real {
if s == "--autodebug" {
@@ -186,9 +145,10 @@ func doAutocomplete() {
me.pb.Debugf("DEBUG: real=(%v) found --gui", me.pb.Real)
me.pb.PrintStderr()
me.pb.SendString("andlabs gogui")
+ savePB()
saveAndExit()
} else {
- // me.pb.Debugf("DEBUG: NO MATCH last='%s' found key '%s' = %s", me.last, key, val)
+ // me.pb.Debugf("DEBUG: NO MATCH last='%s' found key '%s' = %s", last, key, val)
}
}
@@ -224,6 +184,7 @@ func doAutocomplete() {
if me.pb.HelpCounter < 3 {
me.pb.PrintStderr()
} else {
+ savePB()
saveAndExit()
}
} else {
@@ -249,16 +210,88 @@ func doAutocomplete() {
// if not, send "reset bash newline\n" to cause bash to redraw PS1 for the user
}
}
+ savePB()
saveAndExit()
}
func savePB() {
// save now. this is near the end probably
- me.all.Clone(me.pb)
+ me.all.Append(me.pb)
+ npb := new(Argv)
+ // npb.Uuid = uuid.New().String()
+ me.all.Append(npb)
errors.Join(me.Err, me.all.Save())
}
func saveAndExit() {
- savePB()
os.Exit(0)
}
+
+// sets me.last
+// computes me.pb.Duration
+func examineArgvHistory() {
+ me.all = NewArgvs()
+ // loads the argv autocomplete history file
+ me.Err = config.ForceCreateCacheDirPB(me.all, "argv", me.pb.AppInfo.APPNAME)
+ if me.Err != nil {
+ // there is no history.
+ // ALWAYS KEEP THESE LINES AND THE panic()
+ // They are needed to debug autocomplete.
+ //
+ // This code is only executed when the user is hitting tab in the shell,
+ // so this panic() is safe and can never be triggered by normal program execution.
+ //
+ me.debug = true
+ me.pb.Stderr += fmt.Sprintf("config.CreateCacheDirPB() err(%v)\n", me.Err)
+ me.pb.PrintStderr()
+ panic("argvpb.Load() history file failed")
+ }
+ me.all.PrintHistory("<?>")
+ if me.all.Len() > 0 {
+ last := me.all.Argvs[me.all.Len()-1]
+ me.pb.Debugf("DEBUG LAST %v", last)
+ }
+ // roll the autocomplete file
+ maxsize := 17
+ trim := 10
+ if me.all.Len() > maxsize {
+ me.pb.Debugf("DEBUG: trim() history is over 17 len=%d vs new=%d", me.all.Len(), me.all.Len()-trim)
+ me.pb.Debugf("DEBUG: trim() history is over 17 len=%d vs new=%d", me.all.Len(), me.all.Len()-trim)
+ me.pb.Debugf("DEBUG: trim() history is over 17 len=%d vs new=%d", me.all.Len(), me.all.Len()-trim)
+ me.all.Argvs = me.all.Argvs[me.all.Len()-trim:]
+ // newall.Autos = me.all.Autos[0:10]
+ }
+
+ counter := 0
+ for pb := range me.all.IterAll() {
+ counter += 1
+ if pb.Ctime == nil {
+ me.all.Delete(pb)
+ continue
+ }
+ hist := fmt.Sprintf("HISTNIL(%d)", counter)
+ pb.PrintDebugNew(hist, "jwc")
+ }
+ if me.all.Len() == 0 {
+ me.pb.PrintStderr()
+ // todo: make a blak entry here
+ panic("examineArgvHistory() couldn't find a valid last entry")
+ }
+ me.last = me.all.Argvs[me.all.Len()-1]
+
+ // compute the duration since the last time
+ dur := time.Since(me.last.Ctime.AsTime())
+ me.pb.Duration = durationpb.New(dur)
+
+ // turn on debugging if duration < 200 milliseconds
+ if me.pb.Duration.AsDuration() < time.Millisecond*200 {
+ me.debug = true
+ me.pb.Fast = true
+ // me.fastcmd = me.pb.GetCmd()
+ if me.last.Fast {
+ if me.pb.GetCmd() != me.last.GetCmd() {
+ // do the smart something here
+ }
+ }
+ }
+}