settings

package
v0.36.0 Latest Latest
Warning

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

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

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

View Source
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

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.

View Source
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

func NextAutosaveIntervalMin(cur int) int

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.

func Save

func Save(s Settings) error

Save writes s to settings.json, creating parent directories as needed. Atomic on POSIX: writes a sibling tmpfile and renames it into place, mirroring save.Save (internal/save/save.go) so a crash mid-write can't leave a truncated config.

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
)

func (Chip) Label

func (c Chip) Label() string

Label returns the display name for c, falling back to the raw key for any Chip without an explicit label (so a future const can't silently render blank).

type LoadWarning

type LoadWarning struct {
	Path string
	Err  error
}

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

func (s Settings) AutosaveInterval() time.Duration

AutosaveInterval returns the effective interval as a duration; 0 means interval autosave is disabled.

func (Settings) AutosaveIntervalMinutes added in v0.26.0

func (s Settings) AutosaveIntervalMinutes() int

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

func (s Settings) ChipEnabled(c Chip) bool

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

func (s *Settings) SetAutosaveIntervalMin(m int)

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.

func (*Settings) SetChip

func (s *Settings) SetChip(c Chip, enabled bool)

SetChip records an explicit visibility for c, allocating the override map on first use. The Settings screen calls this on a toggle, then persists via Save.

Jump to

Keyboard shortcuts

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