summaryrefslogtreecommitdiff
path: root/docs/config.md
blob: 6485d46a06a404c613f95c9ccdc7420658d18785 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# Startup configuration

Native pardes builds read a per-user `pardes` file before the first frame:

- Unix: `$XDG_CONFIG_HOME/pardes`, falling back to `~/.config/pardes`.
- macOS: `$XDG_CONFIG_HOME/pardes` when that variable is set, otherwise
  `~/Library/Application Support/pardes`.
- Windows: `%LOCALAPPDATA%\pardes`, with `%USERPROFILE%\AppData\Local\pardes`
  as the fallback.

On the two unixes `XDG_CONFIG_HOME` counts only when it is ABSOLUTE, as the
XDG base-directory specification requires; an empty or relative value falls
back to the home-directory form. Windows never consults it. A file of 1 MiB or
more, or one that cannot be read, is treated as no file at all — the path
still resolves, because "nothing is there yet" is the answer `Config` exists
to give. There is one case with no path at all: a native launch with no `HOME`
set, which `Config` reports as such.

`Config` (`SPC f c`, or the word executed anywhere) opens one refreshable
`+Config` pane. It reports the startup path and every live config-like value:
theme, colors, wrapping, tag position, debug mode, the requested shell and the
executable actually resolved at the last spawn, requested/effective GUI font
and size, tagline scale, panel transition,
scene effects, hover delay, platform, native-image support, and (on SDL) whether
the executable uses live-built shaders or the paired prebuilt shader snapshot.
Platform-dependent rows say `unsupported` instead of looking like an off or
empty supported setting: TTY reports Font and scene shaders as unsupported;
web reports Font, panel transitions, and scene shaders as unsupported. Tagline
font size is its own row and capability — GUI font selection is native-only,
while the browser still applies the compiled tagline percentage to its DOM.
The startup path is printed whether or not a file exists — that is usually when
it is most useful — and is ordinary selectable text, so a right click on it
opens the file. Shell follows the same requested/effective/pending model as
Font. `Compiled default shell` is the command built into the binary; `Shell
effective (last spawn)` is the executable the native host really chose after
installation lookup and fallback. A changed request remains pending until a
terminal is spawned, because the core does not resolve native executables.

The mutable global values live together in the plain `runtime_config.State` record.
One plain capability record gates the setting registry, leader table,
`EffectCode`, and report; the compile-time setting table generates both setter
builtins and their `Config` rows. Exhaustive checks require every table-backed
toggle, transition, and scene-effect switch to occur exactly once, so those
generated setting builtins cannot quietly lose their query row or leave a
renderer switch unnamed. Manual pane-local actions remain with their payload (for
example an image tag reports its renderer choices); they are not global
configuration.

The browser build has no local user-config path and does not load this file.
(Nor does it have `Font`, the effect builtins or `EffectCode`, a language
backend, or ptys of its own — see `docs/web.md`.)

The format is one existing builtin command per line, using the same spelling
and argument parsing as commands executed inside pardes:

```text
Theme acme
Font DejaVuSansMono-Regular
TaglineSize 82
Shell zsh
Wrap
```

A line matches a builtin whose name takes NO argument only as that whole word:
`Kill` runs, `Kill something` does not. Builtins that take one (`Theme`,
`Font`, `TaglineSize`, `Shell`, `Restore`, `Find`, `Grep`, `Rename`,
`WsSymbols`, `Look`, `Exec`, `EffectCode`) take everything after the name as
the argument.

`Theme <name>` wants one of the 228 names in the ring. Do not derive the
spelling — read it off `ThemeSel` (`SPC t t`), which lists every one as the
exact `Theme <name>` line that selects it. The generator lowercases, folds
punctuation runs to a single `_` and then TRIMS leading and trailing ones
(`penumbra+.toml` is `penumbra`, not `penumbra_`), and it suffixes every theme
that came from zed with `_zed` so it cannot collide with a helix theme of the
same name (zed's "Ayu Mirage" is `ayu_mirage_zed`; `ayu_mirage` is helix's).
A name that is not in the ring is ignored.

`Shell <name>` sets the binary that the NEXT terminal pane execs; panes
already open keep the shell they are running. A bare name is resolved against
the handful of directories a shell actually lives in, not `$PATH`.

`Font` and `FontSel` exist ONLY in the SDL GUI and native macOS builds — a
terminal's font belongs to its emulator and a browser's to the page — so a
`Font` line is one of the silently-ignored ones everywhere else. Both builds
resolve the name by walking the font directories on every lookup, so a face
installed a moment ago is findable.

`Font` is asynchronous at the renderer boundary. `Config` therefore keeps
requested name/path, pending state, and the effective face/point-or-pixel size
as separate facts; a failed request never gets reported as the face on screen.
Taglines use a distinct face size in both native GUI renderers. Execute
`TaglineSize <percent>` to change it live, for example `TaglineSize 70`; the
accepted range is 1 through 100 and the default comes from
`gui_tagline_font_percent` in `src/config.zig` (82). The native renderer
remeasures both the glyph and its visible tag band while retaining the body's
cell grid. The 100% ceiling is deliberate: a tagline remains exactly one
logical grid row, so a larger face or band would overlap its pane body or a
neighbour instead of leaving the body grid stable. `Config` reports the active
percentage. The browser applies the same compiled percentage to its DOM glyphs
but has no runtime setter.

The SDL GUI joins the reduced-height global and pane tagline bands with
`gui_topbar_pane_border_px` physical pixels. Set it to zero for a direct join.
`gui_topbar_pane_border_rgb` can pin an RGB color; its default `null` follows
the active theme's scrollbar-track color. With `Tagbottom` enabled, a tagline
on the final grid row is bottom-aligned so the same unused half-band does not
show beneath it.

What happens to a codepoint the chosen face has no glyph for differs by shell.
The SDL GUI falls back through a chain it builds itself: embedded Adwaita
Mono, then installed `NotoSansMono-Regular`, `DejaVuSansMono`,
`SymbolsNerdFont-Regular`, `NotoSansSymbols2-Regular`,
`NotoSansSymbols-Regular`, and `DejaVuSans`, in that order, missing entries
skipped; the rasterized glyphs are retained in its GPU atlas. The macOS shell
has none of that and needs none: it embeds no font, substitutes the system
monospaced face (else Menlo) when the NAME you asked for will not load, and
leaves per-codepoint fallback to CoreText's own cascade when it draws. What it
caches is glyph ids, not pixels.

Blank, unknown, malformed, or unsuccessful lines are ignored silently, and a
bad line does not prevent later lines from running. Top-level text that is not
a builtin is not sent to a shell. (`Exec ...` remains an ordinary builtin and
therefore keeps its normal behavior.) Key bindings remain compile-time choices
in `src/config.zig`; this startup file does not remap them.

## Panel and scene effects

Exactly one panel transition is selected at a time. Executing its builtin a
second time turns it off; selecting another replaces it:

```text
PanelSlide
PanelZoom
PanelDissolve
PanelAscii
PanelVertical
```

All panel transitions start off. Slide uses cubic ease-out and zoom uses an
overshooting ease-out-back. Dissolve and ASCII compare the last successfully
presented grid with the new one. Dissolve switches visually changed cells at
stable noise thresholds. ASCII walks every changed single-byte printable glyph
from its old `u8` value to its new one. Nearby values increment or decrement
once per frame; longer distances use ease-out character skips, moving quickly
at first and settling exactly on the destination. Glyph-stable style changes
and non-ASCII graphemes become canonical immediately. A walk is capped at
twelve movement frames, and each pane lasts only as long as its longest walk.
The core computes and composes that semantic diff once for every backend;
pixel attachments, which have no character value, pass through unchanged.
Vertical is a pane-lifecycle effect: a newly added
pane rises from below inside its own fixed box, and a deleted pane's frozen
content drops back down; surviving panes are never animated. The TTY
implementation performs its remaining geometry/dissolve operations directly
on a copy of the core-composed presentation grid.
The SDL and native macOS GUI implementations pass plain panel tracks to their
GPU shaders, including native image/PDF pixels; layout itself commits
immediately and remains the one authoritative geometry. DOM web intentionally
does not expose these builtins: its renderer is selectable HTML/CSS and has no
canvas or shader stage.

The scene effects are independent switches and can be combined:

```text
Crt
Ripple
Glitch
```

They share one full-scene shader pass in SDL and macOS. With all three off the
pass is bypassed. CRT works in linear light with restrained scanlines, mask,
bloom, curvature, and noise rather than remapping the theme to a strong fixed
palette; Ripple and Glitch primarily perturb sample coordinates.

`EffectCode <effect-builtin>` opens the build-embedded effect math, host
paint/submission path, and backend shader/grid sources, for example
`EffectCode PanelAscii` or, in a GUI build, `EffectCode Crt`. TTY exposes it
for its grid transitions; native GUI builds
expose it for transitions and scene shaders. It is absent on web, where no
effect argument could succeed. Shared
passes are shown as shared source segments rather than manufactured per-effect
copies. The command works from an installed binary and does not need the source
checkout beside it. SDL output also labels its shader provenance. An ordinary
build prints the live GLSL that `glslc` compiled for that executable;
`-Dprebuilt-shaders` prints the tracked GLSL snapshot paired with the committed
SPIR-V instead and labels those segments with their `shaders/prebuilt/` paths.
`zig build shaders` refreshes both files of every pair together,
so editing live GLSL without that explicit refresh changes neither half of a
prebuilt executable.

## Delayed Look preview

The preview is enabled by default. Moving the pointer onto selectable text and
leaving it still for `look_preview_delay_frames` (2 animation ticks, roughly
33 ms at the 60 Hz animation cadence) paints a
subtle theme-derived preview of the exact operand a right-click Look would receive.
Repeated motion reports in the same semantic grid cell do not restart the
delay. The preview uses the same side-effect-free word/path expansion as Look;
it does not focus a pane, move a cursor, install a selection, activate a PDF
page, or execute anything. Motion to another operand, pointer leave, input,
pane teardown, and relevant content changes cancel it.

Set this compile-time option in `src/config.zig` to disable the feature:

```zig
pub const look_preview_delay_frames: ?u16 = null;
```