Documentation
¶
Overview ¶
Package settings holds the player's global UI preferences — currently the default visibility of each orbit-screen Chip — persisted to a standalone settings.json under $XDG_CONFIG_HOME/terminal-space-program/.
This is application preference, not game state: it lives in global config (the theme.json precedent), applies across all saves, and is deliberately kept out of the save envelope (ADR 0010, rejected alternative "Persist prefs in the save file"). It is also kept separate from theme.json — colour and visibility are distinct concerns.
The package is pure data + persistence with no UI and no upward dependency: the tui reads a Settings value and the Settings screen mutates it through SetChip; nothing here imports the tui.
Index ¶
Constants ¶
const DefaultAutosaveIntervalMin = 5
DefaultAutosaveIntervalMin is the periodic-autosave default (real minutes) when the player hasn't set one — ADR 0033 §E's 5 minutes.
Variables ¶
var AllChips = []Chip{ ChipTarget, ChipStages, ChipNodes, ChipLaunch, ChipDescent, ChipChute, ChipCapture, ChipFrameTransition, ChipAttitude, ChipProjectedOrbit, ChipSOIPass, ChipMissions, ChipComms, }
AllChips is the canonical, display-ordered list of toggle-able Chips. The Settings screen (slice 3) iterates this — never the underlying map, whose iteration order is unspecified — so toggles render in a stable order. Append-only: order is part of the UI contract.
var AutosaveIntervalSteps = []int{0, 1, 5, 10, 15, 30}
AutosaveIntervalSteps is the cycle the Settings screen's autosave-interval row walks, in order: off, then increasing real- minute intervals. Display-ordered and append-sensitive like AllChips.
Functions ¶
func Load ¶
func Load() (Settings, []LoadWarning)
Load reads settings.json and returns the player's preferences. A missing file is the common case and yields Default() (all Chips visible) with no warning. A present-but-partial file fills only the keys it names, leaving every other Chip at its visible default. A parse or I/O error yields Default() plus a LoadWarning, so the caller can surface it without the app losing a working configuration.
Idempotent: Load reads a file and never mutates global state, so repeated calls with the same file return equivalent values.
func NextAutosaveIntervalMin ¶ added in v0.26.0
NextAutosaveIntervalMin returns the step after cur in AutosaveIntervalSteps, wrapping from the last back to the first (off). A cur outside the canonical list — a hand-edited settings.json — re-enters the cycle at the first step rather than being unreachable forever.
func Path ¶
func Path() string
Path returns the location of settings.json: $XDG_CONFIG_HOME/terminal-space-program/settings.json, falling back to ~/.config/... when XDG_CONFIG_HOME is unset — mirroring theme.json's userThemePath (internal/render/theme.go). Returns "" if the home directory cannot be resolved and XDG is unset.
Types ¶
type Chip ¶
type Chip string
Chip identifies one toggle-able orbit-screen Chip — the contextual blocks that ADR 0010 moves out of the slim HUD column and onto canvas corners. The string value is the stable JSON key in settings.json.
The Navball is intentionally absent: it is a Panel, not a Chip (CONTEXT.md §"HUD & overlays"), and whether it gains a Settings toggle is a live v0.13 open question. If it does, adding a ChipNavball const to AllChips is sufficient — the on-disk map tolerates the new key.
const ( ChipTarget Chip = "target" ChipStages Chip = "stages" ChipNodes Chip = "nodes" ChipLaunch Chip = "launch" ChipDescent Chip = "descent" ChipChute Chip = "chute" ChipCapture Chip = "capture" ChipFrameTransition Chip = "frameTransition" ChipAttitude Chip = "attitude" ChipProjectedOrbit Chip = "projectedOrbit" ChipSOIPass Chip = "soiPass" ChipMissions Chip = "missions" // v0.21 (ADR 0025): in-flight mission checklist ChipComms Chip = "comms" // v0.23 (ADR 0027): CommNet link status )
type LoadWarning ¶
LoadWarning reports a non-fatal problem reading settings.json (a parse failure or an I/O error other than "file absent"). Defined locally so this package mirrors render.LoadWarning / bodies.LoadWarning without importing either. On any warning Load still returns a usable Settings (the all-on Default), so a corrupt file degrades to defaults rather than blocking startup.
func (LoadWarning) Error ¶
func (w LoadWarning) Error() string
type Settings ¶
type Settings struct {
// ChipVisibility records only the Chips the player has explicitly
// overridden. A Chip absent from the map (or a nil map) is visible by
// default, so the defaults-all-on behaviour costs zero bytes on disk
// and unknown keys from a newer build are tolerated and ignored.
ChipVisibility map[Chip]bool `json:"chips,omitempty"`
// TutorialEnabled / ChallengesEnabled gate the two built-in mission
// programs (ADR 0025 §2 / v0.21 Slice 7). Both default false — a fresh
// sandbox shows no missions, chip, or evaluation until the player opts in
// via the Settings screen. The tui maps these to the set of enabled
// program names it pushes down to the World evaluator. omitempty keeps the
// default-off state costing zero bytes on disk (an absent field is off).
TutorialEnabled bool `json:"tutorialEnabled,omitempty"`
ChallengesEnabled bool `json:"challengesEnabled,omitempty"`
// KeyboardLayout names the player's physical keyboard layout (ADR 0022),
// e.g. "qwerty" or "qwertz". The tui maps it to a keylayout.Layout to
// normalize keypresses to QWERTY positions before binding-matching.
// Empty (the common case / absent field) means QWERTY. Stored as a raw
// string so this package keeps zero dependency on keylayout — the tui
// owns resolution and validation.
KeyboardLayout string `json:"keyboardLayout,omitempty"`
// AutosaveIntervalMin is the wall-clock interval, in real minutes,
// between periodic autosaves into the rotating ring (v0.26 S4 /
// ADR 0033 §E). A pointer so the two meaningful "empty" states stay
// distinct under omitempty: nil (absent field — the common case)
// means the 5-minute default, while an explicit 0 means "off"
// (interval autosave disabled; the on-quit autosave still fires).
// Read through AutosaveInterval / AutosaveIntervalMinutes rather
// than dereferencing directly.
AutosaveIntervalMin *int `json:"autosaveIntervalMin,omitempty"`
}
Settings is the on-disk shape of settings.json. The zero value is a valid all-defaults configuration (every Chip visible), which is exactly what an absent file represents. A top-level struct (rather than a bare map) reserves room for future, non-visibility preferences — units, and so on — without a breaking change.
func Default ¶
func Default() Settings
Default returns the all-defaults Settings: every Chip visible, no overrides recorded. This is the in-memory equivalent of a missing settings.json and preserves the pre-ADR-0010 behaviour where every block showed.
func (Settings) AutosaveInterval ¶ added in v0.26.0
AutosaveInterval returns the effective interval as a duration; 0 means interval autosave is disabled.
func (Settings) AutosaveIntervalMinutes ¶ added in v0.26.0
AutosaveIntervalMinutes returns the effective periodic-autosave interval in real minutes: the default when unset, 0 when disabled. A hand-edited negative value clamps to 0 (off) rather than yielding a nonsense negative duration.
func (Settings) ChipEnabled ¶
ChipEnabled reports whether Chip c should be shown by default. Absent from the override map means visible — so a missing file, a partial file, and an unknown key all resolve to the all-on default.
This answers only the Settings half of the slice-2 render rule (enabled && relevant && !declutter); relevance and declutter live in the tui.
func (*Settings) SetAutosaveIntervalMin ¶ added in v0.26.0
SetAutosaveIntervalMin records an explicit interval (0 = off). A fresh pointer per call, so Settings values copied around the tui never alias each other's interval.