Documentation
¶
Overview ¶
Package teahelp provides a Bubble Tea v2 help visor model for displaying keyboard shortcuts in a paginated overlay. It composes the pure rendering utilities from teautils (HelpVisorStyle, FormatKeyDisplay, GetSortedCategories) into a stateful tea.Model with toggle, pagination, and configurable key bindings.
Stability ¶
This package is provisional as of v0.3.0. The public API may change in minor releases until promoted to stable.
Index ¶
- Variables
- func AppendErr(errs []error, err error) []error
- func CombineErrs(errs []error) error
- func ErrValue[T any](err error, key string) (T, bool)
- func Errors(err error) []error
- func FindErr[T error](err error) (out T, ok bool)
- func MsgErr(msg any) error
- func NewErr(parts ...any) error
- func WithErr(parts ...any) error
- type ClosedMsg
- type ErrKV
- func AnyKV(key string, value any) ErrKV
- func AppendKV(kvs []ErrKV, parts ...any) []ErrKV
- func BoolKV(key string, value bool) ErrKV
- func ErrMeta(err error) []ErrKV
- func ErrorKV(key string, value error) ErrKV
- func Float64KV(key string, value float64) ErrKV
- func Int64KV(key string, value int64) ErrKV
- func IntKV(key string, value int) ErrKV
- func StringKV(key, value string) ErrKV
- type HelpVisorKeyMap
- type HelpVisorModel
- func (m HelpVisorModel) Close() HelpVisorModel
- func (m HelpVisorModel) Init() tea.Cmd
- func (m HelpVisorModel) IsOpen() bool
- func (m HelpVisorModel) Open(keysByCategory map[string][]teautils.KeyMeta) HelpVisorModel
- func (m HelpVisorModel) Page() int
- func (m HelpVisorModel) SetSize(width, height int) HelpVisorModel
- func (m HelpVisorModel) TotalPages() int
- func (m HelpVisorModel) Update(msg tea.Msg) (HelpVisorModel, tea.Cmd)
- func (m HelpVisorModel) View() (view tea.View)
- func (m HelpVisorModel) WithContentStyle(style teautils.HelpVisorStyle) HelpVisorModel
- func (m HelpVisorModel) WithKeys(keys HelpVisorKeyMap) HelpVisorModel
- func (m HelpVisorModel) WithStyles(styles HelpVisorStyles) HelpVisorModel
- func (m HelpVisorModel) WithTheme(theme teautils.Theme) HelpVisorModel
- type HelpVisorStyles
- type IsDotErrEntry
Constants ¶
This section is empty.
Variables ¶
var ( ErrMissingSentinel = errors.New("missing required sentinel error") ErrTrailingKey = errors.New("trailing key without value") ErrMisplacedError = errors.New("error in wrong position") ErrInvalidArgumentType = errors.New("invalid argument type") ErrOddKeyValueCount = errors.New("odd number of key-value arguments") ErrCrossPackageError = errors.New("error from different doterr package") )
Sentinel errors for validation failures
var (
ErrHelpVisor = errors.New("help visor error")
)
Functions ¶
func CombineErrs ¶
CombineErrs bundles a slice of errors into a single composite error that unwraps to its members. Order is preserved and nils are skipped. Returns nil for an empty/fully-nil slice, or the sole error when there is exactly one.
func ErrValue ¶
ErrValue extracts a single metadata value by key with type safety. Returns the value and true if found and the value is of type T. Returns the zero value of T and false if not found or type mismatch.
Example:
status, ok := ErrValue[int](err, "http_status")
if ok {
fmt.Printf("Status: %d\n", status)
}
name, ok := ErrValue[string](err, "parameter_name")
func Errors ¶
Errors returns the errors stored on a doterr entry. If err is a doterr entry, returns its errors. If err is a joined error (has Unwrap() []error), scans immediate children left-to-right and returns errors from the first doterr entry found. Otherwise returns nil. The returned slice preserves insertion order and is a copy.
Note: These errors may be sentinel errors (e.g., ErrModal), custom error types (e.g., *rfc9457.Error), or any other error type stored in the entry.
func FindErr ¶
FindErr walks an error tree (including errors.Join trees) and returns the first match for target (via errors.As).
func MsgErr ¶
MsgErr creates an ad-hoc error message without requiring a sentinel error. This is a convenience for rapid development - use sentinels for production code.
Accepts two forms:
- MsgErr("message") - creates error with the given message
- MsgErr(err) - wraps existing error, preserving error chain for errors.Is()
Use this when you don't want to define a sentinel immediately. Future tooling can detect MsgErr usage and suggest/generate appropriate sentinel errors.
For errors with metadata, use NewErr with a sentinel, or wrap with WithErr:
err := MsgErr("config invalid")
err = WithErr(err, "path", configPath)
func NewErr ¶
NewErr builds a standalone structured entry (no primary cause inside). Accepted parts:
- error — sentinel/tag (required: at least one, must be first)
- KV{Key,Value} — explicit key/value
- "key", value — implicit pair (value can be any type, including error)
- error — optional trailing cause (joined last via errors.Join)
Pattern: one or more sentinels (error), then zero or more key-value pairs, then optional trailing cause (error). After the first string key, all remaining args must form valid pairs, except for an optional final error. Returns nil if no meaningful parts are provided after validation. Returns a validation error joined with the partial entry if validation fails.
func WithErr ¶
WithErr is a flexible enrichment helper. Typical uses:
// Enrich an existing composite error (err may be an errors.Join tree):
err = WithErr(err, "Foo", 10)
// Build an entry and join a trailing cause in one shot:
err = WithErr("endpoint", ep, ErrTemplate, cause) // 'cause' is last
Behavior:
If the FIRST arg is an error, it is treated as the base error to enrich: • If it is a doterr entry, merge KVs/sentinels into that entry. • If it is a multi-unwrap (errors.Join tree), find the RIGHTMOST doterr entry, merge into it, and rebuild preserving order. • If no doterr entry is found, a new entry will be joined in (see step 3).
After consuming the base (if present), if the LAST remaining arg is an error, it is treated as the CAUSE and joined LAST.
The remaining middle args (if any) are collected into an entry. If we enriched an existing doterr entry in step 1, that merged entry is used; otherwise, a fresh entry is created. If there is a trailing CAUSE from step 2, the result is errors.Join(entry, cause). If there is no cause, the entry is returned.
Note: For inter-function composition, prefer New() with trailing cause:
return NewErr(ErrHelpVisor, "key", val, cause) // cause last
Types ¶
type ClosedMsg ¶
type ClosedMsg struct{}
ClosedMsg is sent when the help visor is closed by the user
type ErrKV ¶
ErrKV represents a key/value metadata pair. Keys are preserved in insertion order, and values may be of any type.
func AnyKV ¶
AnyKV creates a KV with any value type. Use this for custom types or when the specific type constructor doesn't exist.
func AppendKV ¶
AppendKV appends key-value pairs to a slice of KV values. It accepts variadic arguments in three forms:
- Individual KV values: AppendKV(kvs, StringKV("foo", "bar"))
- String key-value pairs: AppendKV(kvs, "foo", "bar")
- Lazy ErrKV functions: AppendKV(kvs, func()ErrKV{ return StringKV("expensive", compute()) })
This function is useful for accumulating metadata throughout a function before creating an error:
var kvs []ErrKV
kvs = AppendKV(kvs, "user_id", userID)
if complexCondition {
kvs = AppendKV(kvs, "reason", "complex")
}
return NewErr(ErrFailed, kvs, cause)
String key-value pairs must come in even counts (odd counts panic in debug mode). Lazy functions (func()ErrKV) are wrapped and not evaluated until error creation.
func ErrMeta ¶
ErrMeta returns the key/value pairs stored on all doterr entries in the error tree. If err is a doterr entry, returns its metadata. If err is a joined error (has Unwrap() []error), scans all children recursively and collects metadata from all doterr entries found, preserving order. Otherwise returns nil. The returned slice preserves insertion order across all entries.
func ErrorKV ¶
ErrorKV creates a KV with an error value. Use this when you want to include an error as metadata (not as a cause).
type HelpVisorKeyMap ¶
type HelpVisorKeyMap struct {
Close key.Binding // esc/? — close the visor
PrevPage key.Binding // left — previous page
NextPage key.Binding // right — next page
}
HelpVisorKeyMap defines the key bindings for the help visor
func DefaultHelpVisorKeyMap ¶
func DefaultHelpVisorKeyMap() HelpVisorKeyMap
DefaultHelpVisorKeyMap returns the default key bindings for the help visor
type HelpVisorModel ¶
type HelpVisorModel struct {
Keys HelpVisorKeyMap
Styles HelpVisorStyles
// contains filtered or unexported fields
}
HelpVisorModel is a stateful model for the keyboard shortcuts help overlay. Supports paging with left/right navigation and colorized footer.
View() returns the rendered visor content; callers handle overlay positioning (e.g., via teamodal.OverlayModal or their own logic).
func NewHelpVisorModel ¶
func NewHelpVisorModel() HelpVisorModel
NewHelpVisorModel creates a new, closed HelpVisorModel with default styles and keys.
func (HelpVisorModel) Close ¶
func (m HelpVisorModel) Close() HelpVisorModel
Close closes the help visor and clears state.
func (HelpVisorModel) Init ¶
func (m HelpVisorModel) Init() tea.Cmd
Init implements tea.Model — returns nil (no initial command).
func (HelpVisorModel) IsOpen ¶
func (m HelpVisorModel) IsOpen() bool
IsOpen returns whether the help visor is currently displayed.
func (HelpVisorModel) Open ¶
func (m HelpVisorModel) Open(keysByCategory map[string][]teautils.KeyMeta) HelpVisorModel
Open opens the help visor with the given keys and builds pages.
func (HelpVisorModel) Page ¶
func (m HelpVisorModel) Page() int
Page returns the current page index (0-based).
func (HelpVisorModel) SetSize ¶
func (m HelpVisorModel) SetSize(width, height int) HelpVisorModel
SetSize updates the available terminal dimensions and rebuilds pages if open.
func (HelpVisorModel) TotalPages ¶
func (m HelpVisorModel) TotalPages() int
TotalPages returns the total number of pages.
func (HelpVisorModel) Update ¶
func (m HelpVisorModel) Update(msg tea.Msg) (HelpVisorModel, tea.Cmd)
Update handles key events when the visor is open. Uses key.Matches for configurable bindings. Also supports direct page navigation via digit keys 1-9. All keys are consumed (not passed through).
func (HelpVisorModel) View ¶
func (m HelpVisorModel) View() (view tea.View)
View renders the help visor with open-bottom border. Returns empty view when closed. View implements tea.Model (FOLLOWS ClearPath)
func (HelpVisorModel) WithContentStyle ¶
func (m HelpVisorModel) WithContentStyle(style teautils.HelpVisorStyle) HelpVisorModel
WithContentStyle returns a copy with the given content style (title, category, key, desc).
func (HelpVisorModel) WithKeys ¶
func (m HelpVisorModel) WithKeys(keys HelpVisorKeyMap) HelpVisorModel
WithKeys returns a copy with the given key bindings.
func (HelpVisorModel) WithStyles ¶
func (m HelpVisorModel) WithStyles(styles HelpVisorStyles) HelpVisorModel
WithStyles returns a copy with the given chrome styles (border, footer).
func (HelpVisorModel) WithTheme ¶
func (m HelpVisorModel) WithTheme(theme teautils.Theme) HelpVisorModel
WithTheme returns a copy of the HelpVisorModel with styles derived from the given theme. Individual With*Style() calls take precedence if called after.
type HelpVisorStyles ¶
HelpVisorStyles holds the styles for the help visor chrome (border and footer). Content styling (title, category, key, description) is handled by teautils.HelpVisorStyle, which is passed via WithContentStyle.
func DefaultHelpVisorStyles ¶
func DefaultHelpVisorStyles() HelpVisorStyles
DefaultHelpVisorStyles returns the default styles for the help visor