Documentation
¶
Overview ¶
Package presenter provides schema-aware rendering for Basecamp entities. It sits between commands and the output renderer, using declarative YAML schemas to transform generic data into human-centered terminal output.
Index ¶
- func EvalCondition(condition string, data map[string]any) bool
- func FormatField(spec FieldSpec, key string, val any, locale Locale) string
- func IsOverdue(val any) bool
- func Present(w io.Writer, data any, entityHint string, mode RenderMode) bool
- func PresentWithTheme(w io.Writer, data any, entityHint string, mode RenderMode, theme tui.Theme, ...) bool
- func RenderDetail(w io.Writer, schema *EntitySchema, data map[string]any, styles Styles, ...) error
- func RenderDetailMarkdown(w io.Writer, schema *EntitySchema, data map[string]any, locale Locale) error
- func RenderHeadline(schema *EntitySchema, data map[string]any) string
- func RenderList(w io.Writer, schema *EntitySchema, data []map[string]any, styles Styles, ...) error
- func RenderListMarkdown(w io.Writer, schema *EntitySchema, data []map[string]any, locale Locale) error
- func RenderTemplate(tmpl string, data map[string]any) string
- type Affordance
- type CompactView
- type DetailSection
- type DetailView
- type EntitySchema
- type FieldSpec
- type HeadlineSpec
- type Identity
- type ListView
- type Locale
- type Registry
- type Relationship
- type RenderMode
- type Styles
- type ViewSpecs
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EvalCondition ¶
EvalCondition evaluates a template condition (from affordance "when" field). Returns true if the template renders to exactly "true" (as produced by Go's text/template for boolean true values and the {{not}} helper). Empty conditions are always true (unconditional visibility).
func FormatField ¶
FormatField formats a field value according to its FieldSpec using the given locale.
func IsOverdue ¶
IsOverdue checks if a date value is before the start of today in local time. Handles both date-only ("2006-01-02") and RFC3339 timestamps.
func Present ¶
Present attempts schema-aware rendering of the data. Returns true if a schema was found and rendering was handled. Returns false if no schema matched (caller should fall back to generic rendering).
func PresentWithTheme ¶
func PresentWithTheme(w io.Writer, data any, entityHint string, mode RenderMode, theme tui.Theme, locale Locale) bool
PresentWithTheme is like Present but accepts a theme and locale directly (for testing).
func RenderDetail ¶
func RenderDetail(w io.Writer, schema *EntitySchema, data map[string]any, styles Styles, locale Locale) error
RenderDetail renders a single entity using its schema's detail view.
func RenderDetailMarkdown ¶
func RenderDetailMarkdown(w io.Writer, schema *EntitySchema, data map[string]any, locale Locale) error
RenderDetailMarkdown renders a single entity as Markdown.
func RenderHeadline ¶
func RenderHeadline(schema *EntitySchema, data map[string]any) string
RenderHeadline selects and renders the appropriate headline for the data.
func RenderList ¶
func RenderList(w io.Writer, schema *EntitySchema, data []map[string]any, styles Styles, locale Locale) error
RenderList renders a slice of entities using the schema's list view.
func RenderListMarkdown ¶
func RenderListMarkdown(w io.Writer, schema *EntitySchema, data []map[string]any, locale Locale) error
RenderListMarkdown renders a slice of entities as a Markdown table.
func RenderTemplate ¶
RenderTemplate executes a Go text/template with the given data. Numeric values that are integer-like floats (common from JSON) are coerced to int64 before rendering to avoid scientific notation in output. Returns a placeholder on parse/execute errors to make failures visible.
Types ¶
type Affordance ¶
type Affordance struct {
Action string `yaml:"action"`
Cmd string `yaml:"cmd"`
Label string `yaml:"label"`
When string `yaml:"when"`
}
Affordance is a templated CLI action the user can take.
type CompactView ¶
CompactView configures a minimal inline presentation.
type DetailSection ¶
DetailSection groups fields under an optional heading.
type DetailView ¶
type DetailView struct {
Sections []DetailSection `yaml:"sections"`
}
DetailView configures the single-entity detail presentation.
type EntitySchema ¶
type EntitySchema struct {
Entity string `yaml:"entity"`
Kind string `yaml:"kind"`
TypeKey string `yaml:"type_key"`
Identity Identity `yaml:"identity"`
Headline map[string]HeadlineSpec `yaml:"headline"`
Fields map[string]FieldSpec `yaml:"fields"`
Views ViewSpecs `yaml:"views"`
Relations map[string]Relationship `yaml:"relationships"`
Actions []Affordance `yaml:"affordances"`
}
EntitySchema describes how a Basecamp entity wants to be presented. Schemas are declarative metadata loaded from YAML files.
func Detect ¶
func Detect(data any, entityHint string) *EntitySchema
Detect finds a schema from data. It checks an explicit entity name hint first, then falls back to auto-detection from the data's "type" field.
func LookupByName ¶
func LookupByName(name string) *EntitySchema
LookupByName returns a schema by entity name (e.g. "todo").
func LookupByTypeKey ¶
func LookupByTypeKey(typeKey string) *EntitySchema
LookupByTypeKey returns a schema by API type key (e.g. "Todo").
type FieldSpec ¶
type FieldSpec struct {
Role string `yaml:"role"`
Emphasis string `yaml:"emphasis"`
Format string `yaml:"format"`
Collapse bool `yaml:"collapse"`
Labels map[string]string `yaml:"labels"`
WhenOverdue string `yaml:"when_overdue"`
}
FieldSpec describes how a single field should be presented.
type HeadlineSpec ¶
type HeadlineSpec struct {
Template string `yaml:"template"`
}
HeadlineSpec defines a headline template, optionally conditional.
type Identity ¶
type Identity struct {
Label string `yaml:"label"`
ID string `yaml:"id"`
Icon string `yaml:"icon"`
}
Identity identifies the entity's label and ID fields.
type ListView ¶
type ListView struct {
Columns []string `yaml:"columns"`
}
ListView configures the table/list presentation.
type Locale ¶
type Locale struct {
// contains filtered or unexported fields
}
Locale holds resolved formatting conventions for dates and numbers. It supports separate tags for date and number formatting to honor POSIX category-specific overrides (LC_TIME vs LC_NUMERIC).
func DetectLocale ¶
func DetectLocale() Locale
DetectLocale resolves the user's locale from environment variables. Respects the POSIX precedence: LC_ALL overrides everything, then category-specific variables (LC_TIME for dates, LC_NUMERIC for numbers), then LANG as fallback. Falls back to en-US if nothing is set.
func NewLocale ¶
NewLocale creates a Locale from a POSIX locale string (e.g. "de_DE.UTF-8") or BCP 47 tag (e.g. "de-DE"). Uses the same tag for both date and number formatting. Returns en-US for empty or unparseable input.
func NewLocaleSplit ¶
NewLocaleSplit creates a Locale with separate tags for date and number formatting, matching POSIX behavior where LC_TIME and LC_NUMERIC can differ.
func (Locale) FormatDate ¶
FormatDate formats a time.Time as a locale-appropriate date string.
func (Locale) FormatNumber ¶
FormatNumber formats a float64 with locale-appropriate grouping and decimal separators.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds loaded entity schemas indexed by name and type key.
type Relationship ¶
type Relationship struct {
Entity string `yaml:"entity"`
Via string `yaml:"via"`
Label string `yaml:"label"`
Cardinality string `yaml:"cardinality"`
}
Relationship describes a connection to another entity.
type RenderMode ¶
type RenderMode int
RenderMode controls the output format.
const ( ModeStyled RenderMode = iota // ANSI styled terminal output ModeMarkdown // Literal Markdown syntax )
type Styles ¶
type Styles struct {
Primary lipgloss.Style
Normal lipgloss.Style
Muted lipgloss.Style
Subtle lipgloss.Style // for footer elements (most understated)
Success lipgloss.Style
Warning lipgloss.Style
Error lipgloss.Style
Heading lipgloss.Style
Label lipgloss.Style
Body lipgloss.Style
}
Styles holds the lipgloss styles used by the presenter.
type ViewSpecs ¶
type ViewSpecs struct {
List ListView `yaml:"list"`
Detail DetailView `yaml:"detail"`
Compact CompactView `yaml:"compact"`
}
ViewSpecs declares which fields appear per presentation context.