bonfire
Declarative console commands for the summer tool and application binaries, adapted to Cobra with typed input, prompts and styled output.
import "git.golem15.com/golem15/summercms/modules/bonfire"
Overview
bonfire is the console layer of SummerCMS. Plugins and framework modules describe commands as plain bonfire.Command values (name, flags, arguments and a run function), and bonfire.NewRoot turns a slice of them into a Cobra root command. Commands never touch Cobra directly: they read arguments through bonfire.Input and write through bonfire.Output, which also provides tables, spinners, progress bars and interactive prompts. It is the counterpart of WinterCMS's artisan console commands (registerConsoleCommand and Laravel's Illuminate\Console\Command output helpers).
Features
- Command values with a description, positional arguments (
bonfire.Arg) and string flags (bonfire.Flag), collected from plugins or the tool itself. - Command name validation: plugin commands must use the
namespace:verbform (for exampleblog:import);build,dev,serveandmigrateare the only bare names accepted. Invalid names makebonfire.NewRootfail withbonfire.ErrCommandName. - Usage strings and argument-count checks derived from the declared arguments (
<name>for required,[name]for optional). - Scalar flags, bare flags (
bonfire.Flag.Bare, so--forcealone storestrue) and ordered repeatable flags (bonfire.Flag.Repeatable, read back throughbonfire.Input.Flags). - Styled status lines:
bonfire.Output.Info,bonfire.Output.Success,bonfire.Output.Warningandbonfire.Output.Error(the last one writes to the error stream). - Widgets: box-drawn tables (
bonfire.Output.Table), a spinner around a function (bonfire.Output.Spinner) and a progress bar (bonfire.Output.Progress); both fall back to plain lines when output is not a terminal. - Prompts:
bonfire.Output.Ask,bonfire.Output.Confirm,bonfire.Output.Choiceandbonfire.Output.Secret, which reads a hidden value on a terminal. Prompts return their defaults when input ends, andbonfire.Output.Confirmreturns its default without asking when the session is not interactive. - Injectable streams (
bonfire.NewRootIO,bonfire.NewOutput) so commands can be tested against buffers.
Usage
package main
import (
"context"
"os"
"git.golem15.com/golem15/summercms/modules/bonfire"
)
func main() {
importPosts := bonfire.Command{
Name: "blog:import",
Description: "Import posts from a feed",
Args: []bonfire.Arg{{Name: "url", Description: "Feed URL", Required: true}},
Flags: []bonfire.Flag{
{Name: "dry-run", Description: "Report without writing", Bare: true},
{Name: "tag", Description: "Tag to apply (repeatable)", Repeatable: true},
},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
url, _ := in.Argument("url")
_, dryRun := in.Flag("dry-run")
return out.Spinner("Importing "+url, func() error {
out.Table([]string{"Tag"}, [][]string{{"news"}})
if dryRun {
out.Warning("dry run: nothing written")
}
return nil
})
},
}
root, err := bonfire.NewRoot("acme", []bonfire.Command{importPosts}, os.Stdout)
if err != nil {
os.Exit(1)
}
if err := root.Execute(); err != nil {
os.Exit(1)
}
}
API reference
| Identifier | Description |
|---|---|
bonfire.Command |
A console command: name, description, flags, arguments and the bonfire.Command.Run function. |
bonfire.Flag |
A string flag; bonfire.Flag.Bare allows the flag without a value, bonfire.Flag.Repeatable makes it an ordered multi-value flag. |
bonfire.Arg |
A positional argument with a name, description and required marker. |
bonfire.Input |
Parsed view handed to bonfire.Command.Run: bonfire.Input.Args, bonfire.Input.Argument, bonfire.Input.Flag and bonfire.Input.Flags. |
bonfire.Output |
Injected console: printing, status lines, tables, spinner, progress bar and prompts. |
bonfire.Progress |
A progress bar advanced from inside bonfire.Output.Progress. |
bonfire.NewRoot |
Builds the Cobra root command for a binary from a slice of commands, using the process stdin. |
bonfire.NewRootIO |
bonfire.NewRoot with injected stdin, stdout and stderr. |
bonfire.NewOutput |
Builds a bonfire.Output over the given streams, applying the terminal and color policy. |
bonfire.ErrCommandName |
Returned when a plugin command name is not in namespace:verb form. |
Configuration
bonfire reads no config keys. Output color follows these environment variables:
| Variable | Effect |
|---|---|
NO_COLOR |
Any non-empty value disables color. |
TERM |
The value dumb disables color. |
FORCE_COLOR |
Any non-empty value enables color even when output is not a terminal (ignored when color is disabled by NO_COLOR or TERM). |
Without these variables, color is enabled only when stdout is a terminal.
Dependencies
- SummerCMS modules: none.
- Third-party:
github.com/spf13/cobra,golang.org/x/term. - Standard library:
bufio,context,errors,fmt,io,os,strconv,strings,sync,time,unicode/utf8.
Testing
go test ./modules/bonfire/...
The tests use in-memory streams and need no external services.