mains

package
v0.4.192 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2025 License: ISC Imports: 17 Imported by: 2

Documentation

Overview

Package mains contains functions for implementing a command-line utility or a service.

Index

Constants

View Source
const (
	// as second argument to [BaseOptionData], indicates that yaml options -yamlFile -yamlKey should not be present
	YamlNo YamlOption = false
	// indicates silent: no banner. Must be first option on command-line ‘-silent’
	SilentString = "-" + silentOption
	// name of version option
	Version = "version"
)
View Source
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
)
View Source
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
)

Variables

This section is empty.

Functions

func BaseOptionData

func BaseOptionData(program string, yaml ...YamlOption) (optionData []pflags.OptionData)

BaseOptionData returns basic options for mains

  • program: used to generate help text
  • yaml: YamlNo means no yaml options
  • -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)

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

  • -yamlFile -yamlKey -verbose -debug -silent -version -no-yaml
var BaseOptions BaseOptionsType

BaseOptions is the value that holds mains’ effective option values

  • -yamlFile -yamlKey -verbose -debug -silent -version -no-yaml

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(fieldp ...*Keystrokes) (keystrokes *Keystrokes)

NewKeystrokes returns an object reading lines from standard input

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 ...SilentType) (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])

StringSource returns a possibly closing unbound slice sending lines from the keyboard on each return press

  • closing-channel wait mechanic
  • Ch sends strings with return character removed
  • the channel closes upon:
  • Keystrokes.CloseNow or
  • os.Stdin closing or
  • — thread runtime error

type SilentType added in v0.4.191

type SilentType bool

optional flag for no stdin-cose echo SilentClose

const (
	// do not echo to standard error on [os.Stdin] closing
	// optional argument to [Keystrokes.Launch]
	SilentClose SilentType = true
)

type YamlOption

type YamlOption bool

type for second argument to BaseOptionData YamlNo

Directories

Path Synopsis
Package malib provides functions supporting mains package.
Package malib provides functions supporting mains package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL