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  | 
