diff options
| author | Jeff Carr <[email protected]> | 2025-10-16 10:15:13 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-10-16 10:15:13 -0500 |
| commit | 58083f07bc5b3dc3c93843110746c32492022a12 (patch) | |
| tree | 53693291a87a4c243739c24c1f0132665d5d43fe | |
| parent | d05afb455673a5397ecfa41f7ea36c75d0629566 (diff) | |
finally start to move to a pure protobuf herev0.0.38
| -rw-r--r-- | errors.go | 92 | ||||
| -rw-r--r-- | theMagicOfAutocomplete.go | 64 |
2 files changed, 124 insertions, 32 deletions
diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..7da8395 --- /dev/null +++ b/errors.go @@ -0,0 +1,92 @@ +package prep + +// Gemini's excellent at this sorta research. Not much else though + +// This file defines a set of conventional exit codes for command-line applications, +// based on the BSD `sysexits.h` standard and common GNU/Linux practices. +// Using these constants makes the program's exit behavior clear and consistent. + +// ExitCode represents a program's exit status code. +type ExitCode int + +const ( + // --- Standard Success/Failure --- + + // ExitSuccess indicates that the program completed its task without errors. + ExitSuccess ExitCode = 0 + + // ExitFailure is a generic, catch-all code for "something went wrong." + // It should be used if no other more specific code applies. + ExitFailure ExitCode = 1 + + // --- Errors based on BSD sysexits.h --- + + // ExitUsage indicates that the user provided invalid command-line arguments or flags. + // (Standard: EX_USAGE) + ExitUsage ExitCode = 64 + + // ExitDataErr indicates that the input data was incorrect or malformed. + // (e.g., a corrupt configuration file). + // (Standard: EX_DATAERR) + ExitDataErr ExitCode = 65 + + // ExitNoInput indicates that an input file was not found or could not be read. + // (Standard: EX_NOINPUT) + ExitNoInput ExitCode = 66 + + // ExitNoUser indicates that a specified user did not exist. + // (Standard: EX_NOUSER) + ExitNoUser ExitCode = 67 + + // ExitNoHost indicates that a specified host did not exist. + // (Standard: EX_NOHOST) + ExitNoHost ExitCode = 68 + + // ExitUnavailable indicates that a required service is unavailable. + // (Standard: EX_UNAVAILABLE) + ExitUnavailable ExitCode = 69 + + // ExitSoftware indicates an internal software error. This is for unexpected + // conditions and bugs ("this should never happen"). + // (Standard: EX_SOFTWARE) + ExitSoftware ExitCode = 70 + + // ExitOSErr indicates an operating system error, such as a failed system call. + // (e.g., fork failed, couldn't create a directory). + // (Standard: EX_OSERR) + ExitOSErr ExitCode = 71 + + // ExitOSFile indicates a critical OS file is missing or corrupt. + // (e.g., /etc/passwd). + // (Standard: EX_OSFILE) + ExitOSFile ExitCode = 72 + + // ExitCantCreat indicates that a user-specified output file could not be created. + // (Standard: EX_CANTCREAT) + ExitCantCreat ExitCode = 73 + + // ExitIOErr indicates an error occurred during an I/O operation. + // (Standard: EX_IOERR) + ExitIOErr ExitCode = 74 + + // ExitTempFail indicates a temporary failure. The user is invited to retry. + // (Standard: EX_TEMPFAIL) + ExitTempFail ExitCode = 75 + + // ExitProtocol indicates a protocol error during network communication. + // (Standard: EX_PROTOCOL) + ExitProtocol ExitCode = 76 + + // ExitNoPerm indicates that the user does not have sufficient permissions. + // This is for filesystem permissions, not for authentication issues. + // (Standard: EX_NOPERM) + ExitNoPerm ExitCode = 77 + + // ExitConfig indicates that something is wrong in a configuration file. + // (Standard: EX_CONFIG) + ExitConfig ExitCode = 78 +) + +// Note: Exit codes 126, 127, and >128 are reserved for the shell to indicate +// specific execution failures (command not executable, command not found, or +// termination by a signal) and should not be used by applications. diff --git a/theMagicOfAutocomplete.go b/theMagicOfAutocomplete.go index 648e28f..7fddb00 100644 --- a/theMagicOfAutocomplete.go +++ b/theMagicOfAutocomplete.go @@ -29,13 +29,13 @@ func Autocomplete(dest any) *Auto { } // parses os.Args into a protobuf - pb := parseArgv(me.ARGNAME) + me.pb = parseArgv(me.ARGNAME) // the argv history all := NewAutos() // initializes the application config file - config.Init(me.ARGNAME, me.VERSION, me.BUILDTIME, pb.Argv) + config.Init(me.ARGNAME, me.VERSION, me.BUILDTIME, me.pb.Argv) // loads the autocomplete history file err := config.LoadCache(all, "argv", me.ARGNAME) // @@ -46,7 +46,7 @@ func Autocomplete(dest any) *Auto { // set the start time of the binary now := time.Now() - pb.Ctime = timestamppb.New(now) + me.pb.Ctime = timestamppb.New(now) // try to register bash args for go-args arg.Register(&argBash) @@ -54,7 +54,7 @@ func Autocomplete(dest any) *Auto { // user is trying to setup bash or zsh autocomplete // --bash or --zsh is the first os.Args - if pb.SetupAuto { + if me.pb.SetupAuto { // --bash was passed. try to configure bash-completion MakeAutocompleteFiles(me.ARGNAME) // never forget to run this our you will hate yourself and the choices you have made @@ -62,14 +62,14 @@ func Autocomplete(dest any) *Auto { } // not autocompleting. return go-arg & the application - if !pb.IsAuto { + if !me.pb.IsAuto { // save the pb & history - all.Clone(pb) + all.Clone(me.pb) errors.Join(err, all.Save()) me.pp = arg.MustParse(dest) me.err = err - return pb + return me.pb } // EVERYTHING PAST HERE IS FOR AUTOCOMPLETE @@ -83,17 +83,17 @@ func Autocomplete(dest any) *Auto { last = found } dur := time.Since(last.Ctime.AsTime()) - pb.Duration = durationpb.New(dur) + me.pb.Duration = durationpb.New(dur) - if pb.Debug { + if me.pb.Debug { // dump debug info - pb.PrintDebug() + me.pb.PrintDebug() all.PrintHistory() } // roll the autocomplete file if all.Len() > 15 { - pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", all.Len(), all.Len()-90) + me.pb.Debugf("DEBUG: trim() history is over 100 len=%d vs new=%d", all.Len(), all.Len()-90) all.Autos = all.Autos[all.Len()-10:] // newall.Autos = all.Autos[0:10] // for _, found := range all.Autos[0:10] { @@ -101,23 +101,23 @@ func Autocomplete(dest any) *Auto { // } } - pb.Debugf("WRITE DEBUG: write PB='%s' len(pb)=%d config.Save().err=%v", all.Filename, all.Len(), err) + me.pb.Debugf("WRITE DEBUG: write PB='%s' len(pb)=%d config.Save().err=%v", all.Filename, all.Len(), err) // turn on debugging if duration < 200 milliseconds - dur = pb.Duration.AsDuration() + dur = me.pb.Duration.AsDuration() if dur < time.Millisecond*200 { - pb.Debug = true - pb.Fast = true - pb.Fastcmd = pb.Cmd + me.pb.Debug = true + me.pb.Fast = true + me.pb.Fastcmd = me.pb.Cmd if last.Fast { - if pb.Fastcmd == last.Fastcmd { + if me.pb.Fastcmd == last.Fastcmd { // do the smart something here } } } flags := []string{} - for _, s := range pb.Argv { + for _, s := range me.pb.Argv { if s == "--autodebug" { continue } @@ -135,49 +135,49 @@ func Autocomplete(dest any) *Auto { } else { if err != nil { // users has command line arguments that won't parse with go-args - pb.Debugf("DEBUG: Parse error: %v flags%v", err, flags) + me.pb.Debugf("DEBUG: Parse error: %v flags%v", err, flags) } } if me.pp == nil { - pb.Debugf("DEBUG: me.pp == nil after ParseFlags()") + me.pb.Debugf("DEBUG: me.pp == nil after ParseFlags()") } else { - // pb.Debugf("DEBUG: me.pp is ok after ParseFlags()") + // me.pb.Debugf("DEBUG: me.pp is ok after ParseFlags()") } // save now. this is near the end probably - all.Clone(pb) + all.Clone(me.pb) errors.Join(err, all.Save()) // this is a work in progress - if pb.Last == "--gui" { - pb.Debugf("DEBUG: last=%s found --gui", pb.Last) - pb.Autocomplete2("andlabs gogui") + if me.pb.Last == "--gui" { + me.pb.Debugf("DEBUG: last=%s found --gui", me.pb.Last) + me.pb.Autocomplete2("andlabs gogui") os.Exit(0) } else { - // pb.Debugf("DEBUG: NO MATCH last='%s' found key '%s' = %s", pb.Last, key, val) + // me.pb.Debugf("DEBUG: NO MATCH last='%s' found key '%s' = %s", me.pb.Last, key, val) } - if pb.Fast { + if me.pb.Fast { if last.Fast { os.Exit(0) } else { // this means the user is pressing tab. no longer doing stderr - if pb.Cmd == "" { + if me.pb.Cmd == "" { me.pp.WriteHelp(os.Stderr) } else { - me.pp.WriteHelpForSubcommand(os.Stderr, pb.Cmd) + me.pp.WriteHelpForSubcommand(os.Stderr, me.pb.Cmd) } } } else { } if me.autoFunc == nil { - pb.SubCommand(pb.Argv...) + me.pb.SubCommand(me.pb.Argv...) } else { - me.autoFunc(pb) // run the autocomplete function the user made for their application + me.autoFunc(me.pb) // run the autocomplete function the user made for their application } - if pb.Debug { + if me.pb.Debug { // TODO: // check here to see if there was any completion text sent // if not, send "reset bash newline\n" to cause bash to redraw PS1 for the user |
