Documentation ¶
Overview ¶
Package mains contains functions for implementing a service or command-line utility
Index ¶
- Constants
- func BaseOptionData(program string, yaml YamlOption) (optionData []pflags.OptionData)
- func MinimalRecovery(errp *error)
- func NewStdinReader(errorSink parl.ErrorSink1, isError *atomic.Bool) (stdinReader io.Reader)
- func ProcessStart(pid int) (processStart time.Time, err error)
- func ProcessStartTime() (createTime time.Time)
- func SystemUpSince() (upSince time.Time, err error)
- type ArgumentSpec
- type BaseOptionsType
- type Executable
- func (x *Executable) AddError(err error)
- func (x *Executable) ConfigureLog() (ex1 *Executable)
- func (x *Executable) EarlyPanic(errp ...*error)
- func (x *Executable) EndErrors()
- func (x *Executable) Init() (ex2 *Executable)
- func (x *Executable) LongErrors(isLongErrors bool, isErrorLocation bool) *Executable
- func (x *Executable) PrintBannerAndParseOptions(optionsList []pflags.OptionData) (ex1 *Executable)
- func (x *Executable) Recover(errp ...*error)
- func (x *Executable) SetStatusCode(statusCode *int)
- type Keystrokes
- type StdinReader
- type YamlOption
Constants ¶
const ( // as second argument to [BaseOptionData], indicates that yaml options -yamlFile -yamlKey should not be present YamlNo YamlOption = false // as second argument to [BaseOptionData], indicates that yaml options -yamlFile -yamlKey should be present YamlYes YamlOption = true // indicates silent: no banner. Must be first option on command-line ‘-silent’ SilentString = "-" + silentOption // name of version option Version = "version" )
const ( // if [Executable.OKtext] is assigned NoOK there ir no successful message on app exit NoOK = "-" // displays error location for errors printed without stack trace // - second argument to [Executable.LongErrors] OutputErrorLocationTrue = true // error location is not appended to errors printed without stack trace // - second argument to [Executable.LongErrors] NoErrorLocationTrue = false // always output error stack traces // - first argument to [Executable.LongErrors] AlwaysStackTrace = true // stack traces are not output for errors // - stack traces are printed for panic // - first argument to [Executable.LongErrors] NoStackTrace = false )
const ( // NoArguments besides switches, zero trailing arguments is allowed NoArguments = 1 << iota // OneArgument besides switches, exactly one trailing arguments is allowed OneArgument // ManyArguments besides switches, one or more trailing arguments is allowed ManyArguments )
const ( // do not echo to standard error on [os.Stdin] closing // optional argument to [Keystrokes.Launch] SilentClose = true )
Variables ¶
This section is empty.
Functions ¶
func BaseOptionData ¶
func BaseOptionData(program string, yaml YamlOption) (optionData []pflags.OptionData)
BaseOptionData returns basic options for mains
- verbose debug silent version
- if yaml == YamlYes: yamlFile yamlKey
func MinimalRecovery ¶ added in v0.4.130
func MinimalRecovery(errp *error)
MinimalRecovery handles error process exit for the main function
- purpose is to avoid a silent zero status-code exit on error and to print exactly when the process exited
- panics are not recovered
- on success: *errp == nil:
- – a timestamped success message is printed to stderr
- — the function returns
- on error: *errp != nil:
- — if error is caused by panic, error is printed with stack trace
- — other errors are printed as a one-liner with code-location
- — os.Exit is invoked with status code 1
Usage:
main() { var err error defer mains.MinimalRecovery(&err)
func NewStdinReader ¶ added in v0.4.164
NewStdinReader returns a error-free reader of standard input that closes on error
- errorSink receives any errors returned by os.Stdin.Read or runtime panic in this method. If missing, errors are printed to stderr
- isError is an optional atomic set to true on first error
- StdinReader.Read returns bytes read from standard input until it closes. The only error returned is io.EOF
func ProcessStart ¶ added in v0.4.130
ProcessStart returns start time for process pid with second resolution
func ProcessStartTime ¶ added in v0.4.130
ProcessStartTime returns start time for process pid with second resolution
- panic on troubles
func SystemUpSince ¶ added in v0.4.130
SystemUpSince returns boot time second resolution
Types ¶
type ArgumentSpec ¶
type ArgumentSpec uint32
ArgumentSpec bitfield for 0, 1, many arguments following command-line switches
type BaseOptionsType ¶
type BaseOptionsType = struct {
YamlFile, YamlKey, Verbosity string
Debug, Silent, Version, DoYaml bool
}
BaseOptionsType is the type that holds mains’ effective option values
var BaseOptions BaseOptionsType
BaseOptions is the value that holds mains’ effective option values
type Executable ¶
type Executable struct { Program string // “gonet” Version string // “0.0.1” Comment string // [ banner text after program and version] “options parsing” changes in last version Description string // [Description part of usage] “configures firewall and routing” Copyright string // “© 2020…” License string // “ISC License” OKtext string // “Completed successfully” ArgumentsUsage string // usage help text for arguments after options Arguments ArgumentSpec // eg. mains.NoArguments Launch time.Time // process start time LaunchString string // Launch as printable rfc 3339 time string Host string // short hostname, ie. no dots “mymac” ArgCount int // number of post-options strings during parse Arg string // if one post-options string and that is allowed, this is the string Args []string // any post-options strings if allowed // errors are printed with stack traces, associated values and errors // - panics are always printed long // - if errors long or more than 1 error, the first error is repeated last as a one-liner IsLongErrors bool // adds a code location to errors if not IsLongErrors IsErrorLocation bool // contains filtered or unexported fields }
Executable constant strings that describes an executable advisable static values include Program Version Comment Description Copyright License Arguments like:
var ex = mains.Executable{ Program: "getip", Version: "0.0.1", Comment: "first version", Description: "finds ip address for hostname", Copyright: "© 2020-present Harald Rudell <harald.rudell@gmail.com> (http://www.haraldrudell.com)", License: "All rights reserved", Arguments: mains.NoArguments | mains.OneArgument, }
func (*Executable) AddError ¶ added in v0.4.178
func (x *Executable) AddError(err error)
AddError extended with immediate printing of first error
- if err is the first error, it is immediately printed
- subsequent errors are appended to x.err
- err nil: ignored
func (*Executable) ConfigureLog ¶
func (x *Executable) ConfigureLog() (ex1 *Executable)
ConfigureLog configures the default log such as parl.Log parl.Out parl.D for silent, debug and regExp. Settings come from BaseOptions.Silent and BaseOptions.Debug.
ConfigureLog supports functional chaining like:
exe.Init(). … ConfigureLog(). ApplyYaml(…)
func (*Executable) EarlyPanic ¶ added in v0.4.173
func (x *Executable) EarlyPanic(errp ...*error)
EarlyPanic is a deferred function that recovers panic prior to all other deferred functions
- EarlyPanic ensures that a panic is displayed immediately and that the panic is stored as the first occurring error
- the first deferred function should be Executable.Recover
- the last deferred function should be Executable.EarlyPanic
- EarlyPanic avoids confusion from other deferred functions quietly hanging or storing a first error that is actually subsequent to the panic
func (*Executable) EndErrors ¶ added in v0.4.178
func (x *Executable) EndErrors()
a subt making Executable implement parl.ErrorSink
func (*Executable) Init ¶
func (x *Executable) Init() (ex2 *Executable)
Init initializes a created mains.Executable value
- the value should have relevant fields populates such as exeuctable name and more
- — Program Version Comment Copyright License Arguments
- populates launch time and sets silence if first os.Args argument is “-silent.”
- Init supports function chaining like:
typical code:
ex.Init(). PrintBannerAndParseOptions(optionData). LongErrors(options.Debug, options.Verbosity != ""). ConfigureLog() applyYaml(options.YamlFile, options.YamlKey, applyYaml, optionData) …
func (*Executable) LongErrors ¶
func (x *Executable) LongErrors(isLongErrors bool, isErrorLocation bool) *Executable
LongErrors sets if errors are printed with stack trace and values. LongErrors supports functional chaining:
exe.Init(). … LongErrors(options.Debug, options.Verbosity != ""). ConfigureLog()…
isLongErrors prints full stack traces, related errors and error data in string lists and string maps.
isErrorLocation appends the innermost location to the error message when isLongErrors is not set:
error-message at error116.(*csTypeName).FuncName-chainstring_test.go:26
func (*Executable) PrintBannerAndParseOptions ¶
func (x *Executable) PrintBannerAndParseOptions(optionsList []pflags.OptionData) (ex1 *Executable)
PrintBannerAndParseOptions prints greeting like:
parl 0.1.0 parlca https server/client udp server
It then parses options described by []OptionData stroing the values at OptionData.P. If options fail to parse, a proper message is printed to stderr and the process exits with status code 2. PrintBannerAndParseOptions supports functional chaining like:
exe.Init(). PrintBannerAndParseOptions(…). LongErrors(…
Options and yaml is configured likeso:
var options = &struct { noStdin bool *mains.BaseOptionsType }{BaseOptionsType: &mains.BaseOptions} var optionData = append(mains.BaseOptionData(exe.Program, mains.YamlYes), []mains.OptionData{ {P: &options.noStdin, Name: "no-stdin", Value: false, Usage: "Service: do not use standard input", Y: mains.NewYamlValue(&y, &y.NoStdin)}, }...) type YamlData struct { NoStdin bool // nostdin: true } var y YamlData
func (*Executable) Recover ¶
func (x *Executable) Recover(errp ...*error)
Recover terminates the process, typically invoked as the first deferred function in main.main
- errp: optional pointer that may point to a non-nil error
- Recover does not return, instead it invokes os.Exit
- Recover recovers any ongoing panic using recover()
- successful exit is:
- — no ongoing panic
- — no non-nil errors pointed to by errp
- — no errors previously stored by Executable.AddError or Executable.EarlyPanic
- — no non-zero status code previously stored by Executable.SetStatusCode
- on successful exit, a timestamped success message is printed followed by exit status zero:
- — “gtee completed successfully at 240524 17:26:50-07”
- on failure exit:
- — non-panic errors are printed as one-liners with code location
- — panics are printed with stack trace and error chain
- — the last printed line is a timestamped exit message:
- — “240524 21:32:08-07 gtee: exit status 1”
- — exit status code is any non-zero status code provided to Executable.SetStatusCode or 1
Usage:
func main() { var err error defer Recover(&err) …
func (*Executable) SetStatusCode ¶ added in v0.4.179
func (x *Executable) SetStatusCode(statusCode *int)
SetStatusCode allos to set the status code to use on exit
- deferrable, thread-safe
type Keystrokes ¶
type Keystrokes struct {
// contains filtered or unexported fields
}
Keystrokes reads line-wise from standard input
- os.File.Read from os.Stdin cannot be aborted because Stdin cannot be closed
- therefore, on process exit or Keystrokes.CloseNow, keystrokesThread thread is left blocked in Read
- —
- -verbose='mains...Keystrokes|mains.keystrokesThread' “github.com/haraldrudell/parl/mains.(*Keystrokes)”
- this object is released on process exit. Remaining items due to stdin cannot be closed are:
- the stdin unbound channel
- optional addError
- those items along with [KeyStrokesThread] and StdinReader are released on process exit or next keypress
func NewKeystrokes ¶ added in v0.4.130
func NewKeystrokes() (keystrokes *Keystrokes)
NewKeystrokes returns an object reading lines from standard input
- Keystrokes.Launch launches a thread reading from os.Stdin
- [Keystrokes.Ch] provides a channel sending strings on each return key-press
- Keystrokes.CloseNow closes the channel discarding buffered characters
- Ch also closes on Stdin closing or thread runtime error
Usage:
var err error … var keystrokes = NewKeystrokes() defer keystrokes.Launch().CloseNow(&err) for line := range keystrokes.Ch() {
func (*Keystrokes) CloseNow ¶ added in v0.4.130
func (k *Keystrokes) CloseNow(errp *error)
CloseNow closes the string-sending channel discarding any pending characters
func (*Keystrokes) Launch ¶ added in v0.4.130
func (k *Keystrokes) Launch(errorSink parl.ErrorSink1, silent ...bool) (keystrokes *Keystrokes)
Launch starts reading stdin for keystrokes
- can only be invoked once per process or panic
- supports functional chaining
- silent SilentClose does not echo anything on os.Stdin closing
- addError if present receives errors from os.Stdin.Read
func (*Keystrokes) StringSource ¶ added in v0.4.180
func (k *Keystrokes) StringSource() (stringSource parl.ClosableSource1[string])
Ch returns a possibly closing receive-only channel sending lines from the keyboard on each return press
- Ch sends strings with return character removed
- the channel closes upon:
- — Keystrokes.CloseNow or
- — os.Stdin closing or
- — thread runtime error
type StdinReader ¶ added in v0.4.164
type StdinReader struct {
// contains filtered or unexported fields
}
StdinReader is a reader wrapping the unclosable os.Stdin.Read
- on error, the error is sent to addError and EOF is returned
func (*StdinReader) Read ¶ added in v0.4.164
func (r *StdinReader) Read(p []byte) (n int, err error)
Read reads from standard input
- on os.Stdin.Read error or panic, the reader closes
- n: the number of bytes read
- err: Read never returns any other error than io.EOF
- — on any error or panic, Read returns io.EOF
- errors and runtime panics are sent to the errorSink or printed to stderr
- os.Stdin cannot be closed so a blocking StdinReader.Read cannot be canceled
- if the stdin pipe is closed by another process, Read keeps blocking but returns on the next keypress. Then, an error os.ErrClosed is sent to the errorsink and io.EOF is returned
- on process exit, Read is unblocked as stdin is closed
type YamlOption ¶
type YamlOption bool
type for second argument to BaseOptionData
- mains.YamlNo mains.YamlYes