mains

package
v0.4.180 Latest Latest
Warning

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

Go to latest
Published: May 27, 2024 License: ISC Imports: 22 Imported by: 2

Documentation

Overview

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

Index

Constants

View Source
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"
)
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
)
View Source
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

func NewStdinReader(errorSink parl.ErrorSink1, isError *atomic.Bool) (stdinReader io.Reader)

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

func ProcessStart(pid int) (processStart time.Time, err error)

ProcessStart returns start time for process pid with second resolution

func ProcessStartTime added in v0.4.130

func ProcessStartTime() (createTime time.Time)

ProcessStartTime returns start time for process pid with second resolution

  • panic on troubles

func SystemUpSince added in v0.4.130

func SystemUpSince() (upSince time.Time, err error)

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

Jump to

Keyboard shortcuts

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