storeui

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 12 Imported by: 0

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

View Source
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

func ResolveLocalPath(cwd, filename string) string

ResolveLocalPath determines the CWD dot-file path using dual-placement: if .clawker/ dir exists → .clawker/{filename}, otherwise → .{filename}.

func SetFieldValue

func SetFieldValue(v any, path string, val string) error

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

func ShortenHome(p string) string

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

func ApplyOverrides(fields []Field, overrides []Override) []Field

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

func WalkFields(v any) []Field

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

type FieldKind = storage.FieldKind

FieldKind is an alias for storage.FieldKind. Consumers should use the storage constants (KindText, KindBool, etc.) directly.

const KindTriState FieldKind = KindBool

KindTriState is deprecated. Use KindBool instead. Retained for backward compatibility — maps to the same underlying type as KindBool.

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

func WithOnlyPaths(paths ...string) Option

WithOnlyPaths restricts the editor to show only the given dotted paths. All other fields are excluded. When set, WithSkipPaths is ignored.

func WithOverrides

func WithOverrides(overrides []Override) Option

WithOverrides provides domain-specific field overrides.

func WithSkipPaths

func WithSkipPaths(paths ...string) Option

WithSkipPaths hides the given dotted paths from the editor.

func WithTitle

func WithTitle(title string) Option

WithTitle sets the editor title displayed at the top.

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:

  1. store.Read() → snapshot
  2. WalkFields(snapshot) → fields
  3. Filter skip paths, ApplyOverrides
  4. Map storeui.Field → tui.BrowserField, run tui.FieldBrowserModel
  5. OnFieldSaved callback: store.Set + writeFieldToFile per field
  6. Return Result

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL