Documentation
¶
Overview ¶
Package cmdkit is what every workflow command is built from, beneath the command tree internal/cli spells: the scriptable contract — the artifact on a checked stdout, what is said about it on stderr, --yes and --dry-run around a write, a mistake in the call as a usage error — and the connection to where a command runs, the environment it reads the process through, the flags every command shares and the prompt that asks the person at the terminal. It imports no command, and not the web server: the root hands it the port --web serves on unless told otherwise.
Index ¶
- Constants
- Variables
- func AddJSONFlag(cmd *cobra.Command, asJSON *bool, help string)
- func CheckPort(cmd *cobra.Command, web bool, port int) error
- func CompleteAssignedIssues(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
- func ConfigHome(cmd *cobra.Command) string
- func Confirm(prompt Prompt, question string) (bool, error)
- func DryRunRequested(cmd *cobra.Command) bool
- func EncodeJSON(out io.Writer, value any) error
- func Examples(lines ...string) string
- func ForgeNoun(kind forge.Kind) string
- func FromWorkingDir(cmd *cobra.Command, path string) (string, error)
- func HandOver(cmd *cobra.Command, env Environment) error
- func IsAny(err error, targets ...error) bool
- func LiveLook(ui config.UI) console.Look
- func LoadFromEnvironment(cmd *cobra.Command) (config.Config, error)
- func MarkMisuse(root *cobra.Command)
- func MessagingNotConfigured() error
- func NotesOf(cmd *cobra.Command) console.Notes
- func OnlineDoer(cfg config.Config) httpx.Doer
- func PostingIn(settings config.Messaging, channel string) (config.Messaging, error)
- func RequestLogFor(cmd *cobra.Command) (*wiring.RequestLog, func(), error)
- func RequestTimeout(cfg config.Config) time.Duration
- func ServicesUnreachable() []error
- func TerminalOut(cmd *cobra.Command) io.Writer
- func VoiceOf(root *cobra.Command, getenv func(string) string) console.Options
- func Waiting(cmd *cobra.Command, prompt Prompt, look console.Look, ...) error
- func WorkingDir(cmd *cobra.Command) (string, error)
- type CheckedOutput
- type Connection
- type Environment
- type Output
- type Prompt
- type RootFlags
- type WriteOptions
- type WritePrompt
Constants ¶
const ConfirmationHelp = "go ahead without the confirmation"
ConfirmationHelp is --yes's help on a write that asks one question.
Variables ¶
var ErrMessagingNotConfigured = errors.New("no messaging transport is configured")
ErrMessagingNotConfigured refuses announcing when no messaging transport is set up.
var ErrNoTerminal = errors.New("no terminal to answer on")
ErrNoTerminal reports a question asked with nothing to answer it: stdin was closed, or piped and already read to its end.
var ErrOutputUnwritten = errors.New("the output could not be written")
ErrOutputUnwritten reports an artifact that could not be written to stdout — a pipe whose reader has gone, a full disk. It fails the command however its work went, since a script reading stdout would otherwise take an artifact cut short, or none, for a run that succeeded.
var ErrUsage = errors.New("invalid argument")
ErrUsage marks a mistake in how a command was called — a flag or an argument it does not take — as distinct from a command that ran and failed. Its words are cobra's own for a flag value it refuses, so a value this tree refuses reads the same.
Functions ¶
func AddJSONFlag ¶
AddJSONFlag declares --json, or -j, on cmd, held in asJSON, with help that says what it prints: the one way every command's data is asked for.
func CheckPort ¶
CheckPort refuses, as a mistake in the call, --port without --web, where nothing listens on it, and a port no listener can take.
func CompleteAssignedIssues ¶
func CompleteAssignedIssues(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
CompleteAssignedIssues completes an issue command's key with the keys of the issues assigned to you, for `workflow branch <tab>` and every command that names an issue first. Past the key it offers nothing and asks nothing, and a tracker that cannot be reached offers nothing rather than an error.
func ConfigHome ¶
ConfigHome is the home directory a configuration falls back to, or "" for none. A machine without a home directory is unusual but not a failure: the working directory alone is still a valid place to find a configuration.
func Confirm ¶
Confirm asks a yes/no question, defaulting to no, so a bare enter is the safe answer. With nothing to read an answer from, it says so rather than passing on a bare end-of-file.
func DryRunRequested ¶
DryRunRequested reports whether --dry-run was given, before or after the command's name. The root declares it for every command, so it is always there to read.
func EncodeJSON ¶
EncodeJSON writes value as indented JSON: the one encoder every command's data goes out through, so each one's output is shaped and worded the same.
func Examples ¶
Examples is a command's Example text: one invocation a line, indented as cobra indents its other sections, so --help and the reference page show what scripting.md shows.
func ForgeNoun ¶
ForgeNoun names a forge mid-sentence: by its own name, or as the forge when the remote does not say which.
func FromWorkingDir ¶
FromWorkingDir is path, or where it leads from the directory the command cmd runs in was run from when it is relative to that, as a shell would read it there.
func HandOver ¶
func HandOver(cmd *cobra.Command, env Environment) error
HandOver puts env in the context of the command cmd runs, which every command under the root reads it from: the root does this before any command's own work starts, once it has refused --quiet beside --verbose. The working directory is read at the first ask and answered from then on as it was then. The context also carries itself as the lifetime of what the command detaches from its asker (a Slack directory read, a token's refresh), so a signal ends that too.
func LiveLook ¶
LiveLook is how a live line is drawn under ui: in ASCII when ui.ascii asks, and its mark still when ui.motion reduces motion.
func LoadFromEnvironment ¶
LoadFromEnvironment loads the configuration that applies where cmd runs, searching up from its working directory to the repository root and then the home directory. A missing or unreadable file, or a working directory that cannot be named, is reported through the error.
func MarkMisuse ¶
MarkMisuse makes every command in the tree report its flag and argument errors as usage errors: a flag it does not know, a wrong argument count, and an unknown command, which is an argument to a command that takes none.
func MessagingNotConfigured ¶
func MessagingNotConfigured() error
MessagingNotConfigured refuses to announce with no messaging transport set up, saying how to set one up.
func NotesOf ¶
NotesOf is what the command cmd runs says on its stderr, as the root's flags ask, colored as the variables of the environment it runs in allow.
func OnlineDoer ¶
OnlineDoer is the transport the tracker and messaging checks travel over: the redirect-refusing client, bounded by RequestTimeout.
func PostingIn ¶
PostingIn is settings posting in channel, as --channel asks, in place of messaging.channel; a blank channel leaves them as they are. A webhook cannot post anywhere but where it is bound, so asking it to is refused as usage. With no messaging set up the channel is set all the same, for the command's own refusal to say what to set up.
func RequestLogFor ¶
func RequestLogFor(cmd *cobra.Command) (*wiring.RequestLog, func(), error)
RequestLogFor opens the request log --request-log names and, under --verbose, says each outline as a debug line too, or keeps none when neither asks for one, warning on the command's stderr at close when the file was not fully written. The root declares both flags for every command, so they are always there to read.
func RequestTimeout ¶
RequestTimeout is the configured request timeout, or the default when none is set: it bounds each of doctor's --online checks, so a hung service does not hang doctor, and how long a quit waits for the writes in flight.
func ServicesUnreachable ¶
func ServicesUnreachable() []error
ServicesUnreachable are the clients' errors for a service that never answered the request itself: it could not be reached, answered only to say wait, answered with a redirect the client refused to follow, or took too long to finish its answer. A script may try again later. The exit family adds doctor.ErrUnreachable, which says the same of a check doctor made.
func TerminalOut ¶
TerminalOut is the stdout cmd writes to as the stream it was handed, without the check over it: the interface draws on it itself, and Bubble Tea knows a terminal only as the file it is.
func VoiceOf ¶
VoiceOf is how the notes of a run of root are said, as its flags ask: in the --log-format given, leaving the notes out under --quiet and adding debug lines under --verbose, colored as getenv's variables allow.
func Waiting ¶
func Waiting( cmd *cobra.Command, prompt Prompt, look console.Look, wait func(out Output, live console.Wait) error, ) error
Waiting runs wait, a slow command's reads, keeping its live line on stderr, drawn as look asks, while it does when stderr is a terminal a person watches, and keeping none in a pipe or a log, where only what it says prints. Its notes are said above the line, and its artifact goes to stdout, unless stdout is the terminal too.
Types ¶
type CheckedOutput ¶
type CheckedOutput struct {
// Out is the stdout the writes go to.
Out io.Writer
// Err is why the first write that failed could not be made, an
// ErrOutputUnwritten, or nil while none has.
Err error
}
CheckedOutput is stdout, remembering the first write it could not make and refusing every write after it, so every command's artifact — prose written line by line as much as JSON — fails the command when it went nowhere.
func (*CheckedOutput) Failed ¶
func (o *CheckedOutput) Failed(err error) error
Failed is a command's outcome err, joined with why its output could not be written when it could not and err does not already say so.
func (*CheckedOutput) Stream ¶
func (o *CheckedOutput) Stream() io.Writer
Stream is the checked stdout as a command writes it: over a file, the terminal it may be, so fang can tell whether to color its help.
type Connection ¶
type Connection struct {
// Config is the configuration in effect.
Config config.Config
// LoadErr is why the configuration did not load — config.ErrNotFound
// when there is no file — or nil.
LoadErr error
// Where is the repository the command runs in, or the directory when
// there is none.
Where wiring.Workspace
// Deps are the seams over the configuration and the repository.
Deps tui.Deps
// Controls are the wiring's own: finding tokens ahead, and applying
// settings the web's Settings saves.
Controls wiring.Controls
// RequestLog records each request, or is nil; a switch wires the next
// directory to the same log.
RequestLog *wiring.RequestLog
// CloseLog closes the request log, which the caller defers.
CloseLog func()
// Keychain keeps a token typed into the first run's form in the OS
// keychain; nil where none is wired, or under a dry run.
Keychain func(ctx context.Context, service, secret string) error
// Process is what the wiring read of the process: the home, variables,
// store and programs the command runs with.
Process wiring.Environment
}
Connection is a command wired to where it runs: the configuration in effect and, when it did not load, why; the repository; the seams over both, and what finds their tokens ahead of first use, which only the interface and the web server call; and the close of the request log, which the caller defers.
func Connect ¶
func Connect(cmd *cobra.Command) (Connection, error)
Connect wires a command to its working directory, recording each request in the --request-log file when one is named. A configuration file that is there but cannot be read is refused rather than replaced by the defaults, which would act on settings nobody chose; no file at all is not an error.
func ConnectAt ¶
func ConnectAt(ctx context.Context, cmd *cobra.Command, dir string, requestLog *wiring.RequestLog) Connection
ConnectAt wires the directory at dir, which reads its own configuration, recording each request in requestLog unless it is nil, and finding where dir is under ctx. Under --dry-run its store is only read, and only when it is already on disk. It opens nothing, so its close is a no-op.
func ConnectLeniently ¶
func ConnectLeniently(cmd *cobra.Command) (Connection, error)
ConnectLeniently is Connect keeping a configuration that did not load, for the interface and the web server, which each show the user why.
func (Connection) UnreadConfiguration ¶
func (c Connection) UnreadConfiguration() error
UnreadConfiguration is why the configuration file in effect could not be read, or nil when it was read or there is none.
func (Connection) WithSetup ¶
func (c Connection) WithSetup( cmd *cobra.Command, keychain func(ctx context.Context, service, secret string) error, ) Connection
WithSetup is the connection offering a first run where it works, with the token kept through keychain, which a dry run never stores in.
type Environment ¶
type Environment struct {
// WorkingDir is the directory the command was run from, or why the
// operating system cannot name it. A command reads it once, whatever
// reads it after: its sections, its request log and each directory it
// names relatively are all read from the one directory.
WorkingDir func() (string, error)
// Chdir makes dir the process's working directory, so whatever a session
// switched there runs — an editor, a hook — starts there.
Chdir func(dir string) error
// Process is what the wiring reads of the process.
Process wiring.Environment
}
Environment is what a command reads of the process it runs in: the directory it was run from and how to move the process to another, and what the wiring reads — the home directory, the environment's variables, the store's directory and where a program is found. cli.Execute's caller builds it from the operating system, so no command reads the process's own, and a test hands each run one of its own.
func EnvironmentOf ¶
func EnvironmentOf(cmd *cobra.Command) Environment
EnvironmentOf is the Environment the command cmd runs in, or, when none was handed over, one that answers every question with errNoEnvironment.
func NoEnvironment ¶
func NoEnvironment() Environment
NoEnvironment is the environment of a command that has none: it names no directory, home or variable, finds no program, and moves nowhere.
type Output ¶
type Output struct {
// Artifact is where the artifact goes: stdout, or the notes' own stream
// for an aside.
Artifact io.Writer
// Notes are what the command says about it, on stderr.
Notes console.Notes
}
Output is where a command writes: the artifact — the preview, the JSON, what it created — on stdout, and what it says about it — a notice, a dry-run line, a warning — through the notes on stderr, so a script capturing stdout gets data alone.
type Prompt ¶
type Prompt struct {
// Line prints prompt and reads one visible line, for an address or a choice.
Line func(prompt string) (string, error)
// Secret prints prompt and reads one line without echoing it, for a token;
// with no terminal to read it from, it answers io.EOF.
Secret func(prompt string) (string, error)
// StoreSecret saves secret in the OS keychain under the item service names,
// under ctx. It is nil where storing is not wired for the platform, and the
// guided flow then keeps the token in the file.
StoreSecret func(ctx context.Context, service, secret string) error
// Input is standard input, read to its end for a comment's text, as `git
// commit -F -` reads a message, so a script never quotes it. It shares Line's
// reader, so nothing read for one is lost to the other. Nil reads as empty.
Input io.Reader
// IsTerminal reports whether a stream is a terminal, so a slow command keeps
// a live line on stderr only where a person is watching it, never in a
// pipe or a log, and prints its artifact beside the line only where stdout
// is no terminal. Nil reads every stream as no terminal.
IsTerminal func(stream io.Writer) bool
}
Prompt is how a command asks the person at the terminal: reading an answer, for the guided init and every scriptable write's yes/no question; reading standard input whole, for a comment's text; keeping a secret in the operating system's keychain; and composing a note in the editor. Each is a seam so a test can drive the conversation without a terminal, a real keychain or an editor. The main package wires the two terminal reads, which no test can make, and takes the keychain and the editor from their own packages.
A zero Prompt is enough for a command that never asks anything — the doctor, or the reference generator that only walks the tree.
type RootFlags ¶
type RootFlags struct {
// DryRun is --dry-run: show what would change, and change nothing.
DryRun bool
// Web is --web: serve the web app rather than open the interface.
Web bool
// Port is --port, the port --web serves on.
Port int
}
RootFlags are the root's flags: a dry run, which every command reads, and --web and --port, which choose what bare workflow opens.
func (*RootFlags) Declare ¶
Declare declares the flags on root: --dry-run, --request-log and how stderr is said once, for every command, so a script passes them before the command's name or after it, and each command reads them back by name; --web and --port, serving on defaultPort unless given, on the root alone. --log, the request log's old name, is kept hidden only to refuse it with the new one.
type WriteOptions ¶
type WriteOptions struct {
// DryRun is a run that changes nothing.
DryRun bool
// Yes skips the confirmation.
Yes bool
}
WriteOptions are the flags every scriptable write shares: a dry run that changes nothing, and a yes that skips the confirmation for unattended use.
func (*WriteOptions) AddFlags ¶
func (o *WriteOptions) AddFlags(cmd *cobra.Command, yesHelp string)
AddFlags declares --yes, or -y, on a scriptable write command, with help that says what it answers, and has it read the root's --dry-run — one flag every command inherits — before it runs.
func (*WriteOptions) Proceed ¶
func (o *WriteOptions) Proceed(notes console.Notes, confirm func(string) (bool, error), say WritePrompt) (bool, error)
Proceed reports whether to go ahead with a write, the preview already printed. A dry run says what it would do and stops; --yes goes ahead without asking; otherwise it asks, and a declined answer says so and stops. What it says is commentary, written to notes.
type WritePrompt ¶
type WritePrompt struct {
// Question is what the confirmation asks.
Question string
// DryRun is what a dry run says the write would do.
DryRun string
// Declined is what the write prints when the answer is no.
Declined string
}
WritePrompt is what a scriptable write says around its confirmation: the question it asks, what a dry run would do, and what it prints when declined.