summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-16 10:15:13 -0500
committerJeff Carr <[email protected]>2025-10-16 10:15:13 -0500
commit58083f07bc5b3dc3c93843110746c32492022a12 (patch)
tree53693291a87a4c243739c24c1f0132665d5d43fe
parentd05afb455673a5397ecfa41f7ea36c75d0629566 (diff)
finally start to move to a pure protobuf herev0.0.38
-rw-r--r--errors.go92
-rw-r--r--theMagicOfAutocomplete.go64
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