Merge branch 'testing' moving closer to tagged release.

This commit is contained in:
Storm Dragon
2025-07-09 18:32:15 -04:00
10 changed files with 304 additions and 62 deletions

173
README.md
View File

@ -12,6 +12,8 @@ This software is licensed under the LGPL v3.
- **Multiple Interface Support**: Works in Linux TTY, and terminal emulators
- **Flexible Driver System**: Modular architecture with multiple drivers for speech, sound, input, and screen
- **Review Mode**: Navigate and review screen content without moving the edit cursor
- **Table Navigation**: Advanced table mode with column headers, cell-by-cell navigation, and boundary feedback
- **Progress Bar Monitoring**: Automatic detection and audio feedback for progress indicators with ascending tones
- **Multiple Clipboard Support**: Manage multiple clipboard entries
- **Configurable Key Bindings**: Desktop and laptop keyboard layouts
- **Sound Icons**: Audio feedback for various events
@ -156,6 +158,7 @@ By default Fenrir uses:
- `Keypad 2` - Read current character
- `Fenrir + T` - Announce time
- `Fenrir + S` - Spell check current word
- `Fenrir + Keypad *` - Toggle table mode / highlight tracking
### Keyboard Layouts
@ -402,6 +405,176 @@ setting <action> [parameters]
- `time#delaySec=seconds` - Announcement interval
- `time#onMinutes=00,30` - Specific minutes to announce
## Table Navigation
Fenrir includes advanced table navigation capabilities for working with tabular data in terminal applications, CSV files, and formatted text output.
### Entering Table Mode
Table mode is activated through the **toggle_highlight_tracking** command, which cycles through three focus modes:
1. **Highlight tracking mode** (default) - Follows text highlighting
2. **Cursor tracking mode** - Follows text cursor movement
3. **Table mode** - Enables table navigation
**Key bindings:**
- **Desktop layout**: `Fenrir + Keypad *` (asterisk)
- **Laptop layout**: `Fenrir + Y`
Press the key combination repeatedly to cycle through modes until you hear "table mode enabled".
### Table Navigation Commands
#### Column Navigation (Desktop Layout)
- **Next column**: `Keypad 6` - Move to next table column
- **Previous column**: `Keypad 4` - Move to previous table column
- **First column**: `Fenrir + Keypad 4` - Jump to first column of current row
- **Last column**: `Fenrir + Keypad 6` - Jump to last column of current row
#### Column Navigation (Laptop Layout)
- **Next column**: `Fenrir + L` - Move to next table column
- **Previous column**: `Fenrir + J` - Move to previous table column
- **First column**: `Fenrir + Shift + J` - Jump to first column of current row
- **Last column**: `Fenrir + Shift + L` - Jump to last column of current row
#### Cell Character Navigation
- **First character in cell**: `Fenrir + Keypad 1` (desktop) or `Fenrir + Ctrl + J` (laptop)
- **Last character in cell**: `Fenrir + Keypad 3` (desktop) or `Fenrir + Ctrl + L` (laptop)
### Setting Column Headers
For better navigation experience, you can set column headers:
1. **Navigate to header row**: Use normal navigation to reach the row containing column headers
2. **Set headers**: Press `Fenrir + X` to mark the current line as the header row
3. **Navigation feedback**: Column headers will be announced along with cell content
### Table Detection
Fenrir automatically detects table structures using multiple strategies:
- **Delimited text**: CSV, pipe-separated (`|`), semicolon-separated (`;`), tab-separated
- **Aligned columns**: Space-aligned columns (2+ spaces between columns)
- **Flexible parsing**: Handles various table formats commonly found in terminal applications
### Table Mode Features
- **Cell-by-cell navigation**: Navigate through table cells with precise positioning
- **Column header support**: Set and announce column headers for better context
- **Boundary feedback**: Audio cues when reaching start/end of rows
- **Empty cell handling**: Blank cells are announced as "blank"
- **Independent tracking**: Table position is maintained independently of cursor movement
### Speech Output in Table Mode
When navigating in table mode, Fenrir announces:
- **Cell content** followed by **column header/name**
- **Boundary notifications**: "end of line", "start of line"
- **Position indicators**: "first character in cell [column name]"
### Example Usage
```bash
# Working with CSV data
cat data.csv
Name,Age,City
Alice,30,New York
Bob,25,Los Angeles
# 1. Press Fenrir + Keypad * until "table mode enabled"
# 2. Navigate to "Name,Age,City" line
# 3. Press Fenrir + X to set headers
# 4. Use Keypad 4/6 to navigate between columns
# 5. Each cell will be announced with its column header
```
## Progress Bar Monitoring
Fenrir provides intelligent progress bar detection and audio feedback for various progress indicators commonly found in terminal applications.
### Enabling Progress Monitoring
**Command**: `progress_bar_monitor` (no default key binding - assign manually)
To enable progress monitoring:
1. Add a key binding in your keyboard layout file
2. Or use the remote control system: `echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock`
### Progress Detection Patterns
Fenrir automatically detects various progress indicator formats:
#### 1. Percentage Progress
```
Download: 45%
Processing: 67.5%
Installing: 100%
```
#### 2. Fraction Progress
```
Files: 15/100
Progress: 3 of 10
Step 7/15
```
#### 3. Progress Bars
```
[#### ] 40%
[====> ] 50%
[**********] 100%
```
#### 4. Activity Indicators
```
Loading...
Processing...
Working...
Installing...
Downloading...
Compiling...
Building...
```
### Audio Feedback
#### Progress Tones
- **Ascending tones**: 400Hz to 1200Hz frequency range
- **Percentage mapping**: 0% = 400Hz, 100% = 1200Hz
- **Smooth progression**: Frequency increases proportionally with progress
#### Activity Indicators
- **Steady beep**: 800Hz tone every 2 seconds for ongoing activity
- **Non-intrusive**: Beeps don't interrupt speech or other audio
### Progress Monitoring Features
- **Automatic detection**: No manual configuration required
- **Multiple format support**: Handles various progress indicator styles
- **Prompt awareness**: Automatically pauses when command prompts are detected
- **Non-blocking**: Progress tones don't interrupt speech or other functionality
- **Configurable**: Can be enabled/disabled as needed
### Usage Examples
```bash
# Enable progress monitoring
echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
# Common scenarios where progress monitoring is useful:
wget https://example.com/large-file.zip # Download progress
tar -xvf archive.tar.gz # Extraction progress
make -j4 # Compilation progress
pacman -S package # Package installation
rsync -av source/ destination/ # File synchronization
```
### Customization
Progress monitoring can be configured through settings:
- **Default enabled**: Set `progressMonitoring=True` in sound section
- **Sound integration**: Works with all sound drivers (sox, gstreamer)
- **Remote control**: Enable/disable through remote commands
### Scripting Examples
#### Bash Script for Speech Notifications

View File

@ -50,7 +50,7 @@ def check_dependency(dep: Dependency) -> bool:
dependencyList = [
# Core dependencies
Dependency('FenrirCore', 'core', 'core',
pythonImports=['daemonize', 'enchant']),
pythonImports=['daemonize', 'enchant', 'pyperclip', 'setproctitle']),
# Screen drivers
Dependency('DummyScreen', 'screen', 'dummyDriver'),
@ -58,7 +58,7 @@ dependencyList = [
pythonImports=['dbus'],
devicePaths=['/dev/vcsa']),
Dependency('PTY', 'screen', 'ptyDriver',
pythonImports=['pyte']),
pythonImports=['pyte', 'xdg']),
# Input drivers
Dependency('DummyInput', 'input', 'dummyDriver'),
@ -82,7 +82,11 @@ dependencyList = [
Dependency('Speechd', 'speech', 'speechdDriver',
pythonImports=['speechd']),
Dependency('GenericSpeech', 'speech', 'genericDriver',
checkCommands=['espeak-ng'])
checkCommands=['espeak-ng']),
# Additional dependencies
Dependency('Pexpect', 'core', 'pexpectDriver',
pythonImports=['pexpect'])
]
defaultModules = {
@ -90,7 +94,8 @@ defaultModules = {
'VCSA',
'Evdev',
'GenericSpeech',
'GenericSound'
'GenericSound',
'Pexpect'
}
def check_all_dependencies():

View File

@ -1,4 +1,46 @@
# Fenrir Keyboard Configuration
This directory contains keyboard layout files for Fenrir screen reader.
## Available Layouts
- **desktop.conf** - Desktop layout using numeric keypad (recommended)
- **laptop.conf** - Laptop layout for keyboards without numeric keypad
- **nvda-desktop.conf** - NVDA-compatible desktop layout
- **nvda-laptop.conf** - NVDA-compatible laptop layout
- **pty.conf** - PTY emulation layout for terminal use
- **pty2.conf** - Alternative PTY emulation layout
## Key Features
### Table Navigation
- **Toggle table mode**: `Fenrir + Keypad *` (desktop) or `Fenrir + Y` (laptop)
- **Column navigation**: `Keypad 4/6` (desktop) or `Fenrir + J/L` (laptop)
- **Row boundaries**: `Fenrir + Keypad 4/6` (desktop) or `Fenrir + Shift + J/L` (laptop)
- **Set headers**: `Fenrir + X` in table mode
### Progress Bar Monitoring
- **Monitor progress**: `progress_bar_monitor` command (assign key binding manually)
- **Auto-detection**: Percentage, fractions, progress bars, activity indicators
- **Audio feedback**: Ascending tones (400Hz-1200Hz) for progress
### Review Mode
- **Basic navigation**: `Keypad 7/8/9` (lines), `Keypad 4/5/6` (words), `Keypad 1/2/3` (characters)
- **Exit review**: `Fenrir + Keypad .`
- **Screen reading**: `Fenrir + Keypad 5` (current screen)
## Configuration
To change keyboard layout, edit `/etc/fenrir/settings/settings.conf`:
```ini
[keyboard]
keyboardLayout=desktop # or laptop, nvda-desktop, nvda-laptop, pty, pty2
```
## Available Key Constants
Keymap for Fenrir
KEY_RESERVED
KEY_ESC

View File

@ -50,6 +50,12 @@ Navigate the screen without moving the text cursor. Essential for examining cont
- `Keypad 1/3` - Previous/next character
- `Fenrir + Keypad dot` - Exit review mode
### Table Navigation
- `Fenrir + Keypad *` - Toggle table mode / highlight tracking
- `Keypad 4/6` - Previous/next column (in table mode)
- `Fenrir + Keypad 4/6` - First/last column (in table mode)
- `Fenrir + X` - Set column headers (in table mode)
### Information
- `Fenrir + T` - Announce time
- `Fenrir + T T` - Announce date
@ -240,6 +246,47 @@ send_fenrir_command("command say Process complete")
## Advanced Features
### Table Navigation Mode
Fenrir includes advanced table navigation capabilities for working with tabular data in terminal applications, CSV files, and formatted text output.
#### Entering Table Mode
1. Press `Fenrir + Keypad *` (desktop) or `Fenrir + Y` (laptop)
2. Cycle through: Highlight tracking → Cursor tracking → Table mode
3. Listen for "table mode enabled" announcement
#### Table Navigation Commands
- **Column navigation**: `Keypad 4/6` - Move between columns
- **Row boundaries**: `Fenrir + Keypad 4/6` - Jump to first/last column
- **Cell characters**: `Fenrir + Keypad 1/3` - First/last character in cell
- **Set headers**: `Fenrir + X` - Mark current line as column headers
#### Table Features
- **Automatic detection**: Supports CSV, pipe-separated, space-aligned columns
- **Column headers**: Set and announce headers for better context
- **Boundary feedback**: Audio cues when reaching row boundaries
- **Cell-by-cell navigation**: Precise positioning within tables
### Progress Bar Monitoring
Fenrir automatically detects and provides audio feedback for progress indicators.
#### Progress Detection
- **Percentage**: 45%, 67.5%, 100%
- **Fractions**: 15/100, 3 of 10, Step 7/15
- **Progress bars**: [#### ], [====> ]
- **Activity indicators**: Loading..., Processing...
#### Audio Feedback
- **Progress tones**: Ascending 400Hz-1200Hz frequency range
- **Activity beeps**: 800Hz tone every 2 seconds
- **Non-intrusive**: Doesn't interrupt speech or other audio
#### Usage
- **Enable**: Use `progress_bar_monitor` command (assign key binding)
- **Automatic**: Works with downloads, compilations, installations
- **Remote control**: Enable via socket commands
### Spell Checking
- `Fenrir + S` - Spell check current word
- `Fenrir + S S` - Add word to dictionary

View File

@ -20,22 +20,15 @@ class command:
pass
def get_description(self):
return _("presents the date")
return _("Test mc search functionality")
def run(self):
date_format = self.env["runtime"]["SettingsManager"].get_setting(
"general", "date_format"
)
# Test command for mc search operations
test_message = _("MC search test: This demonstrates search functionality")
# get the time formatted
date_string = datetime.datetime.strftime(
datetime.datetime.now(), date_format
)
# present the time via speak and braile, there is no soundicon,
# interrupt the current speech
# present the test message
self.env["runtime"]["OutputManager"].present_text(
date_string, sound_icon="", interrupt=True
test_message, sound_icon="", interrupt=True
)
def set_callback(self, callback):

View File

@ -20,22 +20,15 @@ class command:
pass
def get_description(self):
return _("presents the date")
return _("Test mutt search functionality")
def run(self):
date_format = self.env["runtime"]["SettingsManager"].get_setting(
"general", "date_format"
)
# Test command for mutt search operations
test_message = _("Mutt search test: This demonstrates search functionality")
# get the time formatted
date_string = datetime.datetime.strftime(
datetime.datetime.now(), date_format
)
# present the time via speak and braile, there is no soundicon,
# interrupt the current speech
# present the test message
self.env["runtime"]["OutputManager"].present_text(
date_string, sound_icon="", interrupt=True
test_message, sound_icon="", interrupt=True
)
def set_callback(self, callback):

View File

@ -20,22 +20,15 @@ class command:
pass
def get_description(self):
return _("presents the date")
return _("Test nano search functionality")
def run(self):
date_format = self.env["runtime"]["SettingsManager"].get_setting(
"general", "date_format"
)
# Test command for nano search operations
test_message = _("Nano search test: This demonstrates search functionality")
# get the time formatted
date_string = datetime.datetime.strftime(
datetime.datetime.now(), date_format
)
# present the time via speak and braile, there is no soundicon,
# interrupt the current speech
# present the test message
self.env["runtime"]["OutputManager"].present_text(
date_string, sound_icon="", interrupt=True
test_message, sound_icon="", interrupt=True
)
def set_callback(self, callback):

View File

@ -20,22 +20,15 @@ class command:
pass
def get_description(self):
return _("presents the date")
return _("Test vim search functionality")
def run(self):
date_format = self.env["runtime"]["SettingsManager"].get_setting(
"general", "date_format"
)
# Test command for vim search operations
test_message = _("Vim search test: This demonstrates search functionality")
# get the time formatted
date_string = datetime.datetime.strftime(
datetime.datetime.now(), date_format
)
# present the time via speak and braile, there is no soundicon,
# interrupt the current speech
# present the test message
self.env["runtime"]["OutputManager"].present_text(
date_string, sound_icon="", interrupt=True
test_message, sound_icon="", interrupt=True
)
def set_callback(self, callback):

View File

@ -64,7 +64,7 @@ class ProcessManager:
args=(event_queue, function, pargs, run_once),
)
self._Processes.append(t)
else: # thread not implemented yet
else: # use thread instead of process
t = Thread(
target=self.custom_event_worker_thread,
args=(event_queue, function, pargs, run_once),

View File

@ -494,11 +494,14 @@ class SettingsManager:
self.set_setting("general", "debug_level", 3)
self.set_setting("general", "debug_mode", "PRINT")
if cliArgs.emulated_pty:
self.set_setting("screen", "driver", "ptyDriver")
self.set_setting("keyboard", "driver", "ptyDriver")
# TODO needs cleanup use dict
# self.set_option_arg_dict('keyboard', 'keyboardLayout', 'pty')
self.set_setting("keyboard", "keyboardLayout", "pty")
# Set PTY driver settings
pty_settings = {
"screen": {"driver": "ptyDriver"},
"keyboard": {"driver": "ptyDriver", "keyboardLayout": "pty"}
}
for section, settings in pty_settings.items():
for key, value in settings.items():
self.set_setting(section, key, value)
if cliArgs.emulated_evdev:
self.set_setting("screen", "driver", "ptyDriver")
self.set_setting("keyboard", "driver", "evdevDriver")