diff options
Diffstat (limited to 'theMagicOfAutocomplete.go')
| -rw-r--r-- | theMagicOfAutocomplete.go | 163 |
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 + } + } + } +} |
