mains

package
v0.4.171 Latest Latest
Warning

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

Go to latest
Published: May 12, 2024 License: ISC Imports: 19 Imported by: 1

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

	Version = "version"
)
View Source
const (
	// if [Executable.OKtext] is assigned NoOK there ir no successful message on app exit
	NoOK = "-"
	// displays error location but not stack traces
	//	- second argument to [Executable.LongErrors]
	OutputErrorLocationTrue = true
	// always output error stack traces
	//	- second argument to [Executable.LongErrors]
	AlwaysStackTrace = true
)
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 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 <[email protected]> (http://www.haraldrudell.com)",
  License:     "All rights reserved",
  Arguments:   mains.NoArguments | mains.OneArgument,
}

func (*Executable) AddErr

func (x *Executable) AddErr(err error)

AddErr extended with immediate printing of first error

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) Exit

func (x *Executable) Exit(stausCode ...int)

Exit terminate from mains.err: exit 0 or echo to stderr and status code 1

  • Usually invoked for all app terminations
  • — either by defer ex.Recover(&err) at beginning fo main
  • — or rarely by direct invocation in program code
  • when invoked, errors are expected to be in ex.err from:
  • — ex.AddErr or
  • — ex.Recover
  • Exit does not return from invoking os.Exit

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 function to be used in main.main:

func main() {
  defer Recover()
  …

On panic, the function prints to stderr: "Unhandled panic invoked exe.Recover: stack:" followed by a stack trace. It then adds an error to mains.Executable and terminates the process with status code 1

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

Usage:

var err error
…
var keystrokes = NewKeystrokes()
defer keystrokes.Launch().CloseNow(&err)
for line := range keystrokes.Ch() {

func (*Keystrokes) Ch added in v0.4.130

func (k *Keystrokes) Ch() (ch <-chan 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

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(addError parl.AddError, 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

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 NewStdinReader added in v0.4.164

func NewStdinReader(addError parl.AddError, isError *atomic.Bool) (reader *StdinReader)

NewStdinReader returns a reader that closes on error

  • addError is an optional function receiving errors occurring in os.Stdin.Read. if missing, errors are printed to stderr
  • isError is an optional atomic set to true on first error

func (*StdinReader) Read added in v0.4.164

func (r *StdinReader) Read(p []byte) (n int, err error)

Read reads from standard input

  • on error, the reader closes
  • errors are submitted separately or printed to stderr and not returned
  • the only error returned is io.EOF
  • os.Stdin cannot be closed so a blocking read cannot be canceled
  • if another process closes stdin, on the next keypress an error will result
  • on process exit, Read may hang until enter is pressed

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