Documentation
¶
Overview ¶
Package storeui provides a generic TUI for browsing and editing storage.Store[T] instances.
It bridges the gap between typed stores (internal/storage) and terminal presentation (internal/tui), enabling interactive field browsing, editing, and layer-targeted saving for any store instance.
Index ¶
- Constants
- func BuildBrowser[T storage.Schema](store *storage.Store[T], opts ...Option) (*tui.FieldBrowserModel, error)
- func Ptr[T any](v T) *T
- func ResolveLocalPath(cwd, filename string) string
- func SetFieldValue(v any, path string, val string) error
- func ShortenHome(p string) string
- type Field
- type FieldKind
- type LayerTarget
- type Option
- type Override
- type Result
Constants ¶
const ( KindText = storage.KindText KindBool = storage.KindBool KindSelect = storage.KindSelect KindInt = storage.KindInt KindStringSlice = storage.KindStringSlice KindDuration = storage.KindDuration KindMap = storage.KindMap KindStructSlice = storage.KindStructSlice )
Re-export storage.FieldKind constants for backward compatibility.
Variables ¶
This section is empty.
Functions ¶
func BuildBrowser ¶
func BuildBrowser[T storage.Schema](store *storage.Store[T], opts ...Option) (*tui.FieldBrowserModel, error)
BuildBrowser creates a FieldBrowserModel for a storage.Store[T] without running it. The returned model can be embedded as a WizardPage or run standalone via tui.RunProgram. All save/delete callbacks are wired.
func Ptr ¶
func Ptr[T any](v T) *T
Ptr returns a pointer to a copy of the given value. Useful for constructing Override fields.
func ResolveLocalPath ¶
ResolveLocalPath determines the CWD dot-file path using dual-placement: if .clawker/ dir exists → .clawker/{filename}, otherwise → .{filename}.
func SetFieldValue ¶
SetFieldValue sets a field on a struct pointer by its dotted YAML path. It walks the struct via yaml tags, allocates nil pointer-to-struct parents, and performs type-aware conversion at the leaf.
v must be a non-nil pointer to a struct. Panics otherwise.
func ShortenHome ¶
ShortenHome replaces $HOME prefix with ~ for display.
Types ¶
type Field ¶
type Field struct {
Path string // Dotted YAML path (e.g. "build.image")
Label string // Human-readable label
Description string // Help text
Kind FieldKind // Widget type
Value string // Formatted current value (compact summary for browse display)
EditValue string // Full value for editor pre-population (YAML for Map/StructSlice kinds)
Default string // Effective default shown when Value is "<unset>" or empty
Options []string // For Select fields
Validator func(string) error // Optional input validation
Required bool // Whether the field must have a value
ReadOnly bool // Whether the field is not editable
Order int // Sort order (lower = first)
// Editor is a custom editor factory provided by domain adapters.
// When non-nil, the field browser uses it instead of the default kind-based
// editor dispatch. The returned value must satisfy [tui.FieldEditor].
// Using any preserves the storeui → tui import boundary.
Editor func(label, value string) any
}
Field represents a single editable configuration field discovered via reflection.
func ApplyOverrides ¶
ApplyOverrides merges overrides into a copy of fields, returning the result sorted by Order. Fields matched by a Hidden override are removed. Nil override pointer fields do not clobber existing values. Overrides with no matching field path are silently ignored.
func WalkFields ¶
WalkFields uses reflection to discover editable fields from a struct value. It maps Go types to FieldKind: string→Text, bool→Bool, *bool→Bool, int→Int, []string→StringSlice, time.Duration→Duration, map[string]string→Map, []struct→StructSlice, nested struct→recurse, nil *struct→recurse zero value. Unrecognized types fall back to KindStructSlice (enrichWithSchema overwrites the kind from schema metadata afterward).
Accepts both value and pointer types. Uses yaml struct tags for path building.
type FieldKind ¶
FieldKind is an alias for storage.FieldKind. Consumers should use the storage constants (KindText, KindBool, etc.) directly.
type LayerTarget ¶
type LayerTarget struct {
Label string // Display label (e.g. "Original", "Local", "User")
Description string // Shortened path for display
Path string // Full absolute filesystem path
}
LayerTarget represents a save destination for a single field. Domain adapters build these from config accessors.
func BuildLayerTargets ¶
func BuildLayerTargets(filename, configDir string, layers []storage.LayerInfo) []LayerTarget
BuildLayerTargets builds save destinations from the canonical locations (Local, User) plus every discovered file layer. All targets are always shown so the user can save to any layer — even ones that don't currently define the field being edited.
Virtual layers (empty path = defaults) are always excluded. Duplicate paths are deduped (first occurrence wins).
type Option ¶
type Option func(*editOptions)
Option configures the Edit function.
func WithLayerTargets ¶
func WithLayerTargets(targets []LayerTarget) Option
WithLayerTargets provides the per-field save destinations. Domain adapters build these using config path accessors.
func WithOnlyPaths ¶
WithOnlyPaths restricts the editor to show only the given dotted paths. All other fields are excluded. When set, WithSkipPaths is ignored.
func WithOverrides ¶
WithOverrides provides domain-specific field overrides.
func WithSkipPaths ¶
WithSkipPaths hides the given dotted paths from the editor.
type Override ¶
type Override struct {
Path string
Label *string
Description *string
Default *string // Effective default shown when value is "<unset>"
Kind *FieldKind
Options []string // Replaces options when non-nil
Validator func(string) error // Replaces validator when non-nil
Required *bool
ReadOnly *bool
Order *int
Hidden bool // When true, removes the field from the list entirely
// Editor is a custom editor factory for this field.
// When non-nil, the field browser uses it instead of the default kind-based
// editor dispatch. The returned value must satisfy [tui.FieldEditor].
Editor func(label, value string) any
}
Override allows domain adapters to customize reflected fields by path. Pointer fields use nil to mean "don't override" — only non-nil values replace the original.
type Result ¶
type Result struct {
Saved bool // True if any field was persisted
Cancelled bool // True if the user cancelled
SavedCount int // Number of fields successfully saved
}
Result holds the outcome of an interactive edit session.
func Edit ¶
func Edit[T storage.Schema](ios *iostreams.IOStreams, store *storage.Store[T], opts ...Option) (Result, error)
Edit runs an interactive field editor for a storage.Store[T].
Each field edit is saved immediately to a user-chosen layer target. The orchestration flow:
- store.Read() → snapshot
- WalkFields(snapshot) → fields
- Filter skip paths, ApplyOverrides
- Map storeui.Field → tui.BrowserField, run tui.FieldBrowserModel
- OnFieldSaved callback: store.Set + writeFieldToFile per field
- Return Result