Documentation
¶
Overview ¶
Package gotermstyle is the house terminal style for the Go command-line tools.
It is the Go counterpart to two things that already exist: pytermstyle (https://github.com/datapointchris/pytermstyle) for the Python tools, and formatting.sh for the bash ones. The README says where each lives. The parallel is the point — a Go screen, a Python screen and a bash screen sitting next to each other on PATH should be indistinguishable, which is a property no third-party styling library can provide, because each brings its own aesthetic.
Scope ¶
The palette, the section header, the help grammar, and the rules about when any of it is emitted at all. Beside them, tuitheme reads the colors every terminal UI on this module shares. Not domain logic, not a tool's own configuration, not anything a single tool could own instead.
The membership test: it belongs here only if two tools would otherwise write it identically *and* writing it differently would be visible on screen. Everything else stays in the tool. The package is named for the language rather than for a caller, because a style package named for one family of tools ends up holding the house style for all of them.
Dependencies ¶
None in this package, and that is a constraint rather than a coincidence. Terminal detection is os.Stat plus os.ModeCharDevice, not golang.org/x/term, so a tool importing this package builds no other module. The subpackage cobrahelp is the cobra frontend, kept apart so cobra reaches only a tool that imports it. The module's go.mod names cobra for cobrahelp, so an importer's module graph lists cobra while its build compiles none of it. The subpackage tuitheme reads the theme file a terminal UI draws from, and imports only the standard library.
The go line in this module's go.mod does become the importer's floor, and go get raises a lower one to match. This prints it:
go list -m -f '{{.GoVersion}}' github.com/datapointchris/gotermstyle@latest
Using it ¶
Resolve a Screen against the writer the output is going to, then render:
s := gotermstyle.New(cmd.OutOrStdout())
s.HelpHeader("lab", "Small experiments worth revisiting.")
s.HelpUsage("lab <verb>")
s.HelpSection("Commands")
s.HelpRow("lab list", "", "List every lab")
s.HelpRow("lab show", "<id>", "Show one lab")
s.HelpEnd()
HelpRow buffers rather than writing, so the flush sizes the description column from the longest row in the section. No call site passes a width or a color. Use HelpText rather than writing directly for prose between rows, so pending rows flush ahead of it.
For output that is not a help screen, Palette paints and Clip fits:
p := gotermstyle.PaletteFor(os.Stdout) fmt.Println(p.Cyan(name), p.Command(path))
Where the state lives, and why it differs from the Python ¶
pytermstyle and formatting.sh keep the buffered rows and the section counter in globals, which is affordable in a one-shot CLI and costs pytermstyle a reset helper its tests have to call. Go runs its tests in one process and its programs concurrently, so that state lives on a Screen here. The rendered screen is the same; only the state's owner differs.
The libraries that were considered and rejected, and why, are in the README.
Index ¶
- Constants
- func Clip(text string, used int) string
- func Columns() int
- func Enabled(w io.Writer) bool
- func SectionColor(title string, index int) string
- type Palette
- func (p Palette) Blue(text string) string
- func (p Palette) Bold(text string) string
- func (p Palette) Code(code string) string
- func (p Palette) Command(text string) string
- func (p Palette) Cyan(text string) string
- func (p Palette) Green(text string) string
- func (p Palette) Magenta(text string) string
- func (p Palette) On() bool
- func (p Palette) Paint(code, text string) string
- func (p Palette) Red(text string) string
- func (p Palette) White(text string) string
- func (p Palette) Yellow(text string) string
- type Screen
- func (s *Screen) Header(title string)
- func (s *Screen) HelpEnd()
- func (s *Screen) HelpHeader(name, tagline string)
- func (s *Screen) HelpRow(name, args, description string)
- func (s *Screen) HelpSection(title string)
- func (s *Screen) HelpText(lines ...string)
- func (s *Screen) HelpUsage(lines ...string)
- func (s *Screen) Palette() Palette
Constants ¶
const ( CodeCyan = "\033[0;96m" CodeYellow = "\033[0;93m" CodeGreen = "\033[0;92m" CodeRed = "\033[0;91m" CodeBlue = "\033[0;94m" CodeMagenta = "\033[0;95m" CodeWhite = "\033[0;97m" // CodeCommand is the one non-bright entry. A command you would type reads // differently from a name in a listing, and that difference is the point. CodeCommand = "\033[0;36m" CodeBold = "\033[1m" CodeReset = "\033[0m" )
The house palette, as the escape sequences themselves. These are the codes the bash library's colors.sh exports and pytermstyle interpolates, so a Go screen, a Python screen and a bash screen sitting next to each other on PATH are the same product.
They are terminal-palette codes rather than absolute RGB, which is why no color-profile degradation is needed: a 16-color terminal renders them correctly, and TERM=dumb is handled by the gate instead.
There is deliberately no dim. Its contrast is whatever the terminal theme makes it, and on many themes it is unreadable.
const Bar = "" /* 150-byte string literal not displayed */
Bar is the rule a header draws above and below its title.
const DefaultColumns = 80
DefaultColumns is the width assumed when nothing will say what it really is.
Variables ¶
This section is empty.
Functions ¶
func Clip ¶
Clip shortens text to fit the terminal alongside used other columns.
Callers pass the length of the uncolored surrounding text and color the result afterwards, so a clip can never land inside an escape sequence and leak a raw code onto the screen.
With no room to say anything the text is returned whole: truncating to a bare ellipsis loses more than it saves, and a row that overflows is more use than a row that says nothing.
Every character this clips around is assumed one column wide. That holds for the ↳ · … this family is built for and does not hold for CJK or emoji, which is the one thing a wide-rune library would buy and is a deliberate acceptance rather than an oversight.
func Columns ¶
func Columns() int
Columns is the terminal width. $COLUMNS is consulted first so a caller can override it and a test can set it, then the terminal itself, then DefaultColumns.
This is the order Python's shutil.get_terminal_size uses, which is what the counterpart library resolves through.
func Enabled ¶
Enabled reports whether escape sequences written to w will reach something that can render them.
NO_COLOR is the user saying they do not want color (no-color.org), so it wins outright. FORCE_COLOR answers a different question — "is this a terminal" — for a caller that knows the detection is wrong: a CI log that renders escapes, a pager invoked with -R, a test that needs the codes in order to assert on them. Preference beats detection, so NO_COLOR is first.
The terminal check is os.Stat plus os.ModeCharDevice rather than golang.org/x/term, which would cost this package the zero-dependency guarantee it is built around.
func SectionColor ¶
SectionColor is the code a section heading renders in, by name first and by position second. Matching is case-insensitive because a heading is written for a reader rather than for this lookup.
Types ¶
type Palette ¶
type Palette struct {
// contains filtered or unexported fields
}
Palette decides whether the codes above are emitted. Resolve it once, against the stream the output is going to, and pass it around — re-deciding per call site is how one screen ends up half-colored.
func NewPalette ¶
NewPalette returns a palette that emits color, or does not.
func PaletteFor ¶
PaletteFor resolves the gate against w. This is the constructor to reach for; NewPalette is for a caller that has already decided, and for tests.
func (Palette) Code ¶
Code returns the sequence when color is on and the empty string when it is not, so an interpolating caller can use the constants directly.
func (Palette) On ¶
On reports whether this palette emits color. A caller building a string by interpolation rather than through Paint needs to ask.
type Screen ¶
type Screen struct {
// contains filtered or unexported fields
}
Screen renders one help screen to one writer.
It carries the buffered rows and the section counter that pytermstyle and formatting.sh both keep in globals. Go runs its tests in one process and its programs concurrently, so a value is the same code without the reset helper those two need, and makes concurrent use a non-question. It draws the screen those two draw; only where the state lives differs.
func NewWith ¶
NewWith returns a Screen using a palette the caller has already resolved. A tool that renders to several streams resolves once and shares it; a test asserts on the codes by passing NewPalette(true).
func (*Screen) Header ¶
Header draws a boxed section header: rule, title, rule, blank line. This is the standalone header a command prints over its own output, not the one that opens a help screen.
func (*Screen) HelpEnd ¶
func (s *Screen) HelpEnd()
HelpEnd closes the screen and resets it for the next one.
func (*Screen) HelpHeader ¶
HelpHeader opens a help screen. The blank line leads rather than trails, which is what separates the screen from the command that asked for it.
func (*Screen) HelpRow ¶
HelpRow buffers one row. Nothing is written until the section ends, because the description column is sized from the longest row in the section and no call site should have to pass a width.
A row with an empty name is a continuation of the one above it.
func (*Screen) HelpSection ¶
HelpSection opens a section, flushing whatever rows the previous one buffered.
func (*Screen) HelpText ¶
HelpText prints prose between rows. It flushes first, so a line written after a row cannot appear above it.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package cobrahelp renders every help screen of a cobra command tree: what the command is, then every leaf beneath it, spelled from the screen's own command down to the leaf with its arguments, then its examples and flags.
|
Package cobrahelp renders every help screen of a cobra command tree: what the command is, then every leaf beneath it, spelled from the screen's own command down to the leaf with its arguments, then its examples and flags. |
|
Package tuitheme reads the TUI theme file: the colors and styles a terminal program draws its interface, markdown and code in, keyed by role.
|
Package tuitheme reads the TUI theme file: the colors and styles a terminal program draws its interface, markdown and code in, keyed by role. |