Attempt to improve the multicharacter detection code.

This commit is contained in:
Storm Dragon committed 2026-10-29 14:01:30 -04:00
1 parent 6fc3416a1b
commit 3cf41e662c
12 files changed
+1135 -843

No files matched your search

+495 -125
View File
@@ -86,90 +86,68 @@ review.
.IP \(bu 2
\f[B]Previous / current / next line\f[R]
.RS 2
.PP
Desktop: Keypad 7 / 8 / 9
.PP
Laptop: Fenrir+U / I / O
\f[B]Desktop:\f[R] Keypad 7 / 8 / 9
\f[B]Laptop:\f[R] Fenrir+U / I / O
.RE
.IP \(bu 2
\f[B]Previous / current / next word\f[R]
.RS 2
.PP
Desktop: Keypad 4 / 5 / 6
.PP
Laptop: Fenrir+J / K / L
\f[B]Desktop:\f[R] Keypad 4 / 5 / 6
\f[B]Laptop:\f[R] Fenrir+J / K / L
.RE
.IP \(bu 2
\f[B]Previous / current / next character\f[R]
.RS 2
.PP
Desktop: Keypad 1 / 2 / 3
.PP
Laptop: Fenrir+M / Comma / Period
\f[B]Desktop:\f[R] Keypad 1 / 2 / 3
\f[B]Laptop:\f[R] Fenrir+M / Comma / Period
.RE
.IP \(bu 2
\f[B]Top / bottom of screen\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad 7 / 9
.PP
Laptop: Fenrir+Shift+U / O
\f[B]Desktop:\f[R] Fenrir+Keypad 7 / 9
\f[B]Laptop:\f[R] Fenrir+Shift+U / O
.RE
.IP \(bu 2
\f[B]Line start / end\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad 4 / 6
.PP
Laptop: Fenrir+Shift+J / L
\f[B]Desktop:\f[R] Fenrir+Keypad 4 / 6
\f[B]Laptop:\f[R] Fenrir+Shift+J / L
.RE
.IP \(bu 2
\f[B]First / last text on line\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad 1 / 3
.PP
Laptop: Fenrir+Control+J / L
\f[B]Desktop:\f[R] Fenrir+Keypad 1 / 3
\f[B]Laptop:\f[R] Fenrir+Control+J / L
.RE
.IP \(bu 2
\f[B]Read screen\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad 5
.PP
Laptop: Fenrir+Shift+K
\f[B]Desktop:\f[R] Fenrir+Keypad 5
\f[B]Laptop:\f[R] Fenrir+Shift+K
.RE
.IP \(bu 2
\f[B]Screen before / after cursor\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad 8 / 2
.PP
Laptop: Fenrir+Shift+I / Comma
\f[B]Desktop:\f[R] Fenrir+Keypad 8 / 2
\f[B]Laptop:\f[R] Fenrir+Shift+I / Comma
.RE
.IP \(bu 2
\f[B]Character above / below\f[R]
.RS 2
.PP
Desktop: Fenrir+Control+Keypad 8 / 2
.PP
Laptop: Fenrir+Control+I / Comma
\f[B]Desktop:\f[R] Fenrir+Control+Keypad 8 / 2
\f[B]Laptop:\f[R] Fenrir+Control+I / Comma
.RE
.IP \(bu 2
\f[B]Follow cursor\f[R]
.RS 2
.PP
Desktop: Fenrir+Keypad Period
.PP
Laptop: Fenrir+Slash
\f[B]Desktop:\f[R] Fenrir+Keypad Period
\f[B]Laptop:\f[R] Fenrir+Slash
.RE
.IP \(bu 2
\f[B]Review position\f[R]
.RS 2
.PP
Desktop: Keypad Period
.PP
Laptop: Fenrir+Shift+Period
\f[B]Desktop:\f[R] Keypad Period
\f[B]Laptop:\f[R] Fenrir+Shift+Period
.RE
.PP
Press the current\-line or current\-word shortcut twice quickly to spell
@@ -215,7 +193,13 @@ application.
Character echo, word echo, and cursor echo can be configured separately.
Punctuation levels are \f[CR]none\f[R], \f[CR]some\f[R],
\f[CR]most\f[R], and \f[CR]all\f[R].
Character review still names punctuation.
At \f[CR]some\f[R] and \f[CR]most\f[R], punctuation inside words, URLs,
email addresses, and filenames is also named.
Apostrophes within words and single numeric separators such as those in
\f[CR]3.14\f[R], \f[CR]1,000\f[R], and \f[CR]12:30\f[R] follow the
selected level.
Sentence punctuation follows the selected level too.
Character review always names punctuation.
Capital indicators, emoticons, repeated\-symbol summaries, indentation
feedback, and attribute feedback are configurable in Reading.
.PP
@@ -239,7 +223,8 @@ Activate \f[B]OK\f[R] to save, or \f[B]Cancel\f[R] or Escape to discard
the form\(cqs changes.
.PP
Speech rate, pitch, and volume use a scale from \-100 to 100.
For speech rate, Up and Down change the value by 10; Left and Right change it by 1.
For speech rate, Up and Down change the value by 10; Left and Right
change it by 1.
Sound volume is between 0.0 and 1.0.
Backend, device, keyboard layout, sound theme, and other launch\-only
settings take effect on the next start.
@@ -267,38 +252,374 @@ Quick settings work without opening the form:
.IP \(bu 2
\f[B]Fenrir+Space\f[R]
.RS 2
.PP
Action: Announce current setting
\f[B]Action:\f[R] Announce current setting
.RE
.IP \(bu 2
\f[B]Fenrir+Left / Right\f[R]
.RS 2
.PP
Action: Previous / next setting
\f[B]Action:\f[R] Previous / next setting
.RE
.IP \(bu 2
\f[B]Fenrir+Control+Left / Right\f[R]
.RS 2
.PP
Action: Previous / next category
\f[B]Action:\f[R] Previous / next category
.RE
.IP \(bu 2
\f[B]Fenrir+Up / Down\f[R]
.RS 2
.PP
Action: Change value
\f[B]Action:\f[R] Change value
.RE
.IP \(bu 2
\f[B]Fenrir+Control+S\f[R]
.RS 2
.PP
Action: Save settings
\f[B]Action:\f[R] Save settings
.RE
.PP
Quick changes apply to the current session.
Save to retain them for future launches.
Session controls such as mute and temporary silence are separate from
saved startup preferences.
.SS Application overrides
Press \f[B]Fenrir+A\f[R] to open \f[B]Applications\f[R].
Up and Down select an item; Enter activates it and closes the menu.
Escape or the Cancel button closes the menu without changing the
selection.
Tab and Shift+Tab move between the list, Copy alias to clipboard,
Cancel, and the tab selector.
The active override is initially selected.
.PP
Type the start of a name to jump to it: \f[B]n\f[R] selects
NetworkManager, then \f[B]i\f[R] selects Ninjam.
Searching ignores letter case and does not activate the item.
Backspace removes a search character; Control+Backspace clears the
search.
Up, Down, or moving focus away from the list also clears the search.
Unmatched characters announce \f[B]No matches\f[R] and leave the last
matching search intact.
.PP
Start the application normally, then select its override.
This menu does not launch programs.
Choose \f[B]Default\f[R] to restore the settings and reading regions
that were in effect before the override.
Overrides are built into Fenrir and are never selected automatically or
remembered across restarts.
.PP
To launch a program with its override, select its name in this list,
then Tab to \f[B]Copy alias to clipboard\f[R] and press Enter.
This copies a Bash alias into Fenrir\(cqs clipboard without selecting
the override or closing the menu.
Paste it into your Bash configuration, such as \f[CR]\(ti/.bashrc\f[R],
and load that configuration in a new shell.
The aliases use the executable names \f[CR]cninjam\f[R],
\f[CR]nmtui\f[R], \f[CR]rogue\f[R], and \f[CR]codex\f[R]; Default has no
alias.
Existing aliases with those names are replaced when you load the
definition.
.PP
The alias requests the override through \f[CR]socat\f[R], then launches
the real program with the arguments you supplied.
Errors remain visible, and the program still launches if the request
fails, remote control is disabled, or Fenrir or \f[CR]socat\f[R] is
missing.
Socket inactivity is limited to two seconds.
It uses the standard socket, or your configured
\f[CR]remote.socket_file\f[R], rather than a process\-specific socket
that changes at restart.
Paste with Fenrir\(cqs clipboard command; desktop clipboard
synchronization follows your normal clipboard settings.
.PP
While an override is active, \f[B]Fenrir+F\f[R] opens its application
settings, with the application name in the title.
\f[B]OK\f[R], \f[B]Fenrir+Control+S\f[R], and remote
\f[CR]SETTING SAVE\f[R] save that application\(cqs preferences.
Quick and remote changes remain temporary until saved.
Default settings are kept separately, including any unsaved adjustments
made before activating the override.
.PP
Profiles live in an \f[CR]applications/\f[R] subdirectory of the
ordinary settings save directory.
For example:
.IP \(bu 2
System settings:
\f[CR]/etc/fenrirscreenreader/settings/applications/ninjam.toml\f[R].
.IP \(bu 2
Personal settings:
\f[CR]\(ti/.local/share/stormux/fenrirscreenreader/settings/applications/ninjam.toml\f[R].
.IP \(bu 2
With \f[CR]\-\-config /path/settings.toml\f[R]:
\f[CR]/path/applications/ninjam.toml\f[R].
.PP
NetworkManager uses \f[CR]networkmanager.toml\f[R]; Rogue uses
\f[CR]rogue.toml\f[R]; Codex uses \f[CR]codex.toml\f[R].
The directory and file are created on the first successful save.
Files contain only customized settings; omitted values inherit ordinary
settings followed by the built\-in application defaults.
A customized voice selection saves module, language, and voice together
so a later change to the ordinary voice does not break that selection.
Profiles are loaded when their override first recognizes the
application; restarting Fenrir still starts with Default.
Reselect the application to reload an edited file.
.PP
Application settings include voice, rate, pitch, volume, reading
behavior, sound enablement/volume, and typing echo.
Startup settings such as speech driver, serial device, keyboard layout,
and sound theme remain in the default menu; clipboard storage and
console routing also remain global.
Session mute and the temporary automatic\-reading toggle are not
implicitly saved.
Remote \f[CR]SAVEAS\f[R] and \f[CR]screen#ignore_screen\f[R] are
unavailable while an application is active.
Saving is blocked during context transitions or failed voice
restoration.
A malformed profile or unavailable voice leaves ordinary settings in
effect and reports an error.
Select the application again after correcting the file.
.PP
For example, a rate\-only profile contains current TOML setting names,
with no top\-level \f[CR]version\f[R] field:
.IP
.EX
\f[B][presentation.speech]\f[R]
rate = 40
.EE
.PP
To make a saved value inherit again, remove that setting from the
application file and reselect the override.
Removing the file restores complete inheritance.
.PP
An override belongs to its terminal.
Switching VTs or leaving the terminal suspends its effects; returning
resumes it when the application screen is recognized.
Unrecognized screens use ordinary reading.
A fresh shell prompt on the cursor row, with the application interface
absent, clears the selection and announces \f[B]Default settings
restored\f[R].
This works from screen contents, so it does not require access to remote
processes over SSH or inside GNU Screen.
Unusual prompts may require selecting Default manually.
Password prompts, confirmation questions, and old shell prompts in
scrollback do not clear it.
Split windows, heavily customized application colors, and localized or
unfamiliar layouts may prevent recognition; Default is always available.
.PP
\f[B]NetworkManager\f[R] targets \f[CR]nmtui\f[R] and temporarily
selects highlight tracking.
.PP
\f[B]Ninjam\f[R] targets the \f[CR]cninjam\f[R] curses client.
It announces selected controls with master, metronome, or channel
context; mute, transmit, and receive controls are spoken as states.
While adjusting a volume/pan control, Left/Right announces only the pan
percentage and direction, or center; Up/Down announces only the volume,
with minus and plus spoken explicitly.
Peak meters and the interval bar remain quiet.
Navigating the application\(cqs controls after manual review resumes
tracking; passive updates leave review in place.
Incoming chat is announced independently of control changes.
The following shortcuts temporarily replace numbered region reads:
.IP \(bu 2
\f[B]Fenrir+1\f[R]
.RS 2
\f[B]Ninjam information:\f[R] Latest new chat message received since
activation
.RE
.IP \(bu 2
\f[B]Fenrir+2\f[R]
.RS 2
\f[B]Ninjam information:\f[R] Selected channel or control
.RE
.IP \(bu 2
\f[B]Fenrir+3\f[R]
.RS 2
\f[B]Ninjam information:\f[R] Connection, tempo, and interval position
.RE
.PP
Fenrir+Shift+B lists these application assignments.
Existing user regions are preserved and restored when the override ends.
Review, Read Screen, and copying continue to expose the actual terminal
text, including its literal \f[CR]X\f[R] marks.
Chat history is baselined on activation, resize, buffer changes, and
history paging to avoid announcing old messages as new.
Messages that appear and disappear between screen captures cannot be
recovered reliably.
.PP
The laptop shortcut for reading attributes is \f[B]Fenrir+Shift+A\f[R];
Fenrir+A opens Applications in both layouts.
.PP
\f[B]Rogue\f[R] targets the classic English Rogue 5.4 terminal game,
including the 5.4.4 package.
Start \f[CR]rogue\f[R], then select \f[B]Rogue\f[R] with
\f[B]Fenrir+A\f[R] (type \f[B]r\f[R], then Enter).
The override announces messages and prompts, including \f[B]More; press
Space\f[R], changes in health, hunger, dungeon level, strength, armor,
and experience level, and newly visible monsters, objects, doors,
stairs, and traps.
Ordinary map redraws stay quiet.
Moving monsters are compared by letter and count to reduce repeated
announcements.
Their current positions remain available on request.
Appearing and disappearing messages between captures, or one monster
replacing another of the same letter without a count change, cannot
reliably be distinguished from the visible display alone.
.IP \(bu 2
\f[B]Fenrir+1\f[R]
.RS 2
\f[B]Rogue information:\f[R] Health, for example \(lqHealth: 12 of
12\(rq
.RE
.IP \(bu 2
\f[B]Fenrir+2\f[R]
.RS 2
\f[B]Rogue information:\f[R] Full status line
.RE
.IP \(bu 2
\f[B]Fenrir+3\f[R]
.RS 2
\f[B]Rogue information:\f[R] Latest message or prompt
.RE
.IP \(bu 2
\f[B]Fenrir+4\f[R]
.RS 2
\f[B]Rogue information:\f[R] Eight neighboring cells, clockwise from
north
.RE
.IP \(bu 2
\f[B]Fenrir+5\f[R]
.RS 2
\f[B]Rogue information:\f[R] Visible monsters and their positions
relative to you
.RE
.IP \(bu 2
\f[B]Fenrir+6\f[R]
.RS 2
\f[B]Rogue information:\f[R] Visible objects and landmarks, with
relative positions
.RE
.PP
These explicit reads include their region names.
Names are supported by the shared application\-region API, so other
overrides can use them as needed.
\f[B]Fenrir+Shift+B\f[R] lists the assignments.
Slots 7 through 10 remain available for manual regions.
Existing user regions are preserved while the override is active and
restored when it ends, as with Ninjam.
.PP
Directions give cell offsets, for example \(lqbat, north 2, east 3.\(rq
Descriptions use only displayed symbols; they do not reveal hidden
monsters, secret doors, or unidentified items.
Blank cells are described as unseen, and hallucination or disguised
monsters can make the displayed symbols misleading.
The playfield uses the first 24 rows and 80 columns even in a larger
terminal, with status on row 24.
Inventory, help, and options pages use ordinary reading and review; map
regions report information unavailable on those pages.
Slow inventory uses the ordinary message region.
Read Screen, review, and copying retain the actual terminal text.
Unrecognized screens return to ordinary reading.
.PP
Developers can exercise an installed classic Rogue in private PTYs
without touching the active reader:
.IP
.EX
FENRIR_ROGUE_TEST_BINARY=/usr/bin/rogue go test ./internal/terminal \-run TestRogueLiveOverride \-v
.EE
.SS Codex CLI
The \f[B]Codex\f[R] override replaces automatic terminal diffs with
completed assistant messages.
It suppresses tool output, streaming fragments, and redraws.
Manual screen review remains available, and typing echo is limited to
the composer.
Messages are retained in memory even while speech is muted or automatic
reading is disabled.
Existing lifecycle alerts remain separate from reply reading.
Left/Right navigation retains character feedback inside the composer.
While Codex is working, the existing activity tone sounds once every
four seconds without requiring redraws.
It stops for approval/question waits and completion, respects the sound
and progress toggles, and remains independent of speech mute.
.IP \(bu 2
\f[B]Fenrir+1 through Fenrir+9\f[R]
.RS 2
\f[B]Codex information:\f[R] Recent completed assistant messages, newest
first
.RE
.IP \(bu 2
\f[B]Fenrir+0\f[R]
.RS 2
\f[B]Codex information:\f[R] Working, ready, waiting for approval or an
answer, finished, or interrupted
.RE
.PP
Select \f[B]Codex\f[R] with \f[B]Fenrir+A\f[R], type \f[B]c\f[R], then
Enter.
Select \f[B]Default\f[R] to leave the override.
Without its bridge, the override suppresses automatic screen changes and
the status shortcut says \f[B]Waiting for Codex bridge\f[R].
.PP
The optional bridge requires Python 3 and Fenrir remote command control
enabled.
Merge a command hook invoking
\f[CR]python3 /absolute/path/to/fenrir/tools/codex_bridge.py\f[R] into
each of these events in \f[CR]\(ti/.codex/hooks.json\f[R]:
\f[CR]SessionStart\f[R], \f[CR]UserPromptSubmit\f[R],
\f[CR]PermissionRequest\f[R], \f[CR]PostToolUse\f[R], \f[CR]Stop\f[R],
\f[CR]Interrupt\f[R], and \f[CR]SessionEnd\f[R].
For example, one event entry is:
.IP
.EX
{
\(dqhooks\(dq: {
\(dqSessionStart\(dq: [{\(dqhooks\(dq: [{\(dqtype\(dq: \(dqcommand\(dq, \(dqcommand\(dq: \(dqpython3 /absolute/path/to/fenrir/tools/codex_bridge.py\(dq, \(dqtimeout\(dq: 3}]}]
}
}
.EE
.PP
Preserve existing hooks.
Review and trust the added hooks through Codex\(cqs \f[CR]/hooks\f[R]
interface; restart or resume Codex if required by the installed version.
Starting or resuming a conversation starts a detached bridge follower;
submitting a prompt also restarts it if necessary.
The bridge never speaks or answers approvals.
.PP
The follower reads only the transcript path supplied by that
conversation\(cqs hook and verifies its session identifier.
It accepts completed assistant events, never tool results, reasoning, or
streamed deltas.
It keeps the nine latest replies in memory and writes only status,
conversation identifiers, and lock files to a private runtime directory.
Switching conversations replaces the terminal binding; packets from an
older conversation cannot overwrite the new history.
Existing history is loaded silently on attachment or bridge restart.
Long replies are transported in chunks and announced only after
assembly; the current per\-message limit is 1 MiB.
The worker stops when Codex exits or a \f[CR]SessionEnd\f[R] hook runs.
.PP
X11 routing requires the same \f[CR]WINDOWID\f[R] as the Fenrir
instance; Linux console routing uses Codex\(cqs controlling VT and the
reader\(cqs existing authorization.
Other windows and consoles do not receive the replies.
This local bridge does not forward SSH audio or attach a remote Codex
server to a local terminal.
.PP
The transcript parser was checked against Codex CLI 0.165.0.
It uses Codex\(cqs local completed\-event records, rather than a public
subscription API; a changed record format may require an update.
Status comes from hooks and recorded turn events, not the terminal\(cqs
animated activity label.
Check \f[B]Fenrir+0\f[R] after resuming.
.PP
For a private protocol and keyboard test without live speech or Codex
requests:
.IP
.EX
go build \-o fenrir ./cmd/fenrir
python3 \-m unittest discover \-s tests \-p test_codex_bridge.py
xvfb\-run \-a env FENRIR_PRIVATE_X11=1 python3 tests/native_codex.py
.EE
.PP
Real acceptance still needs a Codex reply spoken once after completion,
working status on demand, history review, composer typing,
approval/question handling, and returning to ordinary reading after
choosing Default or exiting Codex.
.SS Clipboard
Use review navigation to place two marks around text with
\f[B]Fenrir+X\f[R], then press \f[B]Fenrir+C\f[R] to copy it.
@@ -306,68 +627,57 @@ In table mode Fenrir+X sets headers instead.
.IP \(bu 2
\f[B]Fenrir+Shift+X\f[R]
.RS 2
.PP
Action: Read marked text
\f[B]Action:\f[R] Read marked text
.RE
.IP \(bu 2
\f[B]Fenrir+Control+Shift+X\f[R]
.RS 2
.PP
Action: Remove marks
\f[B]Action:\f[R] Remove marks
.RE
.IP \(bu 2
\f[B]Fenrir+C\f[R]
.RS 2
.PP
Action: Copy marked text
\f[B]Action:\f[R] Copy marked text
.RE
.IP \(bu 2
\f[B]Fenrir+Control+C\f[R]
.RS 2
.PP
Action: Copy last presented text
\f[B]Action:\f[R] Copy last presented text
.RE
.IP \(bu 2
\f[B]Fenrir+Shift+C\f[R]
.RS 2
.PP
Action: Read selected clipboard
\f[B]Action:\f[R] Read selected clipboard
.RE
.IP \(bu 2
\f[B]Fenrir+Control+Shift+C\f[R]
.RS 2
.PP
Action: Clear selected clipboard
\f[B]Action:\f[R] Clear selected clipboard
.RE
.IP \(bu 2
\f[B]Fenrir+Home / End\f[R]
.RS 2
.PP
Action: First / last clipboard
\f[B]Action:\f[R] First / last clipboard
.RE
.IP \(bu 2
\f[B]Fenrir+PageUp / PageDown\f[R]
.RS 2
.PP
Action: Previous / next clipboard
\f[B]Action:\f[R] Previous / next clipboard
.RE
.IP \(bu 2
\f[B]Fenrir+V\f[R]
.RS 2
.PP
Action: Paste selected clipboard
\f[B]Action:\f[R] Paste selected clipboard
.RE
.IP \(bu 2
\f[B]Fenrir+F5 / F6\f[R]
.RS 2
.PP
Action: Import from / export to file
\f[B]Action:\f[R] Import from / export to file
.RE
.IP \(bu 2
\f[B]Fenrir+F7 / F8\f[R]
.RS 2
.PP
Action: Import from / export to X clipboard
\f[B]Action:\f[R] Import from / export to X clipboard
.RE
.PP
\f[CR]clipboard.number_of_clipboards\f[R] limits history; the default is
@@ -442,6 +752,39 @@ Select the driver and theme in Sound settings.
The ALSA device name is set with \f[CR]presentation.sound.device\f[R] in
the file.
.PP
Speech Dispatcher has its own synthesis and audio configuration,
separate from Fenrir\(cqs sound cues.
For an X11 terminal session, run \f[CR]./fenrir \-x\f[R] as your regular
user.
With sudo, Fenrir uses \f[CR]SUDO_UID\f[R] to locate the invoking
user\(cqs PulseAudio socket.
The default sound driver tries the user session, then
\f[CR]/tmp/pulse.sock\f[R], then \f[CR]/run/pulse/native\f[R].
Set \f[CR]PULSE_SERVER\f[R] to select an explicit server; the sound
driver does not read PulseAudio\(cqs \f[CR]client.conf\f[R].
The sound service must already be running and accessible to the reader.
See Speech synthesizers for Speech Dispatcher addresses and autostart
behavior.
.PP
If root sound needs additional configuration, the checkout includes
configure_pulse.sh for PulseAudio and configure_pipewire.sh for
PipeWire.
Read the appropriate script before running it.
Each has a regular\-user part and a root part, and writes audio
configuration files.
The PulseAudio script replaces the user\(cqs \f[CR]default.pa\f[R] and
configures an anonymously accessible socket at
\f[CR]/tmp/pulse.sock\f[R].
The PipeWire script also changes WirePlumber settings.
These scripts change system audio configuration and are only needed when
the existing audio setup does not provide the required access.
.PP
For ALSA, select \f[CR]driver = \(dqalsa\(dq\f[R] under
\f[CR][presentation.sound]\f[R] in \f[CR]settings.toml\f[R] and set
\f[CR]device\f[R] to the desired PCM name, such as
\f[CR]\(dqdefault\(dq\f[R].
Driver and device changes apply at the next launch.
.PP
Personal themes are searched under
\f[CR]\(ti/.local/stormux/fenrir/sounds/\f[R] before bundled and system
themes.
@@ -471,8 +814,8 @@ If default files are absent, Fenrir uses built\-in defaults.
Python \f[CR]settings.conf\f[R] files are ignored.
Regular users save to their personal TOML file, including when startup
loaded system defaults; root saves to the system file.
\f[CR]\-\-config PATH\f[R] explicitly selects both the load and save path,
and that file must exist at startup.
\f[CR]\-\-config PATH\f[R] explicitly selects both the load and save
path, and that file must exist at startup.
.PP
Create a personal settings file and validate it without opening devices:
.IP
@@ -494,6 +837,32 @@ The default driver is \f[CR]speech\-dispatcher\f[R].
Select its module, language, and voice in Speech settings; empty values
use server defaults.
.PP
Fenrir uses \f[CR]SPEECHD_ADDRESS\f[R] when set:
\f[CR]unix_socket:/absolute/path\f[R] selects a Unix socket, and
\f[CR]inet_socket:HOST:PORT\f[R] selects TCP (default host
\f[CR]127.0.0.1\f[R], port \f[CR]6560\f[R]).
Invalid addresses report an error.
Otherwise, \f[CR]SPEECHD_SOCKET\f[R] selects a Unix socket.
Without either variable, Fenrir uses
\f[CR]$XDG_RUNTIME_DIR/speech\-dispatcher/speechd.sock\f[R], falling
back to \f[CR]$XDG_CACHE_HOME/speech\-dispatcher/speechd.sock\f[R] or
\f[CR]\(ti/.cache/speech\-dispatcher/speechd.sock\f[R] when the runtime
directory is unset.
With sudo, the default remains
\f[CR]/run/user/$SUDO_UID/speech\-dispatcher/speechd.sock\f[R].
Sudo may remove address variables; preserve them explicitly if needed.
.PP
When opening speech, Fenrir first tries the selected server.
If its socket is missing or refuses connections, Fenrir requests
\f[CR]speech\-dispatcher \-\-spawn\f[R] and briefly retries.
The daemon\(cqs configuration controls whether spawning is allowed.
\f[CR]SPEECHD_CMD\f[R] can select another executable.
Autostart is limited to Unix sockets and local loopback TCP servers.
When sudo changes the account, start Speech Dispatcher as the invoking
user first; Fenrir will not launch a root\-owned daemon for that user.
Settings discovery never starts a daemon or interrupts the active
speaking client.
.PP
Hardware driver IDs are \f[CR]dectalk\f[R], \f[CR]dectalk\-usb\f[R],
\f[CR]litetalk\f[R], \f[CR]doubletalk\f[R], and \f[CR]tripletalk\f[R].
Serial drivers require \f[CR]presentation.speech.hardware_device\f[R],
@@ -553,6 +922,17 @@ Other supported operations include:
.IP \(bu 2
\f[CR]command exportclipboard\f[R]: export the selected clipboard.
.IP \(bu 2
\f[CR]command application ID\f[R]: select \f[CR]default\f[R],
\f[CR]networkmanager\f[R], \f[CR]ninjam\f[R], \f[CR]rogue\f[R], or
\f[CR]codex\f[R] for this reader\(cqs active terminal, like Fenrir+A.
This requires command remote control.
An empty reply means selection succeeded; invalid IDs, busy settings,
and restoration failures return an error.
Application recognition and profile loading happen later, when the
application appears; this command does not launch it.
\f[CR]default\f[R] restores ordinary settings.
Use a private socket when targeting a particular reader.
.IP \(bu 2
\f[CR]command window X1 Y1 X2 Y2\f[R]: set a reading window, using
zero\-based, inclusive coordinates.
.IP \(bu 2
@@ -574,89 +954,77 @@ self\-voicing also allows an account logged into the active console.
Fenrir runs as \f[CR]fenrir [options]\f[R].
Use \f[CR]\-\-help\f[R] for the built\-in reference.
.IP \(bu 2
\f[B]\-\-help\f[R]
\f[B]\f[CB]\-\-help\f[B]\f[R]
.RS 2
.PP
Purpose: Show usage and options
\f[B]Purpose:\f[R] Show usage and options
.RE
.IP \(bu 2
\f[B]\-\-version\f[R]
\f[B]\f[CB]\-\-version\f[B]\f[R]
.RS 2
.PP
Purpose: Print version and release channel
\f[B]Purpose:\f[R] Print version and release channel
.RE
.IP \(bu 2
\f[B]\-f\f[R]
\f[B]\f[CB]\-f\f[B]\f[R]
.RS 2
.PP
Purpose: Keep console mode in the foreground (always enabled with
\f[CR]\-x\f[R])
\f[B]Purpose:\f[R] Keep console mode in the foreground (always enabled
with \f[CR]\-x\f[R])
.RE
.IP \(bu 2
\f[B]\-x\f[R]
\f[B]\f[CB]\-x\f[B]\f[R]
.RS 2
.PP
Purpose: Start a shell inside this X11 terminal
\f[B]Purpose:\f[R] Start a shell inside this X11 terminal
.RE
.IP \(bu 2
\f[B]\-\-config PATH\f[R]
\f[B]\f[CB]\-\-config PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Load a specific TOML settings file
\f[B]Purpose:\f[R] Load a specific TOML settings file
.RE
.IP \(bu 2
\f[B]\-\-keyboard\-layout NAME_OR_PATH\f[R]
\f[B]\f[CB]\-\-keyboard\-layout NAME_OR_PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Select a named layout or TOML file
\f[B]Purpose:\f[R] Select a named layout or TOML file
.RE
.IP \(bu 2
\f[B]\-\-punctuation\-profile NAME_OR_PATH\f[R]
\f[B]\f[CB]\-\-punctuation\-profile NAME_OR_PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Select a punctuation profile
\f[B]Purpose:\f[R] Select a punctuation profile
.RE
.IP \(bu 2
\f[B]\-\-check\-config\f[R]
\f[B]\f[CB]\-\-check\-config\f[B]\f[R]
.RS 2
.PP
Purpose: Validate settings, layout, and punctuation without opening devices
\f[B]Purpose:\f[R] Validate settings, layout, and punctuation without
opening devices
.RE
.IP \(bu 2
\f[B]\-\-write\-config PATH\f[R]
\f[B]\f[CB]\-\-write\-config PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Write effective settings to a file and exit
\f[B]Purpose:\f[R] Write effective settings to a file and exit
.RE
.IP \(bu 2
\f[B]\-\-speech\-driver ID\f[R]
\f[B]\f[CB]\-\-speech\-driver ID\f[B]\f[R]
.RS 2
.PP
Purpose: Override the configured speech driver
\f[B]Purpose:\f[R] Override the configured speech driver
.RE
.IP \(bu 2
\f[B]\-\-speech\-rate NUMBER\f[R]
\f[B]\f[CB]\-\-speech\-rate NUMBER\f[B]\f[R]
.RS 2
.PP
Purpose: Override rate, from \-100 to 100
\f[B]Purpose:\f[R] Override rate, from \-100 to 100
.RE
.IP \(bu 2
\f[B]\-\-speech\-module NAME\f[R]
\f[B]\f[CB]\-\-speech\-module NAME\f[B]\f[R]
.RS 2
.PP
Purpose: Select a Speech Dispatcher module
\f[B]Purpose:\f[R] Select a Speech Dispatcher module
.RE
.IP \(bu 2
\f[B]\-\-input\-device PATH\f[R]
\f[B]\f[CB]\-\-input\-device PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Select a console keyboard event device; may be repeated
\f[B]Purpose:\f[R] Select a console keyboard event device; may be
repeated
.RE
.IP \(bu 2
\f[B]\-\-debug\-file PATH\f[R]
\f[B]\f[CB]\-\-debug\-file PATH\f[B]\f[R]
.RS 2
.PP
Purpose: Append timing and reader\-decision diagnostics
\f[B]Purpose:\f[R] Append timing and reader\-decision diagnostics
.RE
.SS Troubleshooting
.SS Speech or sound is missing
@@ -693,9 +1061,11 @@ problem.
.SS Documentation maintenance and support
\f[CR]docs/user.md\f[R] is the shared manual source.
With Pandoc installed, run \f[CR]./docs/create_manpage.sh\f[R] to
regenerate \f[CR]docs/user.txt\f[R], \f[CR]docs/fenrir.adoc\f[R], and
\f[CR]docs/fenrir.1\f[R].
regenerate \f[CR]docs/user.txt\f[R] and \f[CR]docs/fenrir.1\f[R].
The script can run from any working directory.
Edit the Markdown source rather than the generated files.
The bundled \f[CR]docs/man_tables.lua\f[R] filter renders man\-page
tables as labeled lists for narrow terminals.
.PP
Please review documentation and test instructions for the affected
workflow before submitting a change, as described in the README\(cqs