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
- Variables
- func NewFieldError(field, message string) error
- type Field
- type FieldError
- type FieldKind
- type Form
- func New(title, subtitle string, fields []Field) *Form
- func NewProfileForm(backend ProfileBackend, ...) *Form
- func NewSecretForm(backend SecretBackend, spec SecretFieldInfo, storeName, existingRef string) *Form
- func NewStoreForm(backend StoreBackend, existingName string, initial map[string]string, ...) *Form
- func (f *Form) Canceled() bool
- func (f *Form) Done() bool
- func (f *Form) Fields() []Field
- func (f *Form) FocusedKey() string
- func (f *Form) Init() tea.Cmd
- func (f *Form) Result() string
- func (f *Form) SetDisabled(key string, disabled bool)
- func (f *Form) SetHelp(key, help string)
- func (f *Form) SetLabel(key, label string)
- func (f *Form) SetOptions(key string, options []string)
- func (f *Form) SetRequired(key string, required bool)
- func (f *Form) SetValue(key, value string)
- func (f *Form) TakeIntent() (Intent, bool)
- func (f *Form) TrimmedValue(key string) string
- func (f *Form) Update(msg tea.Msg) (*Form, tea.Cmd)
- func (f *Form) Value(key string) string
- func (f *Form) View() string
- type Intent
- type ProfileBackend
- type SecretBackend
- type SecretFieldInfo
- type StoreBackend
Constants ¶
const ( IntentCreateStore = "create_store" IntentEditStore = "edit_store" )
Intent names yielded by the profile form's store field.
const ( FieldSecretStorage = "storage" FieldSecretRef = "ref" FieldSecretValue = "value" )
Secret form field keys.
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.
const ( EncNone = "none" EncPassword = "password" EncPlatform = "platform" EncKMS = "kms" )
Encryption modes offered by the store form.
const CreateStoreOption = "+ Create store"
CreateStoreOption is the sentinel store-field option that opens the nested store-create form (#232).
const IntentEditSecret = "edit_secret"
IntentEditSecret is yielded when the user configures a store secret field (Ctrl+E), opening the nested secret-ref form.
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 ¶
var EncryptionModes = []string{EncNone, EncPassword, EncPlatform, EncKMS}
EncryptionModes lists the encryption modes offered by the form, in order.
var SourceTypes = []string{
"local",
"sftp",
"gdrive",
"gdrive-changes",
"onedrive",
"onedrive-changes",
}
SourceTypes are the source schemes offered by the profile form, in order.
var StoreTypes = []string{"local", "s3", "b2", "sftp"}
StoreTypes lists the store schemes offered by the form, in order.
Functions ¶
func NewFieldError ¶
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.
type FieldError ¶
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.
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 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) FocusedKey ¶
FocusedKey returns the key of the currently focused field.
func (*Form) SetDisabled ¶
SetDisabled toggles a field's disabled flag; a disabled field is skipped by focus movement and rendered dimmed.
func (*Form) SetOptions ¶
SetOptions replaces a select field's options, keeping the current value when still present.
func (*Form) SetRequired ¶
SetRequired toggles a field's required flag.
func (*Form) TakeIntent ¶
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 ¶
TrimmedValue returns the named field's value with surrounding space removed.
type Intent ¶
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.