app

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 47 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BuiltinFunctions = map[string][]string{
	"SQLite": {
		"ABS", "AVG", "CAST", "CHAR", "COALESCE", "COUNT", "CURRENT_DATE",
		"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATE", "DATETIME", "GROUP_CONCAT",
		"IFNULL", "INSTR", "JSON_EXTRACT", "JSON_OBJECT", "JSON_ARRAY",
		"JULIANDAY", "LENGTH", "LIKE", "LOWER", "LTRIM", "MAX", "MIN", "NULLIF",
		"PRINTF", "RANDOM", "REPLACE", "ROUND", "RTRIM", "STRFTIME", "SUBSTR",
		"SUM", "TIME", "TRIM", "TYPEOF", "UNICODE", "UPPER", "ZEROBLOB",
	},
	"MySQL": {
		"AVG", "CAST", "CHAR_LENGTH", "COALESCE", "CONCAT", "COUNT", "CURDATE",
		"CURRENT_DATE", "CURRENT_TIMESTAMP", "CURTIME", "DATE", "DATE_FORMAT",
		"DATEDIFF", "DAY", "FIND_IN_SET", "FORMAT", "FROM_UNIXTIME", "GROUP_CONCAT",
		"IFNULL", "INSTR", "JSON_EXTRACT", "JSON_OBJECT", "JSON_ARRAY",
		"LENGTH", "LOCATE", "LOWER", "LPAD", "LTRIM", "MAX", "MD5", "MIN",
		"MONTH", "NOW", "NULLIF", "RAND", "REGEXP", "REPLACE", "REVERSE",
		"ROUND", "RPAD", "RTRIM", "SHA1", "SHA2", "SUBSTRING", "SUM",
		"TIMESTAMP", "TRIM", "TRUNCATE", "UNIX_TIMESTAMP", "UPPER", "UUID",
		"VERSION", "WEEK", "YEAR",
	},
	"PostgreSQL": {
		"ABS", "AGE", "ARRAY_AGG", "AVG", "CAST", "CEIL", "CHAR_LENGTH",
		"COALESCE", "CONCAT", "COUNT", "CURRENT_DATE", "CURRENT_TIME",
		"CURRENT_TIMESTAMP", "DATE", "DATE_PART", "DATE_TRUNC", "DATEDIFF",
		"EXTRACT", "FLOOR", "GREATEST", "JSON_AGG", "JSON_BUILD_OBJECT",
		"JSON_EXTRACT_PATH", "LATERAL", "LEAST", "LENGTH", "LOWER", "LPAD",
		"LTRIM", "MAX", "MIN", "NOW", "NULLIF", "POSITION", "POW",
		"RANDOM", "REGEXP_MATCHES", "REGEXP_REPLACE", "REPLACE", "REVERSE",
		"ROUND", "RPAD", "RTRIM", "SPLIT_PART", "STRING_AGG", "SUBSTRING",
		"SUM", "TO_CHAR", "TO_DATE", "TO_NUMBER", "TO_TIMESTAMP", "TRIM",
		"TRUNC", "UPPER", "UUID_GENERATE_V4", "WIDTH_BUCKET",
	},
}

BuiltinFunctions returns SQL built-in function names keyed by product name.

Functions

func AppearanceFromBackground

func AppearanceFromBackground(payload string) string

AppearanceFromBackground converts a terminal-reported background color to a light/dark appearance using the WCAG-relative luminance of the linearized sRGB channels. Payload is the rune payload of an OSC 11 response, e.g. "rgb:1c1c/1c1c/1c1c". An unparseable or empty payload yields "".

func AttachLogProgram

func AttachLogProgram(program *tea.Program)

AttachLogProgram wires the running program into the log notification pipeline so entries logged by async commands surface as popups even when the UI is idle. Call once with the program returned by tea.NewProgram, before program.Run. Attaching nil detaches.

func ConfigPath

func ConfigPath() string

ConfigPath returns the default config file path in the user's XDG config directory.

func KeybindingsPath

func KeybindingsPath() string

KeybindingsPath returns the default config file path in the user's XDG config directory.

func ReadPluginTrust

func ReadPluginTrust(path string) map[string]string

ReadPluginTrust reads only the plugin_trust mapping from the config file without writing, validating, or materializing anything: a missing, empty, or malformed file yields nil. Read-only commands use it to report fingerprint state without ever mutating config.

func RemovePlugin

func RemovePlugin(path, nameOrExecutable string) (entry, canonical string, changed bool, err error)

RemovePlugin removes the configured plugin matching nameOrExecutable and its trust record. The operand matches the config entry exactly, or — when no entry string matches — resolves like a startup entry (bare names through PATH, relative paths against the config file's directory) and must equal exactly one configured entry's canonical path; ambiguous matches fail instead of removing multiple entries. The trust record is dropped only when no remaining entry resolves to the removed canonical path. The rewrite is atomic and preserves every unrelated key; the original file is left intact on failure. The resolved in-memory config follows the persisted state.

func SaveAppearance

func SaveAppearance(path, appearance string) error

SaveAppearance persists the explicit appearance into config.json, preserving every other key.

func SaveAutoTheme

func SaveAutoTheme(path string, enabled bool) error

SaveAutoTheme persists the follow-system toggle into config.json, preserving every other key.

func SavePlugin

func SavePlugin(path, canonical, digest string) (changed bool, err error)

SavePlugin pins one plugin executable: canonical is the canonical absolute path and digest its lowercase SHA-256. The entry is appended to the plugins list when no entry resolves to it, or replaced by the canonical path when an existing entry resolves to it (so a re-pin never duplicates the executable), and plugin_trust[canonical] is set to digest. Every other config key is preserved byte-for-byte and the file is rewritten atomically (same-directory temp + rename, mode 0600); the original is left intact on any failure. When the resulting plugins/trust state already matches, nothing is written and changed is false. The resolved in-memory config follows the persisted state.

func SaveTableOpenTarget

func SaveTableOpenTarget(path, target string) error

SaveTableOpenTarget persists the table-open target into config.json, replacing only the table_open_target key and preserving every other key byte-for-byte.

func SaveTheme

func SaveTheme(path string, name appTheme) error

SaveTheme persists a theme choice into config.json under the slot key for its scheme (dark_theme or light_theme), preserving every other key.

func SaveVimMode

func SaveVimMode(path string, enabled bool) error

SaveVimMode persists the vim-mode toggle into config.json, replacing only the vim_mode key and preserving every other key byte-for-byte.

func SetAppConfig

func SetAppConfig(config Config)

SetAppConfig applies user configuration. Call it before New so startup defaults (browse page size, query-log page size, read-only, theme) pick it up. Env-var overrides (PERK_WORKBENCH_QUERY_LOG_*) still win over config values at their read sites.

func SetSystemAppearance

func SetSystemAppearance(value string)

SetSystemAppearance records the system light/dark appearance captured at startup so auto-following can resolve it. Call it before SetAppConfig when auto_theme is enabled. An empty value is ignored so that unavailable detection leaves the fallback (persisted appearance, then dark) untouched.

Types

type CommandID

type CommandID = uikit.CommandID

CommandID is a stable identifier for an application keyboard command.

type CompletionItem

type CompletionItem struct {
	Label      string         // display text
	InsertText string         // text inserted on accept (defaults to Label)
	Kind       CompletionKind // for display/label
	Detail     string         // extra info shown alongside the label
	Summary    string         // tertiary muted line shown after Detail
}

CompletionItem is a single suggestion candidate.

type CompletionKind

type CompletionKind int

CompletionKind classifies the type of suggestion.

const (
	KindKeyword CompletionKind = iota
	KindTable
	KindView
	KindColumn
	KindSchema
	KindFunction
	KindBufferWord
	KindCommand
)

func (CompletionKind) String

func (k CompletionKind) String() string

type Config

type Config struct {
	// BrowsePageSize is the default row limit for table browsing.
	// Must be within [1, sharedsql.MaxRows] when set.
	BrowsePageSize int `json:"browse_page_size"`
	// QueryLogPageSize is the default page size of the query-log pane.
	// Must be within [1, queryLogLimit] when set.
	QueryLogPageSize int `json:"query_log_page_size"`
	// QueryLogRetentionDays keeps query-log entries for this many days.
	// Omitted or 0 keeps the built-in default (30); to keep no history at
	// all, set PERK_WORKBENCH_QUERY_LOG_RETENTION_DAYS=0 (config cannot
	// express it, since 0 means unset).
	QueryLogRetentionDays int `json:"query_log_retention_days"`
	// NotificationRetentionDays keeps notification entries for this many
	// days. Omitted or 0 keeps the built-in default (30).
	NotificationRetentionDays int `json:"notification_retention_days"`
	// NotificationTimeoutSeconds is how long a notification popup stays
	// visible. Omitted or 0 keeps the built-in default (10); values above
	// one day are rejected.
	NotificationTimeoutSeconds int `json:"notification_timeout_seconds"`
	// ReadOnly opens every connection read-only by default. The
	// per-connection form toggle still opts a connection back to read-write.
	ReadOnly bool `json:"read_only"`
	// Appearance is the effective light/dark theme: "light" or "dark".
	// Omitted or empty keeps the built-in default (dark). While auto_theme
	// is enabled it is the fallback used when system detection is
	// unavailable and the value resolved into when auto is turned off.
	Appearance string `json:"appearance"`
	// AutoTheme follows the system light/dark appearance at startup.
	// Omitted means enabled (the built-in default).
	AutoTheme *bool `json:"auto_theme"`
	// DarkTheme is the theme used while appearance is dark: one of the
	// dark-scheme themes (ocean, nord, monokai, dracula, catppuccin,
	// solarized).
	DarkTheme string `json:"dark_theme"`
	// LightTheme is the theme used while appearance is light: one of the
	// light-scheme themes (light-ocean, light-nord, ...).
	LightTheme string `json:"light_theme"`
	// VimMode enables modal vim-style editing: normal mode navigates with
	// j/k-style keys and insert mode (i/Enter) types. Disabled, the focused
	// input is always editable — click to type, no mode switch. Omitted
	// means enabled (the built-in default).
	VimMode *bool `json:"vim_mode"`
	// NerdFont renders the schema tree's node markers as Nerd Font icons
	// (database, folder, table). Omitted means enabled (the built-in
	// default); terminals without a Nerd Font can set false to fall back to
	// geometric symbols.
	NerdFont *bool `json:"nerd_font"`
	// LogLevel is the minimum severity written to the event log and
	// surfaced as notifications: debug, info, warn, or error. Omitted
	// keeps the built-in default (info).
	LogLevel string `json:"log_level"`
	// TableOpenTarget is the workspace tab focused after selecting a table
	// in the schema tree: structure (columns), browse, sql, indexes, or
	// foreign_keys. Omitted keeps the built-in default (structure).
	TableOpenTarget string `json:"table_open_target"`
	// Plugins lists external database driver plugin executables to load at
	// startup. Each entry is a bare executable name resolved through PATH
	// or a path relative to the config file's directory. Nil or empty
	// disables plugins.
	Plugins []string `json:"plugins"`
	// PluginTrust pins configured plugin executables to the lowercase
	// SHA-256 digest of the exact bytes approved with `plugin add
	// --approve`, keyed by the canonical absolute executable path. An
	// entry without a record loads unpinned for compatibility; a record
	// whose digest does not match the current bytes is refused at startup
	// before anything spawns. Nil or empty keeps every entry unpinned.
	PluginTrust map[string]string `json:"plugin_trust,omitempty"`
}

Config holds user-configurable default behavior. Zero values mean the built-in default, so fields can be omitted from config.json.

func LoadConfig

func LoadConfig(path string) (Config, error)

LoadConfig reads config.json and returns the Config. If the file does not exist, it writes the default config file and returns the defaults.

type Keybindings

type Keybindings struct {
	// contains filtered or unexported fields
}

Keybindings is an immutable registry of application keyboard bindings.

func DefaultKeybindings

func DefaultKeybindings() Keybindings

DefaultKeybindings returns the built-in default bindings.

func LoadKeybindings

func LoadKeybindings(path string) (Keybindings, error)

LoadKeybindings reads a JSON config file and returns Keybindings. If the file does not exist, it writes the default config file and returns the defaults.

func MustLoadKeybindings

func MustLoadKeybindings(path string) Keybindings

MustLoadKeybindings is like LoadKeybindings but panics on error. Suitable for cmd/perk-workbench startup.

func NewKeybindings

func NewKeybindings(overrides map[string][]string) (Keybindings, error)

NewKeybindings creates a registry by merging overrides over defaults. An empty slice disables a command. Unknown command IDs, invalid keystrokes, and same-scope duplicates return an error.

func (Keybindings) DisplayKey

func (b Keybindings) DisplayKey(id CommandID) string

DisplayKey returns the first configured key label for a command.

func (Keybindings) DisplayKeys

func (b Keybindings) DisplayKeys(id CommandID) string

DisplayKeys returns all configured key labels for a command, comma-separated.

func (Keybindings) Match

func (b Keybindings) Match(msg tea.KeyPressMsg, id CommandID, scopes []scope) bool

Match checks whether a key press triggers the given command in the given scope priority order.

func (Keybindings) ResolveAny

func (b Keybindings) ResolveAny(msg tea.KeyPressMsg, scopes []scope) (string, bool)

ResolveAny finds any command matching a key press in the given scopes. Returns ("", false) if unmatched. Prefer Match for specific commands.

type Model

type Model struct {
	core.Workflow
	// contains filtered or unexported fields
}

func New

func New(target string, ctx context.Context, openDatabase OpenDatabase, readOnly bool) Model

func (Model) Init

func (m Model) Init() tea.Cmd

func (*Model) Service

func (m *Model) Service() sharedsql.Service

func (*Model) SetAI

func (m *Model) SetAI(client chat.Client, history chat.History)

SetAI wires the assistant provider and history store into the chat component and enables the pane.

func (*Model) SetKeybindings

func (m *Model) SetKeybindings(b Keybindings)

func (*Model) SetNoQuit

func (m *Model) SetNoQuit(noQuit bool)

SetNoQuit locks the session: every in-app quit affordance (Ctrl+C, Ctrl+Q, the header quit button, the command-palette quit entry, and the footer hints) is removed. The program still exits when its context is cancelled, so the embedding host owns the session lifecycle.

func (*Model) SetPluginControl

func (m *Model) SetPluginControl(control PluginControl)

SetPluginControl injects the live plugin lifecycle controller (the real plugin.Loader from cmd main, or a fake in tests). Without it the plugin manager shows add/remove only: no live status or restart.

func (Model) Update

func (m Model) Update(message tea.Msg) (tea.Model, tea.Cmd)

func (Model) View

func (m Model) View() tea.View

type OpenDatabase

type OpenDatabase func(context.Context, string) (sharedsql.Opened, error)

type PluginControl

type PluginControl interface {
	// Statuses returns one status per configured entry, in config order.
	Statuses() []plugin.Status
	// Restart recovers the configured entry identified by its entry
	// text or canonical path.
	Restart(ctx context.Context, identifier string) error
	// EntryForService returns the configured entry text of the plugin
	// child backing service, or "" when service is not a live session of
	// the controller's current generation.
	EntryForService(service sharedsql.Service) (string, bool)
}

PluginControl is the injected live plugin lifecycle controller: the real plugin.Loader in production, a fake in tests. The workbench never owns plugin child processes — cmd main builds the loader and hands it over through Model.SetPluginControl. Statuses never spawn, mutate, or exchange protocol traffic; Restart recovers exactly one configured entry; EntryForService reports which configured entry backs a live service (never an old generation).

Jump to

Keyboard shortcuts

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