config

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package config is 012's settings file: a Ghostty-style list of "key = value" lines in <user config dir>/012/config, with # comments and config-file includes. One registry (Options) says what every option is called, its type, default, environment variable, flag and meaning; the parser, `012 config`, docs/reference/config.md and the in-app Settings all come from it.

Settings are process-wide. Settings that belong to a workbook (decimal arithmetic, its locale) stay in the workbook's file; the locale option is only the default. Secrets never go here: the JEV API key lives in the OS credential store (see internal/keyring).

Index

Constants

View Source
const (
	GroupAppearance = "Appearance"
	GroupJEV        = "JEV functions"
	GroupTelemetry  = "Telemetry"
	GroupServe      = "012 serve"
	GroupData       = "Data"
	GroupShell      = "Nushell notebooks"
	GroupFiles      = "Config files"
)

Group names, in the order docs list them.

View Source
const DocsMarker = "<!-- Generated from internal/config/registry.go by `go test ./internal/config -update-docs`. Don't edit below. -->"

DocsMarker divides docs/reference/config.md: the introduction above it is written by hand, the reference below it is Reference's output.

Variables

Groups is the order groups are listed in.

View Source
var Options = []Option{
	{Name: "theme", Group: GroupAppearance, Default: "terminal", Env: []string{"O12_THEME"}, Flag: "--theme", Live: true,
		Desc: "Colors. `terminal` uses the terminal's own 16-color palette. `high-contrast` draws white on " +
			"black or black on white by the terminal's background, with WCAG AAA contrast. Any other name is a " +
			"terminal color scheme, built in (`012 config themes` lists them) or a file in the themes " +
			"directory, drawn in its own colors with solid menu and status bars. " +
			"`light:NAME,dark:NAME` picks one by the terminal's background and follows it when it changes.",
		Check: checkTheme},
	{Name: "chart-images", Kind: Bool, Group: GroupAppearance, Default: "true", Env: []string{"O12_CHART_IMAGES"}, Live: true,
		Desc: "Draw charts as images on terminals with kitty graphics (kitty, Ghostty, WezTerm) or, " +
			"outside tmux, sixel graphics (foot, xterm, mlterm, Windows Terminal). When false, charts are always text."},
	{Name: "notifications", Kind: Bool, Group: GroupAppearance, Default: "true", Env: []string{"O12_NOTIFICATIONS"}, Live: true,
		Desc: "Send a desktop notification (OSC 9) when JEV answers or an import finishes while the " +
			"terminal window is in the background."},
	{Name: "keymap", Kind: Enum, Group: GroupAppearance, Default: "default", Values: []string{"default", "vim"}, Env: []string{"O12_KEYMAP"}, Live: true,
		Desc: "Keys in the grid. `default` works like Google Sheets; `vim` adds hjkl, counts, operators, " +
			"visual selection and a : command line (File > Settings > Vim keys)."},

	{Name: "locale", Kind: Enum, Group: GroupData, Default: "en-US", Values: locale.Tags(), Env: []string{"O12_LOCALE"},
		Fallback: []string{"LC_ALL", "LC_NUMERIC", "LANG"}, Adopt: locale.FromPOSIX, Live: true,
		Desc: "How new sheets and files without a locale of their own are typed and shown: decimal and " +
			"thousands separators, date order, the currency symbol and the formula argument separator " +
			"(`;` where the decimal separator is a comma), as in Sheets' File > Settings > Locale, " +
			"which sets a file's own. Files store the same thing in every locale. " +
			"When unset, the POSIX locale (`LC_ALL`, `LC_NUMERIC`, then `LANG`, e.g. `de_DE.UTF-8`) picks it if it's one of these."},

	{Name: "max-cells", Kind: Int, Group: GroupData, Default: "10000000", Env: []string{"O12_MAX_CELLS"}, Live: true,
		Desc: "The most cells an import keeps, and a paste or fill writes at once. Numbers and text " +
			"take 20 to 60 bytes a cell and formulas about 750, so the default of ten million cells of " +
			"data is 200 to 600 MB. Imports keep whole rows " +
			"up to the budget and say how many they left out; larger pastes and fills are refused. " +
			"The grid itself is 1,048,576 rows by 16,384 columns (A to XFD) whatever this is."},

	{Name: "shell", Kind: Enum, Group: GroupShell, Default: "ask", Values: []string{"off", "ask", "on"}, Env: []string{"O12_SHELL"}, Live: true,
		Desc: "Whether notebooks run their code cells (docs/nushell/notebooks.md). `ask` runs what you write " +
			"and asks once before running the cells of a file made on another computer; `on` never asks; " +
			"`off` runs none. Opening a file never runs its cells."},
	{Name: "nu-timeout", Kind: Duration, Group: GroupShell, Default: "30s", Env: []string{"O12_NU_TIMEOUT"}, Live: true,
		Desc: "Stop a notebook cell that runs longer than this; 0 lets it run until Stop (i i) stops it."},
	{Name: "nu-config", Kind: Bool, Group: GroupShell, Default: "false", Env: []string{"O12_NU_CONFIG"}, Live: true,
		Desc: "Run notebook cells with your nushell config files (config.nu, env.nu) rather than " +
			"`nu --no-config-file`, for your own commands and aliases."},
	{Name: "nu-save-cell-kb", Kind: Int, Group: GroupShell, Default: "1024", Env: []string{"O12_NU_SAVE_CELL_KB"}, Live: true,
		Desc: "The largest output of one cell a saved file keeps, in kilobytes of NUON; a larger one is left out " +
			"and shows `not saved; run to see` when the file is opened."},
	{Name: "nu-save-notebook-kb", Kind: Int, Group: GroupShell, Default: "8192", Env: []string{"O12_NU_SAVE_NOTEBOOK_KB"}, Live: true,
		Desc: "How much of all its cells' outputs a saved file keeps, in kilobytes of NUON: the outputs that fit, " +
			"in the notebook's order."},

	{Name: "jev-api-key-command", Kind: Command, Group: GroupJEV,
		Desc: "A command that prints the TypeSafe API key, used when TYPESAFE_API_KEY isn't set and the " +
			"credential store has no key, e.g. `op read op://Private/TypeSafe/credential` or " +
			"`pass show typesafe`. It runs the first time a sheet asks JEV something, without a shell, for up to 10 seconds, and its first line of output is the key; for pipes, write " +
			"`sh -c '...'` yourself. The key itself never goes in this file."},
	{Name: "jev-credential-store", Kind: Bool, Group: GroupJEV, Default: "true", Env: []string{"O12_JEV_CREDENTIAL_STORE"},
		Desc: "Look for the API key in the OS credential store (macOS Keychain, Windows Credential Manager, " +
			"the Secret Service on Linux), where `012 config set-key` and Settings put it."},
	{Name: "jev-base-url", Kind: URL, Group: GroupJEV, Env: []string{"TYPESAFE_BASE_URL"},
		Desc:  "The TypeSafe service to ask; the SDK's default when empty. Must be https, except on localhost.",
		Check: CheckBaseURL, Redact: redactURL},
	{Name: "jev-model", Group: GroupJEV, Env: []string{"TYPESAFE_DEFAULT_MODEL"},
		Desc: "The JEV model to ask; the service's default when empty."},

	{Name: "log-file", Kind: Path, Group: GroupTelemetry, Env: []string{"O12_LOG"}, Flag: "--log",
		Desc: "Append telemetry events to this JSON log file. See docs/contributing/observability.md."},
	{Name: "log-level", Kind: Enum, Group: GroupTelemetry, Default: "info", Values: []string{"debug", "info", "warn", "error"},
		Env:  []string{"O12_LOG_LEVEL"},
		Desc: "The least severe telemetry event recorded; debug adds every frame and command."},
	{Name: "otlp-endpoint", Kind: URL, Group: GroupTelemetry, Env: []string{"OTEL_EXPORTER_OTLP_ENDPOINT"}, Flag: "--otlp",
		Desc: "Send telemetry to this OTLP/HTTP collector, e.g. http://localhost:4318. " +
			"The other OTEL_* variables still apply.",
		Redact: redactURL},

	{Name: "serve-listen", Kind: Address, Group: GroupServe, Default: "127.0.0.1:2312",
		Desc: "The address 012 serve listens on. Anything but the loopback address lets other machines " +
			"reach it (with an authorized key). See docs/terminal/ssh.md."},
	{Name: "serve-authorized-keys", Kind: Path, Group: GroupServe, Default: "~/.ssh/authorized_keys",
		Desc: "The public keys allowed to log in to 012 serve, in OpenSSH's authorized_keys format."},
	{Name: "serve-host-key", Kind: Path, Group: GroupServe,
		Desc: "012 serve's private host key, generated when missing; " +
			"ssh_host_ed25519_key in the config directory when empty."},
	{Name: "serve-idle-timeout", Kind: Duration, Group: GroupServe, Default: "30m",
		Desc: "End a 012 serve session that has had no input for this long; 0 never does."},
	{Name: "serve-max-sessions", Kind: Int, Group: GroupServe, Default: "8",
		Desc: "How many 012 serve sessions may run at once; more are turned away."},
	{Name: "serve-shell", Kind: Bool, Group: GroupServe, Default: "false",
		Desc: "Let 012 serve sessions run notebooks' code cells, as the user 012 serve runs as, " +
			"following the shell option. Off, served notebooks show their cells and saved outputs but run nothing."},

	{Name: "config-file", Kind: Path, Group: GroupFiles, Repeat: true,
		Desc: "Read another config file after this one, relative to this file's directory. " +
			"A leading `?` makes it optional: no warning when it doesn't exist."},
}

Options is every setting. Add an option here and read it with Config.String, Bool or List; parsing, `012 config`, docs/reference/config.md (go test ./internal/config -update-docs) and Settings follow.

Functions

func CheckBaseURL

func CheckBaseURL(v string) error

CheckBaseURL accepts https URLs, and http only for this machine, so a config can't send the API key anywhere in the clear.

func DefaultFile

func DefaultFile() string

DefaultFile is a config file with every option commented out at its default, each with its description: what `012 config default` prints and `012 config edit` starts a new file with.

func DefaultPath

func DefaultPath() (string, error)

DefaultPath is the main config file, <Dir>/config.

func Dir

func Dir() (string, error)

Dir is 012's config directory: $XDG_CONFIG_HOME/012 when that's set (on every OS, so tests and dotfile setups can point it anywhere), otherwise os.UserConfigDir()/012 (~/.config/012 on Linux, ~/Library/Application Support/012 on macOS, %AppData%\012 on Windows).

func Editor

func Editor(path string, getenv func(string) string) (*exec.Cmd, error)

Editor returns the command that opens path in the user's editor: $VISUAL, then $EDITOR (either may carry arguments, e.g. "code -w"), else vi, or notepad on Windows.

func EnsureFile

func EnsureFile(path string) error

EnsureFile creates the config file at path, with every option commented out at its default, when it doesn't exist yet.

func FlagUsage

func FlagUsage() string

FlagUsage lists the flags for a usage line, e.g. "[--log file]".

func IsLocalhost

func IsLocalhost(host string) bool

IsLocalhost reports whether host names this machine.

func Names

func Names() []string

Names is every option name, sorted.

func ParseFlags

func ParseFlags(args []string) (map[string]string, []string, error)

ParseFlags takes the options that have flags ("--log path" or "--log=path") out of args, returning their values by option name and the arguments left.

func Reference

func Reference() string

Reference is the option reference in Markdown, one section per group.

func SetInFile

func SetInFile(path, key, value string) error

SetInFile sets key to value in the config file at path: the last line setting key is replaced, or a line is added at the end. Comments and every other line are kept. The file and its directory are created if needed.

func SplitCommand

func SplitCommand(s string) ([]string, error)

SplitCommand splits a command line into words, as a shell would without expanding anything: spaces separate words, and single or double quotes keep spaces inside one (a backslash escapes the next character outside single quotes). No variables, globs or pipes.

func ThemesDir

func ThemesDir() string

ThemesDir is where theme files go, <Dir>/themes.

func Tilde

func Tilde(path string) string

Tilde shortens a path in the home directory to ~/..., for messages.

Types

type Config

type Config struct {
	// Path is the main config file, which may not exist.
	Path     string
	Warnings []Warning
	// contains filtered or unexported fields
}

Config is the effective configuration.

func Load

func Load(path string, getenv func(string) string, flags map[string]string) *Config

Load reads the config file at path (a missing file is fine), then applies environment variables (from getenv) and flags, which win in that order: flags > environment > config file > defaults.

func (*Config) Bool

func (c *Config) Bool(name string) bool

Bool returns a true-or-false option.

func (*Config) Duration

func (c *Config) Duration(name string) time.Duration

Duration returns a duration option.

func (*Config) Get

func (c *Config) Get(name string) Value

Get returns an option's value and where it came from.

func (*Config) Int

func (c *Config) Int(name string) int

Int returns a number option.

func (*Config) List

func (c *Config) List(name string) []Value

List returns every value of a repeatable option.

func (*Config) Override

func (c *Config) Override(name, value, why string) error

Override sets an option for the rest of the session, over every other source, e.g. a theme picked in Settings. why says who set it. An invalid value is ignored and returned as an error.

func (*Config) Show

func (c *Config) Show() string

Show writes the effective configuration: every option with its value and where it came from, values that can hold secrets redacted.

func (*Config) String

func (c *Config) String(name string) string

String returns an option's value, with ~ expanded for paths.

func (*Config) Theme

func (c *Config) Theme() ThemeChoice

Theme returns the theme choice.

type Kind

type Kind int

Kind is an option's type.

const (
	String Kind = iota
	Bool
	Enum // one of Option.Values
	Path // a file path; ~ is the home directory
	URL
	Command  // a program and its arguments, run without a shell
	Int      // a whole number, at least 1
	Duration // e.g. 30m or 1h30m; 0 for never
	Address  // host:port
)

func (Kind) String

func (k Kind) String() string

type Option

type Option struct {
	Name    string
	Kind    Kind
	Group   string   // heading in docs/reference/config.md and `012 config`
	Default string   // as it would be written in the file
	Values  []string // for Enum
	Env     []string // environment variables that set it, first set wins
	// Fallback are environment variables read, first set wins, when
	// nothing else sets the option, through Adopt, which turns their
	// value into one of the option's or "" to pass over it quietly (LANG
	// may name a locale 012 lacks).
	Fallback []string
	Adopt    func(string) string
	Flag     string // command-line flag, e.g. "--log"
	Repeat   bool   // may be given more than once; each adds a value
	Live     bool   // Reload config applies it without restarting
	Desc     string // what it does, one or more sentences
	// Check validates a value beyond its kind. Invalid values are
	// reported as warnings and the option keeps its previous value.
	Check func(string) error
	// Redact shows a value safely in `012 config`, e.g. without a URL's
	// password.
	Redact func(string) string
}

Option is one setting.

func Lookup

func Lookup(name string) (*Option, bool)

Lookup returns the option called name.

type Source

type Source struct {
	Kind SourceKind
	Name string // the file, variable or flag
	Line int    // for files
}

Source is where a value came from: the default, a line of a config file, an environment variable or a flag.

func (Source) String

func (s Source) String() string

type SourceKind

type SourceKind int

SourceKind says where a value came from.

const (
	FromDefault SourceKind = iota
	FromFile
	FromEnv
	FromFlag
)

type ThemeChoice

type ThemeChoice struct{ Light, Dark string }

ThemeChoice is the theme value: one theme, or one for each kind of terminal background.

func ParseThemeChoice

func ParseThemeChoice(v string) (ThemeChoice, error)

ParseThemeChoice parses "name" or "light:A,dark:B" (either order).

func (ThemeChoice) Pick

func (c ThemeChoice) Pick(dark bool) string

Pick returns the theme for a dark or light terminal.

func (ThemeChoice) String

func (c ThemeChoice) String() string

String is the choice as written in the file.

type Value

type Value struct {
	Raw string
	Src Source
}

Value is one setting's value and where it came from.

type Warning

type Warning struct {
	Src Source
	Msg string
}

Warning is a problem with the config that didn't stop 012: an unknown key, a bad value, a missing include. The option keeps its default.

func (Warning) Short

func (w Warning) Short() string

Short is the warning with a file in the config directory named relative to it ("config:3: ..."), to fit on the context line.

func (Warning) String

func (w Warning) String() string

Jump to

Keyboard shortcuts

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