Attempt to improve the multicharacter detection code.
This commit is contained in:
1 parent
6fc3416a1b
commit
3cf41e662c
12 files changed
+1135
-843
No files matched your search
@@ -1,15 +0,0 @@
|
||||
Please report bugs and feature requests to:
|
||||
https://git.stormux.org/storm/fenrir/issues
|
||||
|
||||
For bugs, please provide a debug file that shows the issue.
|
||||
How to create a debug file:
|
||||
1. start fenrir in debug mode
|
||||
sudo fenrir -d
|
||||
<do your stuff>
|
||||
2.
|
||||
stop fenrir (fenrirKey + q)
|
||||
the debug file is in /tmp/fenrir.log
|
||||
if another Fenrir debug instance is already using it, check /tmp/fenrir2.log,
|
||||
/tmp/fenrir3.log, etc.
|
||||
|
||||
please be as precise as possible to make it easy to solve the problem.
|
||||
@@ -75,7 +75,8 @@ punctuation_profile = "default"
|
||||
punctuation_level = "some"
|
||||
# Whole whitespace-delimited emoticons, matching Python's names/boundaries.
|
||||
emoticons = true
|
||||
# Optional summaries for whole repeated-symbol tokens, e.g. ##### -> 5 number.
|
||||
# Optional summaries for repeated-symbol tokens, e.g. ##### -> 5 number.
|
||||
# Matching brackets around a run are allowed, e.g. [#####].
|
||||
# Only symbols named at the selected punctuation level are summarized.
|
||||
repeated_symbols = false
|
||||
# Minimum run length, 2–10000; default 4 means more than three repeats.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
Fenrir console audio
|
||||
|
||||
Fenrir's pulse sound driver uses PulseAudio or PipeWire's PulseAudio service.
|
||||
The alsa driver opens the configured ALSA PCM device directly. Speech Dispatcher
|
||||
has its own synthesis and audio configuration, separate from Fenrir's sound cues.
|
||||
|
||||
For an X11 terminal session, start Fenrir as the regular user with ./fenrir -x.
|
||||
For console mode started through sudo, Fenrir uses SUDO_UID to find the invoking
|
||||
user's PulseAudio and Speech Dispatcher sockets. An explicit PULSE_SERVER takes
|
||||
precedence for sound cues; SPEECHD_ADDRESS with a unix_socket: address takes
|
||||
precedence for Speech Dispatcher. The relevant services must already be running
|
||||
and accessible to the reader process.
|
||||
|
||||
If root sound still needs separate configuration, the checkout includes
|
||||
tools/configure_pulse.sh for PulseAudio and
|
||||
tools/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's default.pa and configures an anonymously accessible socket
|
||||
at /tmp/pulse.sock. The PipeWire script also changes WirePlumber settings.
|
||||
These are system audio changes, not prerequisites for every Fenrir session.
|
||||
|
||||
For ALSA, select driver = "alsa" under [presentation.sound] in settings.toml
|
||||
and set device to the desired PCM name, such as "default". Driver and device
|
||||
changes apply at the next launch.
|
||||
|
||||
See README.md for build and startup instructions and docs/user.md for the Sound
|
||||
settings and troubleshooting sections.
|
||||
@@ -14,15 +14,13 @@ trap 'rm -rf -- "$tempDir"' EXIT
|
||||
# Generate every format successfully before replacing any existing output.
|
||||
pandoc "$docsDir/user.md" --from markdown --to plain --wrap=auto \
|
||||
| sed 's/[[:blank:]]*$//' > "$tempDir/user.txt"
|
||||
pandoc "$docsDir/user.md" --from markdown --to asciidoc --wrap=auto \
|
||||
--output "$tempDir/fenrir.adoc"
|
||||
pandoc "$docsDir/user.md" --from markdown --to man --standalone \
|
||||
--lua-filter "$docsDir/man_tables.lua" \
|
||||
--metadata title=fenrir --metadata section=1 \
|
||||
--metadata header="Fenrir User Manual" \
|
||||
--output "$tempDir/fenrir.1"
|
||||
|
||||
for manualFile in user.txt fenrir.adoc fenrir.1; do
|
||||
for manualFile in user.txt fenrir.1; do
|
||||
mv -- "$tempDir/$manualFile" "$docsDir/$manualFile"
|
||||
done
|
||||
|
||||
+495
-125
@@ -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
|
||||
|
||||
@@ -1,491 +0,0 @@
|
||||
== Fenrir User Manual
|
||||
|
||||
Fenrir is a Linux console screen reader written in Go. It reads Linux
|
||||
text consoles and can run in an X11 terminal as a regular user.
|
||||
|
||||
*Current maintainer:* Storm Dragon +
|
||||
*Original creator:* Chrys (see link:../CREDITS[CREDITS])
|
||||
|
||||
For build requirements and setup, see the link:../README.md[README].
|
||||
|
||||
=== Starting and stopping
|
||||
|
||||
Run these commands from the checkout root after building `fenrir`:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
# Linux text console, with console and keyboard device access
|
||||
sudo ./fenrir
|
||||
|
||||
# Linux console in the foreground (also use -f with service managers)
|
||||
sudo ./fenrir -f
|
||||
|
||||
# X11 terminal, as your regular user
|
||||
./fenrir -x
|
||||
|
||||
# Either mode can select the laptop layout
|
||||
./fenrir -x --keyboard-layout laptop
|
||||
----
|
||||
|
||||
Console mode starts in the background by default. Add `-f` to keep it in
|
||||
the foreground, including under a service manager. The launcher returns
|
||||
after the reader initializes and reports startup failures in the
|
||||
launching terminal. Use `--debug-file PATH` to retain diagnostics after
|
||||
detaching. Help, version, and configuration-only commands always run in
|
||||
the foreground.
|
||||
|
||||
X11 mode (`-x`) always stays in the foreground because it owns the
|
||||
terminal and its child shell. Press *Fenrir{plus}Q* to quit either mode.
|
||||
Run only one reader on a given Linux console. Separate X11 terminal
|
||||
instances can run at once.
|
||||
|
||||
X11 mode starts a shell in a new PTY. The launching terminal must supply
|
||||
valid `DISPLAY` and `WINDOWID` environment variables. Keyboard
|
||||
interception is scoped to that terminal window; a desktop screen reader
|
||||
can handle other windows.
|
||||
|
||||
Console mode needs access to console devices, keyboard event devices,
|
||||
and `/dev/uinput`. It releases keyboard input on graphical virtual
|
||||
terminals and on text consoles selected in `screen.ignored++_++vts`.
|
||||
|
||||
=== Keyboard layouts and help
|
||||
|
||||
The *Fenrir key* is Insert, Super/Windows, or keypad 0 with NumLock off.
|
||||
Hold it while pressing the other keys in a shortcut. Bare keypad review
|
||||
keys also require NumLock off.
|
||||
|
||||
The desktop layout uses the numeric keypad. The laptop layout uses
|
||||
Fenrir chords on the main keyboard. Select a layout with
|
||||
`--keyboard-layout desktop` or `--keyboard-layout laptop`, or set
|
||||
`keyboard.layout` in the settings file.
|
||||
|
||||
Press *Fenrir{plus}H* or *Fenrir{plus}F1* to enter the tutorial. Command
|
||||
shortcuts are announced and described instead of executed. Up and Down
|
||||
browse commands; Left and Right switch between active actions, unbound
|
||||
actions, and scripts. Space repeats the current item. Escape or
|
||||
Fenrir{plus}F1 exits.
|
||||
|
||||
The complete layouts are
|
||||
link:../config/keyboard/desktop.toml[desktop.toml] and
|
||||
link:../config/keyboard/laptop.toml[laptop.toml].
|
||||
|
||||
=== Screen review
|
||||
|
||||
Review moves Fenrir’s reading position without moving the application’s
|
||||
cursor. Return to the application cursor with the Follow cursor
|
||||
shortcut. By default, application cursor movement or a screen change
|
||||
also leaves review.
|
||||
|
||||
[width="100%",cols="34%,33%,33%",options="header",]
|
||||
|===
|
||||
|Action |Desktop |Laptop
|
||||
|Previous / current / next line |Keypad 7 / 8 / 9 |Fenrir{plus}U / I / O
|
||||
|
||||
|Previous / current / next word |Keypad 4 / 5 / 6 |Fenrir{plus}J / K / L
|
||||
|
||||
|Previous / current / next character |Keypad 1 / 2 / 3 |Fenrir{plus}M /
|
||||
Comma / Period
|
||||
|
||||
|Top / bottom of screen |Fenrir{plus}Keypad 7 / 9
|
||||
|Fenrir{plus}Shift{plus}U / O
|
||||
|
||||
|Line start / end |Fenrir{plus}Keypad 4 / 6 |Fenrir{plus}Shift{plus}J /
|
||||
L
|
||||
|
||||
|First / last text on line |Fenrir{plus}Keypad 1 / 3
|
||||
|Fenrir{plus}Control{plus}J / L
|
||||
|
||||
|Read screen |Fenrir{plus}Keypad 5 |Fenrir{plus}Shift{plus}K
|
||||
|
||||
|Screen before / after cursor |Fenrir{plus}Keypad 8 / 2
|
||||
|Fenrir{plus}Shift{plus}I / Comma
|
||||
|
||||
|Character above / below |Fenrir{plus}Control{plus}Keypad 8 / 2
|
||||
|Fenrir{plus}Control{plus}I / Comma
|
||||
|
||||
|Follow cursor |Fenrir{plus}Keypad Period |Fenrir{plus}Slash
|
||||
|
||||
|Review position |Keypad Period |Fenrir{plus}Shift{plus}Period
|
||||
|===
|
||||
|
||||
Press the current-line or current-word shortcut twice quickly to spell
|
||||
the text, or three times for phonetic reading. Press the
|
||||
current-character shortcut twice for its phonetic name. The default
|
||||
interval between presses is 200 ms;
|
||||
`keyboard.multi++_++press++_++timeout++_++ms` changes it at launch.
|
||||
|
||||
=== Tracking modes
|
||||
|
||||
Cycle through *cursor*, *table*, and *highlight* with
|
||||
*Fenrir{plus}Keypad Asterisk* on desktop or *Fenrir{plus}Y* on laptop.
|
||||
The startup selection is `reading.mode`.
|
||||
|
||||
* *Cursor*: follows application cursor movement.
|
||||
* *Table*: treats delimited or space-aligned text as cells.
|
||||
* *Highlight*: follows changes to highlighted text, such as menu
|
||||
selections.
|
||||
|
||||
In table mode, word navigation moves between cells, line start/end moves
|
||||
to the first/last cell, and first/last text moves to the first/last
|
||||
character in the current cell. Place review on a header row and press
|
||||
*Fenrir{plus}X* to use its cells as column headers. Outside table mode,
|
||||
Fenrir{plus}X places a text-selection mark.
|
||||
|
||||
=== Speech and automatic reading
|
||||
|
||||
* *Control* interrupts speech.
|
||||
* *Fenrir{plus}F4* toggles mute.
|
||||
* *Keypad Enter* on desktop temporarily silences speech. Speech can
|
||||
return on the next keypress or a newly recognized prompt or completion.
|
||||
* *Fenrir{plus}Keypad Enter* on desktop, or *Fenrir{plus}Enter* on
|
||||
laptop, toggles automatic reading of new text.
|
||||
* *Fenrir{plus}Backspace* passes the next key through to the
|
||||
application.
|
||||
|
||||
Character echo, word echo, and cursor echo can be configured separately.
|
||||
Punctuation levels are `none`, `some`, `most`, and `all`. Character
|
||||
review still names punctuation. Capital indicators, emoticons,
|
||||
repeated-symbol summaries, indentation feedback, and attribute feedback
|
||||
are configurable in Reading.
|
||||
|
||||
*Fenrir{plus}T* announces the time; press twice quickly for the date.
|
||||
*Fenrir{plus}Shift{plus}V* announces the Fenrir version.
|
||||
|
||||
=== Fenrir Menu and quick settings
|
||||
|
||||
Press *Fenrir{plus}F* to open the Fenrir Menu. It contains settings tabs
|
||||
for presentation, speech, sound, reading, keyboard, internal UI, clipboard, and other
|
||||
options. The form captures its navigation keys until it closes.
|
||||
|
||||
* At the tab selector, use arrows to choose a tab.
|
||||
* Tab and Shift{plus}Tab move between controls and the tab selector.
|
||||
* Space or Enter toggles a checkbox.
|
||||
* Arrows change list selections and numeric values.
|
||||
* Activate *OK* to save, or *Cancel* or Escape to discard the form’s
|
||||
changes.
|
||||
|
||||
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. 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.
|
||||
|
||||
The *Internal UI* tab controls speech in Fenrir’s own menus and dialogs.
|
||||
*Announce grid row and column* and *Announce item position* are
|
||||
independent checkboxes, both enabled by default. Disable coordinates to
|
||||
omit “row 1, column 2”; disable item position to omit “2 of 20”. Item
|
||||
names and grid navigation remain available with both disabled. Saved
|
||||
changes apply immediately to Emoji and Spellcheck grids and persist
|
||||
across launches. These are global settings, so this tab is omitted from
|
||||
application settings. The TOML keys are
|
||||
`internal++_++ui.announce++_++grid++_++coordinates` and
|
||||
`internal++_++ui.announce++_++item++_++position`.
|
||||
|
||||
Settings saves use mode `644` for the standard system settings file at
|
||||
`/etc/fenrirscreenreader/settings/settings.toml`, so other users can
|
||||
read it as a startup fallback. Personal settings and application
|
||||
profiles use mode `600`.
|
||||
|
||||
Quick settings work without opening the form:
|
||||
|
||||
[cols=",",options="header",]
|
||||
|===
|
||||
|Shortcut |Action
|
||||
|Fenrir{plus}Space |Announce current setting
|
||||
|Fenrir{plus}Left / Right |Previous / next setting
|
||||
|Fenrir{plus}Control{plus}Left / Right |Previous / next category
|
||||
|Fenrir{plus}Up / Down |Change value
|
||||
|Fenrir{plus}Control{plus}S |Save settings
|
||||
|===
|
||||
|
||||
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.
|
||||
|
||||
=== Clipboard
|
||||
|
||||
Use review navigation to place two marks around text with
|
||||
*Fenrir{plus}X*, then press *Fenrir{plus}C* to copy it. In table mode
|
||||
Fenrir{plus}X sets headers instead.
|
||||
|
||||
[cols=",",options="header",]
|
||||
|===
|
||||
|Shortcut |Action
|
||||
|Fenrir{plus}Shift{plus}X |Read marked text
|
||||
|Fenrir{plus}Control{plus}Shift{plus}X |Remove marks
|
||||
|Fenrir{plus}C |Copy marked text
|
||||
|Fenrir{plus}Control{plus}C |Copy last presented text
|
||||
|Fenrir{plus}Shift{plus}C |Read selected clipboard
|
||||
|Fenrir{plus}Control{plus}Shift{plus}C |Clear selected clipboard
|
||||
|Fenrir{plus}Home / End |First / last clipboard
|
||||
|Fenrir{plus}PageUp / PageDown |Previous / next clipboard
|
||||
|Fenrir{plus}V |Paste selected clipboard
|
||||
|Fenrir{plus}F5 / F6 |Import from / export to file
|
||||
|Fenrir{plus}F7 / F8 |Import from / export to X clipboard
|
||||
|===
|
||||
|
||||
`clipboard.number++_++of++_++clipboards` limits history; the default is
|
||||
200. `clipboard.export++_++path` selects the import/export file,
|
||||
initially `/tmp/fenrirClipboard`. `clipboard.sync` enables automatic X
|
||||
clipboard synchronization, which requires `xclip` and access to the X
|
||||
display.
|
||||
|
||||
Persistent history is optional and off by default. Set
|
||||
`clipboard.persistent` to retain unencrypted history across launches.
|
||||
Terminal sessions use `~/.local/state/fenrir/clipboard/terminal.json`;
|
||||
console sessions use `/var/lib/fenrir/clipboard/tty.json`. Same-user
|
||||
readers of the same mode share persistent history.
|
||||
|
||||
=== Spell checking and emoji
|
||||
|
||||
Automatic spell checking uses Enchant 2 and a dictionary matching the
|
||||
session language. Reading settings control word repetition, spoken
|
||||
misspelling feedback, and misspelling sounds.
|
||||
|
||||
Press *Fenrir{plus}S* to open the Spellcheck Menu for the current word.
|
||||
The Suggestions tab lets you edit the word and choose a suggested
|
||||
spelling. The Exceptions tab lets you add words, remove selected entries
|
||||
with Delete, and undo a removal. Selecting a suggestion copies it to
|
||||
Fenrir’s clipboard; paste it with Fenrir{plus}V.
|
||||
|
||||
Press *Fenrir{plus}Control{plus}E* to open the Emoji Menu. Choose a
|
||||
category at the tab selector, then Tab to the emoji grid. Arrows
|
||||
navigate, typing filters by name prefix, and Control{plus}Backspace
|
||||
clears the filter. Enter copies the selected emoji to Fenrir’s
|
||||
clipboard. Escape closes the menu.
|
||||
|
||||
=== Reading windows and live regions
|
||||
|
||||
Reading regions belong to the current terminal and last for the reader
|
||||
session. A reading window restricts automatic reading to a rectangle.
|
||||
Live regions exclude changing areas from automatic speech while allowing
|
||||
explicit reading and progress monitoring.
|
||||
|
||||
Outside table mode, place two marks with *Fenrir{plus}X* to define
|
||||
opposite corners. Press *Fenrir{plus}Keypad Slash* on desktop or
|
||||
*Fenrir{plus}Control{plus}8* on laptop to set a reading window. Press
|
||||
the shortcut twice quickly to clear it.
|
||||
|
||||
To create a live region, place one mark for the rest of that line, or
|
||||
two marks for a rectangle, then press *Fenrir{plus}B*. Fenrir assigns
|
||||
the first free slot, up to ten. Region creation clears the marks.
|
||||
|
||||
* *Fenrir{plus}1* through *Fenrir{plus}0* read live regions 1 through
|
||||
10.
|
||||
* *Fenrir{plus}Shift{plus}1* through *Fenrir{plus}Shift{plus}0* clear
|
||||
individual live regions.
|
||||
* *Fenrir{plus}Shift{plus}B* lists the current reading regions.
|
||||
* *Fenrir{plus}Control{plus}B* clears all live regions.
|
||||
* *Fenrir{plus}Control{plus}Shift{plus}B* clears both the reading window
|
||||
and live regions.
|
||||
|
||||
=== Sound and progress
|
||||
|
||||
Sound output uses `pulse` for PulseAudio or PipeWire’s PulseAudio
|
||||
service, or `alsa` for an ALSA PCM device. Select the driver and theme
|
||||
in Sound settings. The ALSA device name is set with
|
||||
`presentation.sound.device` in the file.
|
||||
|
||||
Personal themes are searched under `~/.local/stormux/fenrir/sounds/`
|
||||
before bundled and system themes. A theme contains WAV files and
|
||||
`soundicons.toml`.
|
||||
|
||||
Progress tones are controlled separately from speech and automatic
|
||||
reading. Press *Keypad Plus* on desktop or *Fenrir{plus}Shift{plus}P* on
|
||||
laptop to toggle them. Fenrir recognizes percentages, fractions,
|
||||
progress bars, and activity indicators; tones rise with progress.
|
||||
Startup behavior is set by `presentation.progress.enabled`.
|
||||
|
||||
=== Configuration files
|
||||
|
||||
Settings are TOML. The annotated
|
||||
link:../config/settings/settings.toml[settings.toml] lists all available
|
||||
options. Fenrir loads one settings file rather than merging files.
|
||||
|
||||
* Regular users: first
|
||||
`~/.local/share/stormux/fenrirscreenreader/settings/settings.toml`, then
|
||||
`/etc/fenrirscreenreader/settings/settings.toml`.
|
||||
* Root: `/etc/fenrirscreenreader/settings/settings.toml`.
|
||||
* `--config PATH`: use that file explicitly.
|
||||
|
||||
If default files are absent, Fenrir uses built-in defaults. An
|
||||
explicitly selected file must exist. Saving targets the selected file;
|
||||
if startup used built-in defaults, saving creates the first default path
|
||||
for that account.
|
||||
|
||||
Create a personal settings file and validate it without opening devices:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
./fenrir --write-config ~/.local/share/stormux/fenrirscreenreader/settings/settings.toml
|
||||
./fenrir --config ~/.local/share/stormux/fenrirscreenreader/settings/settings.toml --check-config
|
||||
----
|
||||
|
||||
Named keyboard layouts are searched in the regular user’s
|
||||
`~/.local/share/stormux/fenrirscreenreader/keyboard/`, then
|
||||
`/etc/fenrirscreenreader/keyboard/`, then `config/keyboard/` beside the
|
||||
binary. Root searches the system and bundled locations. An explicit TOML
|
||||
path selects one file. Custom layouts replace the complete layout; they
|
||||
are not overlays. See the link:../config/keyboard/Readme.md[keyboard
|
||||
guide] for an example.
|
||||
|
||||
=== Speech synthesizers
|
||||
|
||||
The default driver is `speech-dispatcher`. Select its module, language,
|
||||
and voice in Speech settings; empty values use server defaults.
|
||||
|
||||
Hardware driver IDs are `dectalk`, `dectalk-usb`, `litetalk`,
|
||||
`doubletalk`, and `tripletalk`. Serial drivers require
|
||||
`presentation.speech.hardware++_++device`, for example `/dev/ttyUSB0`,
|
||||
and default to 9600 baud when `hardware++_++baud++_++rate = 0`.
|
||||
DoubleTalk support targets the external LT device. TripleTalk USB
|
||||
devices need to expose a serial tty.
|
||||
|
||||
Native `dectalk-usb` uses libusb 1.0 and ignores serial settings. The
|
||||
process needs access to the device. The Speech form’s *Test synthesizer*
|
||||
button previews hardware choices before saving. Driver and port changes
|
||||
apply at launch.
|
||||
|
||||
=== Script shortcuts
|
||||
|
||||
Fenrir searches `~/.local/stormux/fenrir/`, the configured
|
||||
`general.script++_++path` (default
|
||||
`/usr/share/fenrirscreenreader/scripts`), and the bundled
|
||||
`config/scripts/` beside the binary. Earlier directories take priority.
|
||||
|
||||
A filename such as `example++__++-++__++key++_++y.sh` assigns the script
|
||||
key plus Y. The script key defaults to Compose and is configured by
|
||||
`general.script++_++keys`. Scripts must be executable to run. Fenrir
|
||||
invokes them directly and passes the current account name as the first
|
||||
argument. Commands appear in the tutorial’s script list.
|
||||
|
||||
=== Remote control
|
||||
|
||||
Unix socket remote control is enabled by default. The standard socket is
|
||||
`/tmp/fenrirscreenreader-daemon.sock`, and instances also have private
|
||||
sockets `/tmp/fenrirscreenreader-++<++pid++>++.sock`. Set
|
||||
`remote.socket++_++file` for a custom socket.
|
||||
|
||||
Use `ls` to discover instances. Use a private socket to address one
|
||||
reader:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set reading#mode=highlight" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
----
|
||||
|
||||
Remote requests use `section++#++setting=value` syntax independently of
|
||||
TOML. Remote speech rate, pitch, and volume use *0.0 to 1.0*, mapped to
|
||||
the -100 to 100 scale used in settings files and menus. For example,
|
||||
`speech++#++rate=0.8` selects rate 60.
|
||||
|
||||
Other supported operations include:
|
||||
|
||||
* `command tempdisablespeech`: temporarily silence speech.
|
||||
* `command clipboard TEXT`: add text to the clipboard.
|
||||
* `command exportclipboard`: export the selected clipboard.
|
||||
* `command window X1 Y1 X2 Y2`: set a reading window, using zero-based,
|
||||
inclusive coordinates.
|
||||
* `command resetwindow`: clear the window.
|
||||
* `setting save`: save settings.
|
||||
* `setting reset`: clear quick and remote overrides back to the last
|
||||
loaded or successfully saved settings.
|
||||
* `command quitapplication`: quit Fenrir.
|
||||
|
||||
Set `remote.enabled = false` to disable the service. Command and setting
|
||||
requests have separate switches, `enable++_++command++_++remote` and
|
||||
`enable++_++settings++_++remote`. Requests are authorized against the
|
||||
caller’s account; console self-voicing also allows an account logged
|
||||
into the active console.
|
||||
|
||||
=== Command-line options
|
||||
|
||||
Fenrir runs as `fenrir ++[++options++]++`. Use `--help` for the built-in
|
||||
reference.
|
||||
|
||||
[width="100%",cols="50%,50%",options="header",]
|
||||
|===
|
||||
|Option |Purpose
|
||||
|`--help` |Show usage and options
|
||||
|
||||
|`--version` |Print version and release channel
|
||||
|
||||
|`-f` |Keep console mode in the foreground (always enabled with `-x`)
|
||||
|
||||
|`-x` |Start a shell inside this X11 terminal
|
||||
|
||||
|`--config PATH` |Load a specific TOML settings file
|
||||
|
||||
|`--keyboard-layout NAME++_++OR++_++PATH` |Select a named layout or TOML
|
||||
file
|
||||
|
||||
|`--punctuation-profile NAME++_++OR++_++PATH` |Select a punctuation
|
||||
profile
|
||||
|
||||
|`--check-config` |Validate settings, layout, and punctuation without
|
||||
opening devices
|
||||
|
||||
|`--write-config PATH` |Write effective settings to a file and exit
|
||||
|
||||
|`--speech-driver ID` |Override the configured speech driver
|
||||
|
||||
|`--speech-rate NUMBER` |Override rate, from -100 to 100
|
||||
|
||||
|`--speech-module NAME` |Select a Speech Dispatcher module
|
||||
|
||||
|`--input-device PATH` |Select a console keyboard event device; may be
|
||||
repeated
|
||||
|
||||
|`--debug-file PATH` |Append timing and reader-decision diagnostics
|
||||
|===
|
||||
|
||||
=== Troubleshooting
|
||||
|
||||
==== Speech or sound is missing
|
||||
|
||||
Check that speech and sound are enabled, and that the selected backend
|
||||
is available. Speech Dispatcher needs a configured synthesizer. Pulse
|
||||
output needs access to a running PulseAudio service, including
|
||||
PipeWire’s PulseAudio service; ALSA needs access to its selected PCM
|
||||
device. Root console sessions may need separate audio configuration; see
|
||||
the README’s setup section.
|
||||
|
||||
For hardware speech, check the driver, device path, device permissions,
|
||||
and serial baud rate. Use *Test synthesizer* before saving a new
|
||||
hardware selection.
|
||||
|
||||
==== Keyboard input or X11 mode fails
|
||||
|
||||
In console mode, check access to keyboard event devices and
|
||||
`/dev/uinput`. In X11 mode, check `DISPLAY`, `WINDOWID`, and competing
|
||||
grabs on the terminal. Use NumLock off for bare keypad review. A
|
||||
configured `keyboard.devices` list or `--input-device` applies to
|
||||
console mode and cannot be used with `-x`.
|
||||
|
||||
==== Check configuration and collect diagnostics
|
||||
|
||||
Validate an edited settings file with `--config PATH --check-config`.
|
||||
For reader diagnostics, add `--debug-file /tmp/fenrir-debug.log` to the
|
||||
launch command. This appends timing and reader decisions without screen
|
||||
text or key values. `./fenrir --version` identifies the build when
|
||||
reporting a problem.
|
||||
|
||||
=== Documentation maintenance and support
|
||||
|
||||
`docs/user.md` is the shared manual source. With Pandoc installed, run
|
||||
`./docs/create++_++manpage.sh` to regenerate `docs/user.txt`,
|
||||
`docs/fenrir.adoc`, and `docs/fenrir.1`. The script can run from any
|
||||
working directory.
|
||||
|
||||
Please review documentation and test instructions for the affected
|
||||
workflow before submitting a change, as described in the README’s
|
||||
contribution policy.
|
||||
|
||||
* https://git.stormux.org/storm/fenrir[Project repository and issue
|
||||
tracker]
|
||||
* https://git.stormux.org/storm/fenrir/wiki[Fenrir Wiki]
|
||||
* Email list: `stormux{plus}subscribe@groups.io`, with the subject
|
||||
`subscribe`.
|
||||
* IRC: `irc.stormux.org`, channel `++#++stormux`.
|
||||
@@ -0,0 +1,53 @@
|
||||
-- Render manual tables as labeled lists so shortcuts remain readable at narrow
|
||||
-- terminal widths. Keep cell contents as Pandoc elements to preserve formatting.
|
||||
function Table(manualTable)
|
||||
local columnNames = {}
|
||||
local headerRow = manualTable.head.rows[1]
|
||||
if headerRow then
|
||||
for columnIndex, cell in ipairs(headerRow.cells) do
|
||||
columnNames[columnIndex] = pandoc.utils.stringify(cell.contents)
|
||||
end
|
||||
end
|
||||
|
||||
local listItems = {}
|
||||
local function append_row(row)
|
||||
local itemBlocks = pandoc.List()
|
||||
for columnIndex, cell in ipairs(row.cells) do
|
||||
local cellBlocks = cell.contents:clone()
|
||||
if columnIndex == 1 then
|
||||
cellBlocks = cellBlocks:walk({
|
||||
Plain = function(block)
|
||||
return pandoc.Para({pandoc.Strong(block.content)})
|
||||
end,
|
||||
Para = function(block)
|
||||
return pandoc.Para({pandoc.Strong(block.content)})
|
||||
end,
|
||||
})
|
||||
elseif columnNames[columnIndex] then
|
||||
local label = pandoc.Strong({pandoc.Str(columnNames[columnIndex] .. ":")})
|
||||
local firstBlock = cellBlocks[1]
|
||||
if firstBlock and (firstBlock.t == "Plain" or firstBlock.t == "Para") then
|
||||
firstBlock.content:insert(1, pandoc.Space())
|
||||
firstBlock.content:insert(1, label)
|
||||
else
|
||||
cellBlocks:insert(1, pandoc.Para({label}))
|
||||
end
|
||||
end
|
||||
itemBlocks:extend(cellBlocks)
|
||||
end
|
||||
listItems[#listItems + 1] = itemBlocks
|
||||
end
|
||||
|
||||
for _, body in ipairs(manualTable.bodies) do
|
||||
for _, row in ipairs(body.head) do
|
||||
append_row(row)
|
||||
end
|
||||
for _, row in ipairs(body.body) do
|
||||
append_row(row)
|
||||
end
|
||||
end
|
||||
for _, row in ipairs(manualTable.foot.rows) do
|
||||
append_row(row)
|
||||
end
|
||||
return pandoc.BulletList(listItems)
|
||||
end
|
||||
+190
-164
@@ -8,6 +8,168 @@ consoles and can run in an X11 terminal as a regular user.
|
||||
|
||||
For build requirements and setup, see the [README](../README.md).
|
||||
|
||||
## Starting and stopping
|
||||
|
||||
Run these commands from the checkout root after building `fenrir`:
|
||||
|
||||
```bash
|
||||
# Linux text console, with console and keyboard device access
|
||||
sudo ./fenrir
|
||||
|
||||
# Linux console in the foreground (also use -f with service managers)
|
||||
sudo ./fenrir -f
|
||||
|
||||
# X11 terminal, as your regular user
|
||||
./fenrir -x
|
||||
|
||||
# Either mode can select the laptop layout
|
||||
./fenrir -x --keyboard-layout laptop
|
||||
```
|
||||
|
||||
Console mode starts in the background by default. Add `-f` to keep it in the
|
||||
foreground, including under a service manager. The launcher returns after the
|
||||
reader initializes and reports startup failures in the launching terminal.
|
||||
Use `--debug-file PATH` to retain diagnostics after detaching. Help, version,
|
||||
and configuration-only commands always run in the foreground.
|
||||
|
||||
X11 mode (`-x`) always stays in the foreground because it owns the terminal
|
||||
and its child shell. Press **Fenrir+Q** to quit either mode. Run only one
|
||||
reader on a given Linux console. Separate X11 terminal instances can run at
|
||||
once.
|
||||
|
||||
X11 mode starts a shell in a new PTY. The launching terminal must supply valid
|
||||
`DISPLAY` and `WINDOWID` environment variables. Keyboard interception is scoped
|
||||
to that terminal window; a desktop screen reader can handle other windows.
|
||||
|
||||
Console mode needs access to console devices, keyboard event devices, and
|
||||
`/dev/uinput`. It releases keyboard input on graphical virtual terminals and
|
||||
on text consoles selected in `screen.ignored_vts`.
|
||||
|
||||
## Keyboard layouts and help
|
||||
|
||||
The **Fenrir key** is Insert, Super/Windows, or keypad 0 with NumLock off.
|
||||
Hold it while pressing the other keys in a shortcut. Bare keypad review keys
|
||||
also require NumLock off.
|
||||
|
||||
The desktop layout uses the numeric keypad. The laptop layout uses Fenrir
|
||||
chords on the main keyboard. Select a layout with `--keyboard-layout desktop`
|
||||
or `--keyboard-layout laptop`, or set `keyboard.layout` in the settings file.
|
||||
|
||||
Press **Fenrir+H** or **Fenrir+F1** to enter the tutorial. Command shortcuts are
|
||||
announced and described instead of executed. Up and Down browse commands;
|
||||
Left and Right switch between active actions, unbound actions, and scripts.
|
||||
Space repeats the current item. Escape or Fenrir+F1 exits.
|
||||
|
||||
The complete layouts are [desktop.toml](../config/keyboard/desktop.toml) and
|
||||
[laptop.toml](../config/keyboard/laptop.toml).
|
||||
|
||||
## Screen review
|
||||
|
||||
Review moves Fenrir's reading position without moving the application's cursor.
|
||||
Return to the application cursor with the Follow cursor shortcut. By default,
|
||||
application cursor movement or a screen change also leaves review.
|
||||
|
||||
| Action | Desktop | Laptop |
|
||||
| --- | --- | --- |
|
||||
| Previous / current / next line | Keypad 7 / 8 / 9 | Fenrir+U / I / O |
|
||||
| Previous / current / next word | Keypad 4 / 5 / 6 | Fenrir+J / K / L |
|
||||
| Previous / current / next character | Keypad 1 / 2 / 3 | Fenrir+M / Comma / Period |
|
||||
| Top / bottom of screen | Fenrir+Keypad 7 / 9 | Fenrir+Shift+U / O |
|
||||
| Line start / end | Fenrir+Keypad 4 / 6 | Fenrir+Shift+J / L |
|
||||
| First / last text on line | Fenrir+Keypad 1 / 3 | Fenrir+Control+J / L |
|
||||
| Read screen | Fenrir+Keypad 5 | Fenrir+Shift+K |
|
||||
| Screen before / after cursor | Fenrir+Keypad 8 / 2 | Fenrir+Shift+I / Comma |
|
||||
| Character above / below | Fenrir+Control+Keypad 8 / 2 | Fenrir+Control+I / Comma |
|
||||
| Follow cursor | Fenrir+Keypad Period | Fenrir+Slash |
|
||||
| Review position | Keypad Period | Fenrir+Shift+Period |
|
||||
|
||||
Press the current-line or current-word shortcut twice quickly to spell the
|
||||
text, or three times for phonetic reading. Press the current-character shortcut
|
||||
twice for its phonetic name. The default interval between presses is 200 ms;
|
||||
`keyboard.multi_press_timeout_ms` changes it at launch.
|
||||
|
||||
## Tracking modes
|
||||
|
||||
Cycle through **cursor**, **table**, and **highlight** with
|
||||
**Fenrir+Keypad Asterisk** on desktop or **Fenrir+Y** on laptop.
|
||||
The startup selection is `reading.mode`.
|
||||
|
||||
- **Cursor**: follows application cursor movement.
|
||||
- **Table**: treats delimited or space-aligned text as cells.
|
||||
- **Highlight**: follows changes to highlighted text, such as menu selections.
|
||||
|
||||
In table mode, word navigation moves between cells, line start/end moves to the
|
||||
first/last cell, and first/last text moves to the first/last character in the
|
||||
current cell. Place review on a header row and press **Fenrir+X** to use its
|
||||
cells as column headers. Outside table mode, Fenrir+X places a text-selection
|
||||
mark.
|
||||
|
||||
## Speech and automatic reading
|
||||
|
||||
- **Control** interrupts speech.
|
||||
- **Fenrir+F4** toggles mute.
|
||||
- **Keypad Enter** on desktop temporarily silences speech. Speech can return on
|
||||
the next keypress or a newly recognized prompt or completion.
|
||||
- **Fenrir+Keypad Enter** on desktop, or **Fenrir+Enter** on laptop, toggles
|
||||
automatic reading of new text.
|
||||
- **Fenrir+Backspace** passes the next key through to the application.
|
||||
|
||||
Character echo, word echo, and cursor echo can be configured separately.
|
||||
Punctuation levels are `none`, `some`, `most`, and `all`. At `some` and `most`,
|
||||
punctuation inside words, URLs, email addresses, and filenames is also named.
|
||||
Apostrophes within words and single numeric separators such as those in `3.14`,
|
||||
`1,000`, and `12:30` 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.
|
||||
|
||||
**Fenrir+T** announces the time; press twice quickly for the date.
|
||||
**Fenrir+Shift+V** announces the Fenrir version.
|
||||
|
||||
## Fenrir Menu and quick settings
|
||||
|
||||
Press **Fenrir+F** to open the Fenrir Menu. It contains settings tabs for
|
||||
presentation, speech, sound, reading, keyboard, internal UI, clipboard, and other options.
|
||||
The form captures its navigation keys until it closes.
|
||||
|
||||
- At the tab selector, use arrows to choose a tab.
|
||||
- Tab and Shift+Tab move between controls and the tab selector.
|
||||
- Space or Enter toggles a checkbox.
|
||||
- Arrows change list selections and numeric values.
|
||||
- Activate **OK** to save, or **Cancel** or Escape to discard the form's changes.
|
||||
|
||||
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. 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.
|
||||
|
||||
The **Internal UI** tab controls speech in Fenrir's own menus and dialogs.
|
||||
**Announce grid row and column** and **Announce item position** are independent
|
||||
checkboxes, both enabled by default. Disable coordinates to omit “row 1, column 2”;
|
||||
disable item position to omit “2 of 20”. Item names and grid navigation remain
|
||||
available with both disabled. Saved changes apply immediately to Emoji and
|
||||
Spellcheck grids and persist across launches. These are global settings, so this
|
||||
tab is omitted from application settings. The TOML keys are
|
||||
`internal_ui.announce_grid_coordinates` and `internal_ui.announce_item_position`.
|
||||
|
||||
Settings saves use mode `644` for the standard system settings file at
|
||||
`/etc/fenrirscreenreader/settings/settings.toml`, so other users can read it as a
|
||||
startup fallback. Personal settings and application profiles use mode `600`.
|
||||
|
||||
Quick settings work without opening the form:
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Fenrir+Space | Announce current setting |
|
||||
| Fenrir+Left / Right | Previous / next setting |
|
||||
| Fenrir+Control+Left / Right | Previous / next category |
|
||||
| Fenrir+Up / Down | Change value |
|
||||
| Fenrir+Control+S | Save settings |
|
||||
|
||||
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.
|
||||
|
||||
## Application overrides
|
||||
|
||||
Press **Fenrir+A** to open **Applications**. Up and Down select an item; Enter
|
||||
@@ -241,168 +403,6 @@ 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.
|
||||
|
||||
## Starting and stopping
|
||||
|
||||
Run these commands from the checkout root after building `fenrir`:
|
||||
|
||||
```bash
|
||||
# Linux text console, with console and keyboard device access
|
||||
sudo ./fenrir
|
||||
|
||||
# Linux console in the foreground (also use -f with service managers)
|
||||
sudo ./fenrir -f
|
||||
|
||||
# X11 terminal, as your regular user
|
||||
./fenrir -x
|
||||
|
||||
# Either mode can select the laptop layout
|
||||
./fenrir -x --keyboard-layout laptop
|
||||
```
|
||||
|
||||
Console mode starts in the background by default. Add `-f` to keep it in the
|
||||
foreground, including under a service manager. The launcher returns after the
|
||||
reader initializes and reports startup failures in the launching terminal.
|
||||
Use `--debug-file PATH` to retain diagnostics after detaching. Help, version,
|
||||
and configuration-only commands always run in the foreground.
|
||||
|
||||
X11 mode (`-x`) always stays in the foreground because it owns the terminal
|
||||
and its child shell. Press **Fenrir+Q** to quit either mode. Run only one
|
||||
reader on a given Linux console. Separate X11 terminal instances can run at
|
||||
once.
|
||||
|
||||
X11 mode starts a shell in a new PTY. The launching terminal must supply valid
|
||||
`DISPLAY` and `WINDOWID` environment variables. Keyboard interception is scoped
|
||||
to that terminal window; a desktop screen reader can handle other windows.
|
||||
|
||||
Console mode needs access to console devices, keyboard event devices, and
|
||||
`/dev/uinput`. It releases keyboard input on graphical virtual terminals and
|
||||
on text consoles selected in `screen.ignored_vts`.
|
||||
|
||||
## Keyboard layouts and help
|
||||
|
||||
The **Fenrir key** is Insert, Super/Windows, or keypad 0 with NumLock off.
|
||||
Hold it while pressing the other keys in a shortcut. Bare keypad review keys
|
||||
also require NumLock off.
|
||||
|
||||
The desktop layout uses the numeric keypad. The laptop layout uses Fenrir
|
||||
chords on the main keyboard. Select a layout with `--keyboard-layout desktop`
|
||||
or `--keyboard-layout laptop`, or set `keyboard.layout` in the settings file.
|
||||
|
||||
Press **Fenrir+H** or **Fenrir+F1** to enter the tutorial. Command shortcuts are
|
||||
announced and described instead of executed. Up and Down browse commands;
|
||||
Left and Right switch between active actions, unbound actions, and scripts.
|
||||
Space repeats the current item. Escape or Fenrir+F1 exits.
|
||||
|
||||
The complete layouts are [desktop.toml](../config/keyboard/desktop.toml) and
|
||||
[laptop.toml](../config/keyboard/laptop.toml).
|
||||
|
||||
## Screen review
|
||||
|
||||
Review moves Fenrir's reading position without moving the application's cursor.
|
||||
Return to the application cursor with the Follow cursor shortcut. By default,
|
||||
application cursor movement or a screen change also leaves review.
|
||||
|
||||
| Action | Desktop | Laptop |
|
||||
| --- | --- | --- |
|
||||
| Previous / current / next line | Keypad 7 / 8 / 9 | Fenrir+U / I / O |
|
||||
| Previous / current / next word | Keypad 4 / 5 / 6 | Fenrir+J / K / L |
|
||||
| Previous / current / next character | Keypad 1 / 2 / 3 | Fenrir+M / Comma / Period |
|
||||
| Top / bottom of screen | Fenrir+Keypad 7 / 9 | Fenrir+Shift+U / O |
|
||||
| Line start / end | Fenrir+Keypad 4 / 6 | Fenrir+Shift+J / L |
|
||||
| First / last text on line | Fenrir+Keypad 1 / 3 | Fenrir+Control+J / L |
|
||||
| Read screen | Fenrir+Keypad 5 | Fenrir+Shift+K |
|
||||
| Screen before / after cursor | Fenrir+Keypad 8 / 2 | Fenrir+Shift+I / Comma |
|
||||
| Character above / below | Fenrir+Control+Keypad 8 / 2 | Fenrir+Control+I / Comma |
|
||||
| Follow cursor | Fenrir+Keypad Period | Fenrir+Slash |
|
||||
| Review position | Keypad Period | Fenrir+Shift+Period |
|
||||
|
||||
Press the current-line or current-word shortcut twice quickly to spell the
|
||||
text, or three times for phonetic reading. Press the current-character shortcut
|
||||
twice for its phonetic name. The default interval between presses is 200 ms;
|
||||
`keyboard.multi_press_timeout_ms` changes it at launch.
|
||||
|
||||
## Tracking modes
|
||||
|
||||
Cycle through **cursor**, **table**, and **highlight** with
|
||||
**Fenrir+Keypad Asterisk** on desktop or **Fenrir+Y** on laptop.
|
||||
The startup selection is `reading.mode`.
|
||||
|
||||
- **Cursor**: follows application cursor movement.
|
||||
- **Table**: treats delimited or space-aligned text as cells.
|
||||
- **Highlight**: follows changes to highlighted text, such as menu selections.
|
||||
|
||||
In table mode, word navigation moves between cells, line start/end moves to the
|
||||
first/last cell, and first/last text moves to the first/last character in the
|
||||
current cell. Place review on a header row and press **Fenrir+X** to use its
|
||||
cells as column headers. Outside table mode, Fenrir+X places a text-selection
|
||||
mark.
|
||||
|
||||
## Speech and automatic reading
|
||||
|
||||
- **Control** interrupts speech.
|
||||
- **Fenrir+F4** toggles mute.
|
||||
- **Keypad Enter** on desktop temporarily silences speech. Speech can return on
|
||||
the next keypress or a newly recognized prompt or completion.
|
||||
- **Fenrir+Keypad Enter** on desktop, or **Fenrir+Enter** on laptop, toggles
|
||||
automatic reading of new text.
|
||||
- **Fenrir+Backspace** passes the next key through to the application.
|
||||
|
||||
Character echo, word echo, and cursor echo can be configured separately.
|
||||
Punctuation levels are `none`, `some`, `most`, and `all`. At `some` and `most`,
|
||||
punctuation inside words, URLs, email addresses, and filenames is also named.
|
||||
Apostrophes within words and single numeric separators such as those in `3.14`,
|
||||
`1,000`, and `12:30` 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.
|
||||
|
||||
**Fenrir+T** announces the time; press twice quickly for the date.
|
||||
**Fenrir+Shift+V** announces the Fenrir version.
|
||||
|
||||
## Fenrir Menu and quick settings
|
||||
|
||||
Press **Fenrir+F** to open the Fenrir Menu. It contains settings tabs for
|
||||
presentation, speech, sound, reading, keyboard, internal UI, clipboard, and other options.
|
||||
The form captures its navigation keys until it closes.
|
||||
|
||||
- At the tab selector, use arrows to choose a tab.
|
||||
- Tab and Shift+Tab move between controls and the tab selector.
|
||||
- Space or Enter toggles a checkbox.
|
||||
- Arrows change list selections and numeric values.
|
||||
- Activate **OK** to save, or **Cancel** or Escape to discard the form's changes.
|
||||
|
||||
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. 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.
|
||||
|
||||
The **Internal UI** tab controls speech in Fenrir's own menus and dialogs.
|
||||
**Announce grid row and column** and **Announce item position** are independent
|
||||
checkboxes, both enabled by default. Disable coordinates to omit “row 1, column 2”;
|
||||
disable item position to omit “2 of 20”. Item names and grid navigation remain
|
||||
available with both disabled. Saved changes apply immediately to Emoji and
|
||||
Spellcheck grids and persist across launches. These are global settings, so this
|
||||
tab is omitted from application settings. The TOML keys are
|
||||
`internal_ui.announce_grid_coordinates` and `internal_ui.announce_item_position`.
|
||||
|
||||
Settings saves use mode `644` for the standard system settings file at
|
||||
`/etc/fenrirscreenreader/settings/settings.toml`, so other users can read it as a
|
||||
startup fallback. Personal settings and application profiles use mode `600`.
|
||||
|
||||
Quick settings work without opening the form:
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Fenrir+Space | Announce current setting |
|
||||
| Fenrir+Left / Right | Previous / next setting |
|
||||
| Fenrir+Control+Left / Right | Previous / next category |
|
||||
| Fenrir+Up / Down | Change value |
|
||||
| Fenrir+Control+S | Save settings |
|
||||
|
||||
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.
|
||||
|
||||
## Clipboard
|
||||
|
||||
Use review navigation to place two marks around text with **Fenrir+X**, then
|
||||
@@ -477,6 +477,30 @@ Sound output uses `pulse` for PulseAudio or PipeWire's PulseAudio service, or
|
||||
`alsa` for an ALSA PCM device. Select the driver and theme in Sound settings.
|
||||
The ALSA device name is set with `presentation.sound.device` in the file.
|
||||
|
||||
Speech Dispatcher has its own synthesis and audio configuration, separate
|
||||
from Fenrir's sound cues. For an X11 terminal session, run `./fenrir -x` as
|
||||
your regular user. With sudo, Fenrir uses `SUDO_UID` to locate the invoking
|
||||
user's PulseAudio socket. The default sound driver tries the user session,
|
||||
then `/tmp/pulse.sock`, then `/run/pulse/native`. Set `PULSE_SERVER` to select
|
||||
an explicit server; the sound driver does not read PulseAudio's `client.conf`.
|
||||
The sound service must already be running and accessible to the reader.
|
||||
See [Speech synthesizers](#speech-synthesizers) for Speech Dispatcher addresses
|
||||
and autostart behavior.
|
||||
|
||||
If root sound needs additional configuration, the checkout includes
|
||||
[configure_pulse.sh](../tools/configure_pulse.sh) for PulseAudio and
|
||||
[configure_pipewire.sh](../tools/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's `default.pa` and configures an anonymously accessible socket
|
||||
at `/tmp/pulse.sock`. 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.
|
||||
|
||||
For ALSA, select `driver = "alsa"` under `[presentation.sound]` in
|
||||
`settings.toml` and set `device` to the desired PCM name, such as `"default"`.
|
||||
Driver and device changes apply at the next launch.
|
||||
|
||||
Personal themes are searched under `~/.local/stormux/fenrir/sounds/` before
|
||||
bundled and system themes. A theme contains WAV files and `soundicons.toml`.
|
||||
|
||||
@@ -660,8 +684,10 @@ values. `./fenrir --version` identifies the build when reporting a problem.
|
||||
## Documentation maintenance and support
|
||||
|
||||
`docs/user.md` is the shared manual source. With Pandoc installed, run
|
||||
`./docs/create_manpage.sh` to regenerate `docs/user.txt`, `docs/fenrir.adoc`, and
|
||||
`docs/fenrir.1`. The script can run from any working directory.
|
||||
`./docs/create_manpage.sh` to regenerate `docs/user.txt` and `docs/fenrir.1`.
|
||||
The script can run from any working directory. Edit the Markdown source rather
|
||||
than the generated files. The bundled `docs/man_tables.lua` filter renders
|
||||
man-page tables as labeled lists for narrow terminals.
|
||||
|
||||
Please review documentation and test instructions for the affected workflow
|
||||
before submitting a change, as described in the README's contribution policy.
|
||||
|
||||
+326
-12
@@ -135,7 +135,11 @@ Speech and automatic reading
|
||||
- Fenrir+Backspace passes the next key through to the application.
|
||||
|
||||
Character echo, word echo, and cursor echo can be configured separately.
|
||||
Punctuation levels are none, some, most, and all. Character review still
|
||||
Punctuation levels are none, some, most, and all. At some and most,
|
||||
punctuation inside words, URLs, email addresses, and filenames is also
|
||||
named. Apostrophes within words and single numeric separators such as
|
||||
those in 3.14, 1,000, and 12:30 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.
|
||||
@@ -146,8 +150,9 @@ Fenrir+Shift+V announces the Fenrir version.
|
||||
Fenrir Menu and quick settings
|
||||
|
||||
Press Fenrir+F to open the Fenrir Menu. It contains settings tabs for
|
||||
presentation, speech, sound, reading, keyboard, internal UI, clipboard, and other
|
||||
options. The form captures its navigation keys until it closes.
|
||||
presentation, speech, sound, reading, keyboard, internal UI, clipboard,
|
||||
and other options. The form captures its navigation keys until it
|
||||
closes.
|
||||
|
||||
- At the tab selector, use arrows to choose a tab.
|
||||
- Tab and Shift+Tab move between controls and the tab selector.
|
||||
@@ -157,9 +162,10 @@ options. The form captures its navigation keys until it closes.
|
||||
changes.
|
||||
|
||||
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. 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.
|
||||
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.
|
||||
|
||||
The Internal UI tab controls speech in Fenrir’s own menus and dialogs.
|
||||
Announce grid row and column and Announce item position are independent
|
||||
@@ -190,6 +196,259 @@ 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.
|
||||
|
||||
Application overrides
|
||||
|
||||
Press Fenrir+A to open Applications. 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.
|
||||
|
||||
Type the start of a name to jump to it: n selects NetworkManager, then i
|
||||
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 No matches and leave the last
|
||||
matching search intact.
|
||||
|
||||
Start the application normally, then select its override. This menu does
|
||||
not launch programs. Choose Default 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.
|
||||
|
||||
To launch a program with its override, select its name in this list,
|
||||
then Tab to Copy alias to clipboard and press Enter. This copies a Bash
|
||||
alias into Fenrir’s clipboard without selecting the override or closing
|
||||
the menu. Paste it into your Bash configuration, such as ~/.bashrc, and
|
||||
load that configuration in a new shell. The aliases use the executable
|
||||
names cninjam, nmtui, rogue, and codex; Default has no alias. Existing
|
||||
aliases with those names are replaced when you load the definition.
|
||||
|
||||
The alias requests the override through socat, 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 socat is missing. Socket inactivity is limited to two
|
||||
seconds. It uses the standard socket, or your configured
|
||||
remote.socket_file, rather than a process-specific socket that changes
|
||||
at restart. Paste with Fenrir’s clipboard command; desktop clipboard
|
||||
synchronization follows your normal clipboard settings.
|
||||
|
||||
While an override is active, Fenrir+F opens its application settings,
|
||||
with the application name in the title. OK, Fenrir+Control+S, and remote
|
||||
SETTING SAVE save that application’s preferences. Quick and remote
|
||||
changes remain temporary until saved. Default settings are kept
|
||||
separately, including any unsaved adjustments made before activating the
|
||||
override.
|
||||
|
||||
Profiles live in an applications/ subdirectory of the ordinary settings
|
||||
save directory. For example:
|
||||
|
||||
- System settings:
|
||||
/etc/fenrirscreenreader/settings/applications/ninjam.toml.
|
||||
- Personal settings:
|
||||
~/.local/share/stormux/fenrirscreenreader/settings/applications/ninjam.toml.
|
||||
- With --config /path/settings.toml: /path/applications/ninjam.toml.
|
||||
|
||||
NetworkManager uses networkmanager.toml; Rogue uses rogue.toml; Codex
|
||||
uses codex.toml. 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.
|
||||
|
||||
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 SAVEAS and screen#ignore_screen 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.
|
||||
|
||||
For example, a rate-only profile contains current TOML setting names,
|
||||
with no top-level version field:
|
||||
|
||||
[presentation.speech]
|
||||
rate = 40
|
||||
|
||||
To make a saved value inherit again, remove that setting from the
|
||||
application file and reselect the override. Removing the file restores
|
||||
complete inheritance.
|
||||
|
||||
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 Default settings restored. 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.
|
||||
|
||||
NetworkManager targets nmtui and temporarily selects highlight tracking.
|
||||
|
||||
Ninjam targets the cninjam 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’s 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:
|
||||
|
||||
Shortcut Ninjam information
|
||||
---------- ---------------------------------------------------
|
||||
Fenrir+1 Latest new chat message received since activation
|
||||
Fenrir+2 Selected channel or control
|
||||
Fenrir+3 Connection, tempo, and interval position
|
||||
|
||||
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 X 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.
|
||||
|
||||
The laptop shortcut for reading attributes is Fenrir+Shift+A; Fenrir+A
|
||||
opens Applications in both layouts.
|
||||
|
||||
Rogue targets the classic English Rogue 5.4 terminal game, including the
|
||||
5.4.4 package. Start rogue, then select Rogue with Fenrir+A (type r,
|
||||
then Enter). The override announces messages and prompts, including
|
||||
More; press Space, 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.
|
||||
|
||||
Shortcut Rogue information
|
||||
---------- --------------------------------------------------------
|
||||
Fenrir+1 Health, for example “Health: 12 of 12”
|
||||
Fenrir+2 Full status line
|
||||
Fenrir+3 Latest message or prompt
|
||||
Fenrir+4 Eight neighboring cells, clockwise from north
|
||||
Fenrir+5 Visible monsters and their positions relative to you
|
||||
Fenrir+6 Visible objects and landmarks, with relative positions
|
||||
|
||||
These explicit reads include their region names. Names are supported by
|
||||
the shared application-region API, so other overrides can use them as
|
||||
needed. Fenrir+Shift+B 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.
|
||||
|
||||
Directions give cell offsets, for example “bat, north 2, east 3.”
|
||||
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.
|
||||
|
||||
Developers can exercise an installed classic Rogue in private PTYs
|
||||
without touching the active reader:
|
||||
|
||||
FENRIR_ROGUE_TEST_BINARY=/usr/bin/rogue go test ./internal/terminal -run TestRogueLiveOverride -v
|
||||
|
||||
Codex CLI
|
||||
|
||||
The Codex 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.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Shortcut Codex information
|
||||
----------------------------------- -----------------------------------
|
||||
Fenrir+1 through Fenrir+9 Recent completed assistant
|
||||
messages, newest first
|
||||
|
||||
Fenrir+0 Working, ready, waiting for
|
||||
approval or an answer, finished, or
|
||||
interrupted
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Select Codex with Fenrir+A, type c, then Enter. Select Default to leave
|
||||
the override. Without its bridge, the override suppresses automatic
|
||||
screen changes and the status shortcut says Waiting for Codex bridge.
|
||||
|
||||
The optional bridge requires Python 3 and Fenrir remote command control
|
||||
enabled. Merge a command hook invoking
|
||||
python3 /absolute/path/to/fenrir/tools/codex_bridge.py into each of
|
||||
these events in ~/.codex/hooks.json: SessionStart, UserPromptSubmit,
|
||||
PermissionRequest, PostToolUse, Stop, Interrupt, and SessionEnd. For
|
||||
example, one event entry is:
|
||||
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{"hooks": [{"type": "command", "command": "python3 /absolute/path/to/fenrir/tools/codex_bridge.py", "timeout": 3}]}]
|
||||
}
|
||||
}
|
||||
|
||||
Preserve existing hooks. Review and trust the added hooks through
|
||||
Codex’s /hooks 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.
|
||||
|
||||
The follower reads only the transcript path supplied by that
|
||||
conversation’s 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 SessionEnd hook runs.
|
||||
|
||||
X11 routing requires the same WINDOWID as the Fenrir instance; Linux
|
||||
console routing uses Codex’s controlling VT and the reader’s 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.
|
||||
|
||||
The transcript parser was checked against Codex CLI 0.165.0. It uses
|
||||
Codex’s 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’s animated activity
|
||||
label. Check Fenrir+0 after resuming.
|
||||
|
||||
For a private protocol and keyboard test without live speech or Codex
|
||||
requests:
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
Clipboard
|
||||
|
||||
Use review navigation to place two marks around text with Fenrir+X, then
|
||||
@@ -267,6 +526,30 @@ or alsa for an ALSA PCM device. Select the driver and theme in Sound
|
||||
settings. The ALSA device name is set with presentation.sound.device in
|
||||
the file.
|
||||
|
||||
Speech Dispatcher has its own synthesis and audio configuration,
|
||||
separate from Fenrir’s sound cues. For an X11 terminal session, run
|
||||
./fenrir -x as your regular user. With sudo, Fenrir uses SUDO_UID to
|
||||
locate the invoking user’s PulseAudio socket. The default sound driver
|
||||
tries the user session, then /tmp/pulse.sock, then /run/pulse/native.
|
||||
Set PULSE_SERVER to select an explicit server; the sound driver does not
|
||||
read PulseAudio’s client.conf. The sound service must already be running
|
||||
and accessible to the reader. See Speech synthesizers for Speech
|
||||
Dispatcher addresses and autostart behavior.
|
||||
|
||||
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’s default.pa and configures an
|
||||
anonymously accessible socket at /tmp/pulse.sock. 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.
|
||||
|
||||
For ALSA, select driver = "alsa" under [presentation.sound] in
|
||||
settings.toml and set device to the desired PCM name, such as "default".
|
||||
Driver and device changes apply at the next launch.
|
||||
|
||||
Personal themes are searched under ~/.local/stormux/fenrir/sounds/
|
||||
before bundled and system themes. A theme contains WAV files and
|
||||
soundicons.toml.
|
||||
@@ -289,10 +572,10 @@ options. Fenrir loads one settings file rather than merging files.
|
||||
- --config PATH: use that file explicitly.
|
||||
|
||||
If default files are absent, Fenrir uses built-in defaults. Python
|
||||
settings.conf files are ignored. Regular users save to their personal TOML
|
||||
file, including when startup loaded system defaults; root saves to the system
|
||||
file. --config PATH explicitly selects both the load and save path, and that
|
||||
file must exist at startup.
|
||||
settings.conf files are ignored. Regular users save to their personal
|
||||
TOML file, including when startup loaded system defaults; root saves to
|
||||
the system file. --config PATH explicitly selects both the load and save
|
||||
path, and that file must exist at startup.
|
||||
|
||||
Create a personal settings file and validate it without opening devices:
|
||||
|
||||
@@ -311,6 +594,27 @@ Speech synthesizers
|
||||
The default driver is speech-dispatcher. Select its module, language,
|
||||
and voice in Speech settings; empty values use server defaults.
|
||||
|
||||
Fenrir uses SPEECHD_ADDRESS when set: unix_socket:/absolute/path selects
|
||||
a Unix socket, and inet_socket:HOST:PORT selects TCP (default host
|
||||
127.0.0.1, port 6560). Invalid addresses report an error. Otherwise,
|
||||
SPEECHD_SOCKET selects a Unix socket. Without either variable, Fenrir
|
||||
uses $XDG_RUNTIME_DIR/speech-dispatcher/speechd.sock, falling back to
|
||||
$XDG_CACHE_HOME/speech-dispatcher/speechd.sock or
|
||||
~/.cache/speech-dispatcher/speechd.sock when the runtime directory is
|
||||
unset. With sudo, the default remains
|
||||
/run/user/$SUDO_UID/speech-dispatcher/speechd.sock. Sudo may remove
|
||||
address variables; preserve them explicitly if needed.
|
||||
|
||||
When opening speech, Fenrir first tries the selected server. If its
|
||||
socket is missing or refuses connections, Fenrir requests
|
||||
speech-dispatcher --spawn and briefly retries. The daemon’s
|
||||
configuration controls whether spawning is allowed. SPEECHD_CMD 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.
|
||||
|
||||
Hardware driver IDs are dectalk, dectalk-usb, litetalk, doubletalk, and
|
||||
tripletalk. Serial drivers require presentation.speech.hardware_device,
|
||||
for example /dev/ttyUSB0, and default to 9600 baud when
|
||||
@@ -360,6 +664,14 @@ Other supported operations include:
|
||||
- command tempdisablespeech: temporarily silence speech.
|
||||
- command clipboard TEXT: add text to the clipboard.
|
||||
- command exportclipboard: export the selected clipboard.
|
||||
- command application ID: select default, networkmanager, ninjam, rogue,
|
||||
or codex for this reader’s 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. default
|
||||
restores ordinary settings. Use a private socket when targeting a
|
||||
particular reader.
|
||||
- command window X1 Y1 X2 Y2: set a reading window, using zero-based,
|
||||
inclusive coordinates.
|
||||
- command resetwindow: clear the window.
|
||||
@@ -451,8 +763,10 @@ problem.
|
||||
Documentation maintenance and support
|
||||
|
||||
docs/user.md is the shared manual source. With Pandoc installed, run
|
||||
./docs/create_manpage.sh to regenerate docs/user.txt, docs/fenrir.adoc,
|
||||
and docs/fenrir.1. The script can run from any working directory.
|
||||
./docs/create_manpage.sh to regenerate docs/user.txt and docs/fenrir.1.
|
||||
The script can run from any working directory. Edit the Markdown source
|
||||
rather than the generated files. The bundled docs/man_tables.lua filter
|
||||
renders man-page tables as labeled lists for narrow terminals.
|
||||
|
||||
Please review documentation and test instructions for the affected
|
||||
workflow before submitting a change, as described in the README’s
|
||||
|
||||
@@ -66,6 +66,28 @@ func TestURLSpeechKeepsEmbeddedPunctuationAndOriginalClipboardText(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageProgressBarSpeechKeepsOriginalClipboardText(t *testing.T) {
|
||||
processor, _, err := punctuation.Load([]string{"../../config/punctuation/default.toml"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
settings := config.Defaults()
|
||||
settings.Reading.RepeatedSymbols = true
|
||||
voice := &fakeVoice{}
|
||||
echo := &echoSpeaker{Speaker: voice, punctuation: processor, punctuationLevel: "some", settings: &settings}
|
||||
text := "(123/189) upgrading nodejs-lts-jod" + strings.Repeat(" ", 157) + "[" + strings.Repeat("#", 120) + "] 100%"
|
||||
echo.Say(text)
|
||||
if len(voice.messages) != 1 {
|
||||
t.Fatal("missing progress speech", voice.messages)
|
||||
}
|
||||
if got := strings.Join(strings.Fields(voice.messages[0]), " "); got != "123 slash 189 upgrading nodejs dash lts dash jod 120 number 100" {
|
||||
t.Fatal("progress bar did not summarize", got)
|
||||
}
|
||||
if echo.last != text {
|
||||
t.Fatal("clipboard echo lost original progress bar", echo.last)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReviewCharactersUseProfileRegardlessOfLevelAndKeepBoundaries(t *testing.T) {
|
||||
processor, _, err := punctuation.Load([]string{"../../config/punctuation/fr.toml"})
|
||||
if err != nil {
|
||||
|
||||
@@ -47,10 +47,24 @@ func (p *Processor) process_token(token, level string, options TextOptions) stri
|
||||
}
|
||||
}
|
||||
if options.RepeatedSymbols && options.RepeatedSymbolsMin >= 2 && token != "" {
|
||||
char, _ := utf8.DecodeRuneInString(token)
|
||||
repeated := token
|
||||
prefix, suffix := "", ""
|
||||
// Progress bars commonly enclose a repeated run in brackets. Keep
|
||||
// those delimiters under ordinary punctuation handling, and require
|
||||
// the entire interior to repeat so paths and mixed tokens stay literal.
|
||||
if len(token) >= 2 {
|
||||
for _, pair := range []string{"[]", "()", "{}", "<>"} {
|
||||
if token[0] == pair[0] && token[len(token)-1] == pair[1] {
|
||||
prefix, suffix = token[:1], token[len(token)-1:]
|
||||
repeated = token[1 : len(token)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
char, _ := utf8.DecodeRuneInString(repeated)
|
||||
if p.levels[level][char] && (unicode.IsPunct(char) || unicode.IsSymbol(char)) {
|
||||
count := 0
|
||||
for _, next := range token {
|
||||
for _, next := range repeated {
|
||||
if next != char {
|
||||
return p.Text(token, level)
|
||||
}
|
||||
@@ -66,7 +80,7 @@ func (p *Processor) process_token(token, level string, options TextOptions) stri
|
||||
name = i18n.T(name)
|
||||
}
|
||||
}
|
||||
return i18n.Format("{0} {1}", strconv.Itoa(count), name)
|
||||
return p.Text(prefix, level) + i18n.Format("{0} {1}", strconv.Itoa(count), name) + p.Text(suffix, level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,17 @@ func TestTextSubstitutionsAndBoundaries(t *testing.T) {
|
||||
{"#### ####", "4 number 4 number"},
|
||||
{"##### title #####", "5 number title 5 number"},
|
||||
{"////", "4 slash"},
|
||||
{"[#####]", " 5 number "},
|
||||
{"(#####)", " 5 number "},
|
||||
{"{#####}", " 5 number "},
|
||||
{"<#####>", " 5 number "},
|
||||
{"Oo", "WTF?"},
|
||||
} {
|
||||
if got := processor.Process_text(trial.text, "some", options); got != trial.want {
|
||||
t.Errorf("%q: %q, want %q", trial.text, got, trial.want)
|
||||
}
|
||||
}
|
||||
for _, text := range []string{"hello :)!", "path/to:)file", "https://example.invalid/:)", "https://example.invalid/:-/", "(o_O)", "###", "##--##", "a####b", "../....", "https://example.invalid/####", "10000", "aaaa", "🙂🙂🙂🙂", ""} {
|
||||
for _, text := range []string{"hello :)!", "path/to:)file", "https://example.invalid/:)", "https://example.invalid/:-/", "(o_O)", "###", "##--##", "a####b", "../....", "https://example.invalid/####", "10000", "aaaa", "🙂🙂🙂🙂", "", "[]", "[###]", "[####)", "[##--##]", "[a####b]", "[../....]", "[https://example.invalid/####]"} {
|
||||
for _, level := range Levels() {
|
||||
if got, want := processor.Process_text(text, level, options), processor.Text(text, level); got != want {
|
||||
t.Errorf("%q, %s changed ordinary processing: %q, want %q", text, level, got, want)
|
||||
@@ -101,6 +105,30 @@ func TestSubstitutionOptionsAndProfileNames(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBracketedRepeatedSymbolsRespectOptionsAndLevels(t *testing.T) {
|
||||
processor, _, err := Load([]string{"../../config/punctuation/default.toml"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, level := range Levels() {
|
||||
for _, options := range []TextOptions{
|
||||
{},
|
||||
{Emoticons: true},
|
||||
{RepeatedSymbols: true, RepeatedSymbolsMin: 1},
|
||||
{RepeatedSymbols: true, RepeatedSymbolsMin: 6},
|
||||
{RepeatedSymbols: true, RepeatedSymbolsMin: 4},
|
||||
} {
|
||||
want := processor.Text("[#####]", level)
|
||||
if options.RepeatedSymbols && options.RepeatedSymbolsMin == 4 && level != "none" {
|
||||
want = processor.Text("[", level) + "5 number" + processor.Text("]", level)
|
||||
}
|
||||
if got := processor.Process_text("[#####]", level, options); got != want {
|
||||
t.Errorf("level %s, options %+v: got %q, want %q", level, options, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextSubstitutionTranslationsAndFieldOrder(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
directory := filepath.Join(root, "xx", "LC_MESSAGES")
|
||||
|
||||
Reference in new issue
Block a user