forms

package
v1.18.0 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package forms provides Bubble Tea form components for the interactive TUI.

It replaces the hand-rolled modal state machines and the ASCII-only byte reader in package main (RFC 0012 Phase 2, issue #340). Text fields are backed by bubbles/textinput, so Unicode input, cursor movement, and paste work by construction rather than being re-implemented byte by byte.

Index

Constants

View Source
const (
	IntentCreateStore = "create_store"
	IntentEditStore   = "edit_store"
)

Intent names yielded by the profile form's store field.

View Source
const (
	FieldSecretStorage = "storage"
	FieldSecretRef     = "ref"
	FieldSecretValue   = "value"
)

Secret form field keys.

View Source
const (
	FieldStoreName      = "name"
	FieldStoreType      = "store_type"
	FieldStoreValue     = "store_value"
	FieldS3Region       = "s3_region"
	FieldS3Profile      = "s3_profile"
	FieldS3Endpoint     = "s3_endpoint"
	FieldS3AccessKey    = "s3_access_key_secret"
	FieldS3SecretKey    = "s3_secret_key_secret"
	FieldSFTPPassword   = "sftp_password_secret"
	FieldSFTPKey        = "sftp_key_secret"
	FieldEncryptionMode = "encryption_mode"
	FieldPasswordSecret = "password_secret"
	FieldPlatformSecret = "encryption_key_secret"
	FieldKMSKeyARN      = "kms_key_arn"
	FieldKMSRegion      = "kms_region"
	FieldKMSEndpoint    = "kms_endpoint"
	// FieldStoreURI is not an input; the form writes the composed URI here for
	// the backend to consume.
	FieldStoreURI = "uri"
)

Store form field keys. They are shared with the cmd-side StoreBackend adapter (which assembles a ProfileStore from the collected values), so both sides must agree on them.

View Source
const (
	EncNone     = "none"
	EncPassword = "password"
	EncPlatform = "platform"
	EncKMS      = "kms"
)

Encryption modes offered by the store form.

View Source
const CreateStoreOption = "+ Create store"

CreateStoreOption is the sentinel store-field option that opens the nested store-create form (#232).

View Source
const IntentEditSecret = "edit_secret"

IntentEditSecret is yielded when the user configures a store secret field (Ctrl+E), opening the nested secret-ref form.

View Source
const StorageEnv = "env"

StorageEnv is the built-in storage option that saves only an environment variable reference (the secret value stays outside profiles.yaml).

Variables

View Source
var EncryptionModes = []string{EncNone, EncPassword, EncPlatform, EncKMS}

EncryptionModes lists the encryption modes offered by the form, in order.

View Source
var SourceTypes = []string{
	"local",
	"sftp",
	"gdrive",
	"gdrive-changes",
	"onedrive",
	"onedrive-changes",
}

SourceTypes are the source schemes offered by the profile form, in order.

View Source
var StoreTypes = []string{"local", "s3", "b2", "sftp"}

StoreTypes lists the store schemes offered by the form, in order.

Functions

func NewFieldError

func NewFieldError(field, message string) error

NewFieldError builds a FieldError for the given field key.

Types

type Field

type Field struct {
	Key      string
	Label    string
	Kind     FieldKind
	Options  []string
	Required bool
	Disabled bool
	// Help is an optional dimmed hint rendered under the field when focused.
	Help string
	// contains filtered or unexported fields
}

Field is one editable row in a form.

func (Field) Value

func (f Field) Value() string

Value returns the field's current value.

type FieldError

type FieldError struct {
	Field   string
	Message string
}

FieldError attaches an error message to a specific field so the form can highlight it. Submit hooks return it to report per-field validation errors.

func (*FieldError) Error

func (e *FieldError) Error() string

type FieldKind

type FieldKind int

FieldKind distinguishes a free-text field from a fixed-option selector.

const (
	// FieldText is a free-text field backed by bubbles/textinput.
	FieldText FieldKind = iota
	// FieldSelect cycles through a fixed set of options.
	FieldSelect
)

type Form

type Form struct {
	Title    string
	Subtitle string

	// OnChange is called after any field value changes, so the form can
	// recompute derived fields (labels, options, enabled/disabled). It may be
	// nil for static forms.
	OnChange func(f *Form, changedKey string)
	// Submit validates and persists the form. It returns the result value on
	// success, or a *FieldError / plain error on failure. It is required.
	Submit func(f *Form) (string, error)
	// Interrupt, if set, is consulted for every key before normal handling. It
	// may return a navigation Intent to yield to the host (e.g. open a nested
	// form) without editing or completing the form.
	Interrupt func(f *Form, key tea.KeyMsg) (Intent, bool)
	// contains filtered or unexported fields
}

Form is a vertical, keyboard-driven form. The owning model delegates input to Update while a form is open and reads Done/Canceled/Result afterward.

func New

func New(title, subtitle string, fields []Field) *Form

New builds a form with the given fields and focuses the first editable one.

func NewProfileForm

func NewProfileForm(backend ProfileBackend, existingName, existingSource, existingStore, existingAuth string, editing bool) *Form

NewProfileForm builds the create/edit profile form. For editing, name and the current source/store/auth are pre-filled and the name field is locked.

func NewSecretForm

func NewSecretForm(backend SecretBackend, spec SecretFieldInfo, storeName, existingRef string) *Form

NewSecretForm builds the guided secret-reference form. It lets the user keep the secret outside profiles.yaml as an env reference, or store the value in a platform backend and save the resulting reference.

func NewStoreForm

func NewStoreForm(backend StoreBackend, existingName string, initial map[string]string, editing bool) *Form

NewStoreForm builds the create/edit store form. initial seeds field values (built by the backend from an existing ProfileStore for edits); for creates it may be nil.

func (*Form) Canceled

func (f *Form) Canceled() bool

Canceled reports whether the form was canceled (Esc).

func (*Form) Done

func (f *Form) Done() bool

Done reports whether the form was submitted successfully.

func (*Form) Fields

func (f *Form) Fields() []Field

Fields exposes the form's fields for derivation hooks.

func (*Form) FocusedKey

func (f *Form) FocusedKey() string

FocusedKey returns the key of the currently focused field.

func (*Form) Init

func (f *Form) Init() tea.Cmd

Init returns the command that starts the focused text field's cursor blink.

func (*Form) Result

func (f *Form) Result() string

Result returns the value produced by a successful Submit.

func (*Form) SetDisabled

func (f *Form) SetDisabled(key string, disabled bool)

SetDisabled toggles a field's disabled flag; a disabled field is skipped by focus movement and rendered dimmed.

func (*Form) SetHelp

func (f *Form) SetHelp(key, help string)

SetHelp sets the dimmed hint shown under the field when focused.

func (*Form) SetLabel

func (f *Form) SetLabel(key, label string)

SetLabel updates a field's label (used by derived source/store labels).

func (*Form) SetOptions

func (f *Form) SetOptions(key string, options []string)

SetOptions replaces a select field's options, keeping the current value when still present.

func (*Form) SetRequired

func (f *Form) SetRequired(key string, required bool)

SetRequired toggles a field's required flag.

func (*Form) SetValue

func (f *Form) SetValue(key, value string)

SetValue sets the named field's value.

func (*Form) TakeIntent

func (f *Form) TakeIntent() (Intent, bool)

TakeIntent returns and clears any pending intent set by the Interrupt hook. The host calls it after Update to decide whether to open a nested form.

func (*Form) TrimmedValue

func (f *Form) TrimmedValue(key string) string

TrimmedValue returns the named field's value with surrounding space removed.

func (*Form) Update

func (f *Form) Update(msg tea.Msg) (*Form, tea.Cmd)

Update processes one message while the form is open.

func (*Form) Value

func (f *Form) Value(key string) string

Value returns the current value of the named field.

func (*Form) View

func (f *Form) View() string

View renders the form as a bordered box.

type Intent

type Intent struct {
	Name  string
	Value string
}

Intent is a navigation request a form yields to its host instead of completing — for example, opening a nested form. Name identifies the action; Value carries a parameter (e.g. the store to edit, or the secret field key).

type ProfileBackend

type ProfileBackend interface {
	// StoreOptions returns the selectable store names.
	StoreOptions() []string
	// ProviderForSourceType returns the auth provider a source type requires,
	// or "" when the source needs no auth.
	ProviderForSourceType(sourceType string) string
	// AuthOptions returns the auth refs available for a provider.
	AuthOptions(provider string) []string
	// SourceParts splits an existing source URI into its (type, value) pair.
	SourceParts(sourceURI string) (sourceType, value string)
	// SourceDetailLabel returns the label for the source detail field.
	SourceDetailLabel(sourceType string) string
	// SourceDetailRequired reports whether the source detail is mandatory.
	SourceDetailRequired(sourceType string) bool
	// SourceExample returns an example hint for the source detail field.
	SourceExample(sourceType string) string
	// ComposeSource builds and validates a source URI from type and value.
	ComposeSource(sourceType, value string) (string, error)
	// ValidateNewName validates a candidate new profile name.
	ValidateNewName(name string) error
	// ProfileExists reports whether a profile name is already taken.
	ProfileExists(name string) bool
	// SaveProfile persists the profile.
	SaveProfile(name, sourceURI, storeRef, authRef string, editing bool) error
}

ProfileBackend is the domain boundary for the profile form. The cmd package implements it by reusing the existing source-URI, options, validation, and save helpers, so this package stays free of URI-parsing and persistence concerns.

type SecretBackend

type SecretBackend interface {
	// StorageOptions returns the selectable storage schemes: "env" plus the
	// available writable backend schemes (keychain, secret-service, …).
	StorageOptions() []string
	// DefaultRef returns a suggested reference for a writable backend scheme.
	DefaultRef(scheme, storeName, account string) string
	// ParseRef reports a reference's scheme, and for env refs the variable
	// name; ok is false when the reference does not parse.
	ParseRef(ref string) (scheme, envName string, ok bool)
	// ValidateRef validates a reference's format.
	ValidateRef(ref string) error
	// StoreSecret stores value under the reference in its backend.
	StoreSecret(ref, value string) error
}

SecretBackend is the domain boundary for the secret-ref form. The cmd package implements it over the secretref resolver.

type SecretFieldInfo

type SecretFieldInfo struct {
	// Label names the secret in prose, e.g. "S3 access key".
	Label string
	// DefaultEnvName is the suggested environment variable name.
	DefaultEnvName string
	// DefaultAccount is the account/key hint passed to writable backends.
	DefaultAccount string
}

SecretFieldInfo describes the secret a secret-ref form configures. It is carried from the store field being edited.

func StoreSecretFieldSpec

func StoreSecretFieldSpec(fieldKey string) (SecretFieldInfo, bool)

StoreSecretFieldSpec returns the secret spec for a store field key.

type StoreBackend

type StoreBackend interface {
	// StoreDetailLabel returns the label for the primary value field.
	StoreDetailLabel(storeType string) string
	// StoreExample returns an example hint for the primary value field.
	StoreExample(storeType string) string
	// ComposeStore builds and validates a store URI from type and value.
	ComposeStore(storeType, value string) (string, error)
	// ValidateStoreName validates a candidate new store name.
	ValidateStoreName(name string) error
	// StoreExists reports whether a store name is already taken.
	StoreExists(name string) bool
	// ValidateSecretRef validates a non-empty secret reference's format.
	ValidateSecretRef(ref string) error
	// SaveStore persists the store from the collected field values.
	SaveStore(name string, values map[string]string, editing bool) error
}

StoreBackend is the domain boundary for the store form. The cmd package implements it by reusing the store-URI and secret-ref helpers, keeping this package free of parsing and persistence concerns.

Jump to

Keyboard shortcuts

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