Compare commits
161 Commits
2025.04.28
...
900a027643
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
900a027643 | ||
|
|
0e50175463 | ||
|
|
7283f04778 | ||
|
|
8d3495f74f | ||
|
|
a6cd47dafc | ||
|
|
0bb2e52deb | ||
|
|
b8eb815a86 | ||
|
|
beca468338 | ||
|
|
a26fe26c8c | ||
|
|
508fd11610 | ||
|
|
afe0e71a1d | ||
|
|
9e8d0b3869 | ||
|
|
d7f86ca0de | ||
|
|
49a79d2722 | ||
|
|
4ab024d115 | ||
|
|
c4ae27a01b | ||
|
|
668d39b444 | ||
|
|
8b25afbf5a | ||
|
|
efeb040f75 | ||
|
|
7a17b36d50 | ||
|
|
047a31b4bf | ||
|
|
096aef9f08 | ||
|
|
76472b83b5 | ||
|
|
a52bf624ec | ||
|
|
f4e28a246f | ||
|
|
560ceb26c9 | ||
|
|
61868c94e5 | ||
|
|
f462ca7990 | ||
|
|
f0bbcb8a38 | ||
|
|
aed627ec2a | ||
|
|
e62b887e9c | ||
|
|
bf0d134187 | ||
|
|
c66a9ba9c2 | ||
|
|
2092a3e257 | ||
|
|
d46d8de3ee | ||
|
|
75a8447759 | ||
|
|
1650eec768 | ||
|
|
5bb786ef4c | ||
|
|
7f7faa17d3 | ||
|
|
2766f70c5d | ||
|
|
8d781643bc | ||
|
|
c184cf023a | ||
|
|
841c221c7b | ||
|
|
87553bdc38 | ||
|
|
77a3aae5a4 | ||
|
|
aabc202d83 | ||
|
|
2f3a114790 | ||
|
|
c797974560 | ||
|
|
af4740d5ad | ||
|
|
5ef5faaebe | ||
|
|
7041d2567a | ||
|
|
2c38bcf5f4 | ||
|
|
96cdda99c4 | ||
|
|
0658d37ae8 | ||
|
|
a6bb3e1301 | ||
|
|
5ff653bd00 | ||
|
|
356f4b01c1 | ||
|
|
c7ad4d9200 | ||
|
|
d274fe78f3 | ||
|
|
f5344a7227 | ||
|
|
90ffc2fc08 | ||
|
|
b635f7538b | ||
|
|
7f473b72a7 | ||
|
|
e255651c28 | ||
|
|
b3d73102fc | ||
|
|
78c1cbbb6b | ||
|
|
8c26d93001 | ||
|
|
98b9c56af7 | ||
|
|
8bada48a09 | ||
|
|
0a2c8472c0 | ||
|
|
e9a0101fe7 | ||
|
|
69eade3327 | ||
|
|
73f67c2a04 | ||
|
|
9ef9d762f4 | ||
|
|
84293db6dc | ||
|
|
914535d12b | ||
|
|
94a1acbaca | ||
|
|
8c233e0385 | ||
|
|
b6a9e1a692 | ||
|
|
d41ea8388f | ||
|
|
2dd732dc9d | ||
|
|
b68a28e857 | ||
|
|
8c668cc0cc | ||
|
|
579bf0f0f0 | ||
|
|
d1bad818cd | ||
|
|
e177c7f486 | ||
|
|
ae4c418323 | ||
|
|
b9abf02b12 | ||
|
|
0c116adaf2 | ||
|
|
fe5e2c065e | ||
|
|
5a14804d11 | ||
|
|
ef3ebee10c | ||
|
|
6876995d4c | ||
|
|
01f4b64390 | ||
|
|
5e858cfde1 | ||
|
|
2ad754a372 | ||
|
|
271c4fc18f | ||
|
|
bb6dbc7186 | ||
|
|
c7cc9d039b | ||
|
|
d1a42835e4 | ||
|
|
3390c25dfe | ||
|
|
ea56b90b48 | ||
|
|
1268d989b7 | ||
|
|
d28c18faed | ||
|
|
c90c726899 | ||
|
|
bab7c1a552 | ||
|
|
848844aae4 | ||
|
|
4c1bddbbd3 | ||
|
|
21bb9c6083 | ||
|
|
7408951152 | ||
|
|
23c3ad20a1 | ||
|
|
4bcf82178e | ||
|
|
beae1866bb | ||
|
|
8af1cca879 | ||
|
|
40b88efa34 | ||
|
|
b1edc53362 | ||
|
|
dda84b9905 | ||
|
|
64e79f6945 | ||
|
|
f4ed8da4c3 | ||
|
|
a5ca1d28e8 | ||
|
|
a394ea0222 | ||
|
|
4e193f133f | ||
|
|
27dcff23bb | ||
|
|
efb308ac72 | ||
|
|
d81d563bb6 | ||
|
|
43871cea3c | ||
|
|
72bd334d65 | ||
|
|
f6be6c54fb | ||
|
|
e76b914d6e | ||
|
|
83cb330d34 | ||
|
|
b0ac6e1409 | ||
|
|
6998706934 | ||
|
|
62e1001679 | ||
|
|
d935ef2e3c | ||
|
|
e2fb28d92f | ||
|
|
8a223282df | ||
|
|
91c97dd1dd | ||
|
|
5cc719a6f3 | ||
|
|
ddc1b43304 | ||
|
|
6ad11effc6 | ||
|
|
f18c31df6c | ||
|
|
ca0e3b5987 | ||
|
|
0009d90a68 | ||
|
|
2c2efc56f0 | ||
|
|
3dca3e5b23 | ||
|
|
27c35939b1 | ||
|
|
7e87ebf04b | ||
|
|
ec6c135581 | ||
|
|
998c63cc71 | ||
|
|
26c6e32c59 | ||
|
|
97e2da614b | ||
|
|
0930a86ce7 | ||
|
|
1b9a9a90b1 | ||
|
|
a742c12cd8 | ||
|
|
8d50003730 | ||
|
|
4c8c8d896d | ||
|
|
bd151c7cec | ||
|
|
6f4784daed | ||
|
|
8c471adfa4 | ||
|
|
77065c55b4 | ||
|
|
7f75c231e1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ dist/
|
||||
build/
|
||||
*.kate-swp
|
||||
.directory
|
||||
CLAUDE.md
|
||||
|
||||
28
CREDITS
28
CREDITS
@@ -1,18 +1,30 @@
|
||||
# Fenrir screen reader
|
||||
# Fenrir Screen Reader Credits
|
||||
|
||||
|
||||
## Developers
|
||||
## Current Maintainer
|
||||
|
||||
* Storm Dragon: Project leader
|
||||
* Jeremiah: Coder.
|
||||
* **Storm Dragon** - Project leader and maintainer
|
||||
|
||||
|
||||
## Current Contributors
|
||||
|
||||
* **Jeremiah** - Developer
|
||||
|
||||
|
||||
## Previous Developers
|
||||
|
||||
* Chrys: coder.
|
||||
* **Chrys** - Original creator and main developer
|
||||
|
||||
|
||||
## Special thanks to:
|
||||
## Special Thanks
|
||||
|
||||
* F123 Consulting for suggestions, some funding, and endless testing.
|
||||
* Stormux for continuation of the project.
|
||||
* **F123 Consulting** - Suggestions, funding, and extensive testing
|
||||
* **Stormux Community** - Continuation of the project and ongoing support
|
||||
* **All contributors** - Bug reports, feature requests, and community support
|
||||
|
||||
|
||||
## Community
|
||||
|
||||
* IRC: irc.stormux.org #stormux
|
||||
* Email list: stormux+subscribe@groups.io
|
||||
* Wiki: https://git.stormux.org/storm/fenrir/wiki
|
||||
|
||||
745
README.md
745
README.md
@@ -1,69 +1,99 @@
|
||||
# Fenrir
|
||||
|
||||
A modern, modular, flexible and fast console screenreader.
|
||||
A modern, modular, flexible and fast console screen reader.
|
||||
It should run on any operating system. If you want to help, or write drivers to make it work on other systems, just let me know.
|
||||
This software is licensed under the LGPL v3.
|
||||
|
||||
**Current maintainer:** Storm Dragon
|
||||
**Previous developer:** Chrys
|
||||
|
||||
## Key Features
|
||||
|
||||
- **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
|
||||
- **Spell Checking**: Built-in spell checker with word management
|
||||
- **Language Support**: Multiple speech synthesis languages and voices
|
||||
- **Bookmark System**: Quick access to specific screen areas
|
||||
- **Auto-announcement**: Automatic reading of incoming text and time announcements
|
||||
- **Tutorial Mode**: Built-in help system for learning keyboard shortcuts
|
||||
|
||||
|
||||
## OS Requirements
|
||||
|
||||
- Linux (ptyDriver, vcsaDriver, evdevDriver)
|
||||
- macOS (ptyDriver)
|
||||
- BSD (ptyDriver)
|
||||
- Windows (ptyDriver)
|
||||
- Linux (ptyDriver, vcsaDriver, evdevDriver) - Primary platform with full support
|
||||
- macOS (ptyDriver) - Limited support
|
||||
- BSD (ptyDriver) - Limited support
|
||||
- Windows (ptyDriver) - Limited support
|
||||
|
||||
|
||||
## Core Requirements
|
||||
|
||||
- python3 >= 3.3
|
||||
- screen, input, speech, sound drivers dependencies see "Features, Drivers, Extras".
|
||||
- Python 3 >= 3.9 (recommended 3.13+)
|
||||
- Screen, input, speech, sound driver dependencies (see "Features, Drivers, Extras" section)
|
||||
- For full functionality on Linux: evdev, speech-dispatcher, sox
|
||||
|
||||
|
||||
## Features, Drivers, Extras, Dependencies
|
||||
|
||||
### Input Drivers:
|
||||
1. "evdevDriver" input driver for linux evdev
|
||||
- python-evdev >=0.6.3 (This is commonly referred to as python3-evdev by your distribution)
|
||||
- python-pyudev
|
||||
- loaded uinput kernel module
|
||||
- ReadWrite permission
|
||||
- /dev/input
|
||||
- /dev/uinput
|
||||
2. "ptyDriver" terminal emulation input driver
|
||||
- python-pyte
|
||||
1. **evdevDriver** - Linux evdev input driver (recommended for Linux)
|
||||
- python-evdev >=0.6.3 (This is commonly referred to as python3-evdev by your distribution)
|
||||
- python-pyudev
|
||||
- loaded uinput kernel module
|
||||
- ReadWrite permission:
|
||||
- /dev/input
|
||||
- /dev/uinput
|
||||
2. **ptyDriver** - Terminal emulation input driver (cross-platform)
|
||||
- python-pyte
|
||||
3. **atspiDriver** - AT-SPI input driver for desktop environments
|
||||
- python-pyatspi2
|
||||
|
||||
### Remote Drivers:
|
||||
1. **unixDriver** - Unix socket remote control (default)
|
||||
- socat (for command-line interaction)
|
||||
2. **tcpDriver** - TCP socket remote control (localhost only)
|
||||
- netcat or telnet (for command-line interaction)
|
||||
|
||||
|
||||
### Screen Drivers:
|
||||
|
||||
1. "vcsaDriver" screen driver for linux VCSA devices
|
||||
- python-dbus
|
||||
- Read permission to the following files and services:
|
||||
- /sys/devices/virtual/tty/tty0/active
|
||||
- /dev/tty[1-64]
|
||||
- /dev/vcsa[1-64]
|
||||
- read logind DBUS
|
||||
2. "ptyDriver" terminal emulation driver
|
||||
- python-pyte
|
||||
1. **vcsaDriver** - Linux VCSA devices driver (recommended for Linux TTY)
|
||||
- python-dbus
|
||||
- Read permission to the following files and services:
|
||||
- /sys/devices/virtual/tty/tty0/active
|
||||
- /dev/tty[1-64]
|
||||
- /dev/vcsa[1-64]
|
||||
- read logind DBUS
|
||||
2. **ptyDriver** - Terminal emulation driver (cross-platform)
|
||||
- python-pyte
|
||||
|
||||
|
||||
### Speech Drivers:
|
||||
|
||||
1. "genericDriver" (default) speech driver for sound as subprocess:
|
||||
- espeak or espeak-ng
|
||||
2. "speechdDriver" speech driver for Speech-dispatcher:
|
||||
- Speech-dispatcher
|
||||
- python-speechd
|
||||
3. "emacspeakDriver" speech driver for emacspeak
|
||||
- emacspeak
|
||||
1. **speechdDriver** - Speech-dispatcher driver (recommended)
|
||||
- Speech-dispatcher
|
||||
- python-speechd
|
||||
2. **genericDriver** - Generic subprocess speech driver
|
||||
- espeak or espeak-ng (or any TTS command)
|
||||
3. **debugDriver** - Debug speech driver for testing
|
||||
- No dependencies
|
||||
|
||||
|
||||
### Sound Drivers:
|
||||
|
||||
1. "genericDriver" (default) sound driver for sound as subprocess:
|
||||
- Sox
|
||||
2. "gstreamerDriver" sound driver for gstreamer
|
||||
- gstreamer >=1.0
|
||||
- GLib
|
||||
1. **genericDriver** (default) - Generic subprocess sound driver
|
||||
- Sox with opus support (recommended)
|
||||
2. **gstreamerDriver** - GStreamer sound driver
|
||||
- gstreamer >=1.0
|
||||
- GLib
|
||||
3. **debugDriver** - Debug sound driver for testing
|
||||
- No dependencies
|
||||
|
||||
|
||||
## Extras:
|
||||
@@ -91,48 +121,635 @@ If there is a package for your distrobution of choice, please let us know so we
|
||||
- You can also just run it from Git without installing:
|
||||
Requires root privileges
|
||||
|
||||
cd src/fenrir/
|
||||
cd src/
|
||||
sudo ./fenrir
|
||||
|
||||
Settings "settings.conf" is located in the "config" directory or after installation in /etc/fenrir/settings.
|
||||
Take care to use drivers from the config matching your installed drivers.
|
||||
By default it uses:
|
||||
- sound driver: genericDriver (via sox, could configured in settings.conf)
|
||||
- speech driver: genericDriver (via espeak or espeak-ng, could configured in settings.conf)
|
||||
- input driver: evdevDriver
|
||||
Settings are located in:
|
||||
- **After installation**: `/etc/fenrir/settings/settings.conf`
|
||||
- **Development**: `config/settings/settings.conf`
|
||||
|
||||
By default Fenrir uses:
|
||||
- **Sound driver**: genericDriver (via sox)
|
||||
- **Speech driver**: speechdDriver (via speech-dispatcher)
|
||||
- **Input driver**: evdevDriver (Linux) or ptyDriver (other platforms)
|
||||
- **Screen driver**: vcsaDriver (Linux TTY) or ptyDriver (terminal emulation)
|
||||
|
||||
## Configure pulseaudio
|
||||
## Audio Configuration
|
||||
|
||||
Pulseaudio by default only plays sound for the user its currently running for. As fenrir is running as root, your local user does not hear the sound and speech produced by fenrir.
|
||||
for this fenrir provides a script to configure pulseaudio to stream the sound played as root to your local user. This is not a issue of fenrir but this is how pulseaudio works.
|
||||
Both PulseAudio and PipeWire require special configuration to allow console applications running as root (like Fenrir) to route audio to your regular user session. This is normal audio system behavior, not a Fenrir issue.
|
||||
|
||||
just run the configuration script twice (once as user, once as root):
|
||||
### Quick Setup - Direct Script Download
|
||||
|
||||
/usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
For non-Fenrir users or quick setup, download and run these scripts directly:
|
||||
|
||||
The script is also located in the tools directory in git
|
||||
#### PulseAudio Configuration
|
||||
```bash
|
||||
# Download the script
|
||||
wget https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pulse.sh
|
||||
chmod +x configure_pulse.sh
|
||||
|
||||
# Run twice: once as user, once as root
|
||||
./configure_pulse.sh
|
||||
sudo ./configure_pulse.sh
|
||||
```
|
||||
|
||||
## Configure pipewire
|
||||
#### PipeWire Configuration
|
||||
```bash
|
||||
# Download the script
|
||||
wget https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pipewire.sh
|
||||
chmod +x configure_pipewire.sh
|
||||
|
||||
Pipewire by default only plays sound for the user its currently running for. As fenrir is running as root, your local user does not hear the sound and speech produced by fenrir.
|
||||
for this fenrir provides a script to configure pipewire to stream the sound played as root to your local user. This is not a issue of fenrir but this is how pipewire works.
|
||||
# Run twice: once as user, once as root
|
||||
./configure_pipewire.sh
|
||||
sudo ./configure_pipewire.sh
|
||||
```
|
||||
|
||||
just run the configuration script twice (once as user, once as root):
|
||||
**Direct links:**
|
||||
- [configure_pulse.sh](https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pulse.sh)
|
||||
- [configure_pipewire.sh](https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pipewire.sh)
|
||||
|
||||
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
### Using Installed Scripts
|
||||
|
||||
The script is also located in the tools directory in git
|
||||
If you have Fenrir installed, the scripts are available at:
|
||||
|
||||
## localization
|
||||
copy fenrir.mo translations file from fenrir/locale/your_language/LC_MESSAGES/fenrir.mo to /usr/share/locale/your_language/LC_MESSAGES/fenrir.mo
|
||||
**PulseAudio:**
|
||||
```bash
|
||||
/usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
```
|
||||
|
||||
**PipeWire:**
|
||||
```bash
|
||||
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
```
|
||||
|
||||
**Note:** These scripts work for any console application that needs root audio access, not just Fenrir.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Basic Usage
|
||||
|
||||
1. **Start Fenrir**:
|
||||
```bash
|
||||
sudo systemctl start fenrir # If installed as service
|
||||
# OR
|
||||
sudo fenrir # Run directly
|
||||
```
|
||||
|
||||
2. **Basic Navigation**:
|
||||
- **Fenrir Key**: By default `Insert`, `Keypad Insert`, or `Meta/Super` key
|
||||
- **Tutorial Mode**: `Fenrir + H` to learn all commands interactively
|
||||
- **Quit Fenrir**: `Fenrir + Q`
|
||||
|
||||
3. **Essential Commands**:
|
||||
- `Ctrl` - Stop speech (shut up)
|
||||
- `Fenrir + Keypad 5` - Read current screen
|
||||
- `Keypad 8` - Read current line
|
||||
- `Keypad 5` - Read current word
|
||||
- `Keypad 2` - Read current character
|
||||
- `Fenrir + T` - Announce time
|
||||
- `Fenrir + S` - Spell check current word
|
||||
- `Fenrir + Keypad *` - Toggle table mode / highlight tracking
|
||||
|
||||
### Keyboard Layouts
|
||||
|
||||
Fenrir supports two main keyboard layouts:
|
||||
|
||||
- **Desktop Layout**: Uses numeric keypad for navigation (recommended for desktop users)
|
||||
- **Laptop Layout**: Alternative bindings for keyboards without numeric keypad
|
||||
|
||||
Configure in `/etc/fenrir/settings/settings.conf`:
|
||||
```ini
|
||||
[keyboard]
|
||||
keyboard_layout=desktop # or 'laptop'
|
||||
```
|
||||
|
||||
### First Time Setup
|
||||
|
||||
1. **Enable Fenrir at boot**:
|
||||
```bash
|
||||
sudo systemctl enable fenrir
|
||||
```
|
||||
|
||||
2. **Configure audio** (if needed):
|
||||
- For PulseAudio: Run configure_pulse.sh script (see below)
|
||||
- For PipeWire: Run configure_pipewire.sh script (see below)
|
||||
|
||||
3. **Test speech**:
|
||||
```bash
|
||||
# Test speech-dispatcher directly
|
||||
sudo spd-say "Hello World"
|
||||
```
|
||||
|
||||
## Remote Control
|
||||
|
||||
Fenrir includes a powerful remote control system that allows external applications and scripts to control Fenrir through Unix sockets or TCP connections. This is particularly useful for automation, integration with other applications, or providing alternative control methods.
|
||||
|
||||
### Configuration
|
||||
|
||||
Enable remote control in `/etc/fenrir/settings/settings.conf`:
|
||||
|
||||
```ini
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver # or tcpDriver
|
||||
port=22447 # for TCP driver
|
||||
socket_file= # custom socket path (optional)
|
||||
enable_settings_remote=True # allow settings changes
|
||||
enable_command_remote=True # allow command execution
|
||||
```
|
||||
|
||||
### Remote Drivers
|
||||
|
||||
1. **unixDriver** (recommended): Uses Unix domain sockets
|
||||
- Socket location: `/tmp/fenrirscreenreader-deamon.sock` (TTY mode) or `/tmp/fenrirscreenreader-<pid>.sock`
|
||||
- More secure, local-only access
|
||||
- Works with `socat`
|
||||
|
||||
2. **tcpDriver**: Uses TCP sockets on localhost
|
||||
- Default port: 22447
|
||||
- Works with `netcat`, `telnet`, or any TCP client
|
||||
- Local connections only (127.0.0.1)
|
||||
|
||||
### Using socat with Unix Sockets
|
||||
|
||||
The `socat` command provides the easiest way to send commands to Fenrir:
|
||||
|
||||
#### Basic Speech Control
|
||||
```bash
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Temporarily disable speech (until next keystroke)
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
#### Settings Control
|
||||
```bash
|
||||
# Enable highlight tracking mode
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Change speech parameters
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#pitch=0.6" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#volume=0.9" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuation_level=none" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Voice and TTS engine control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#module=espeak-ng" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Disable sound temporarily
|
||||
echo "setting set sound#enabled=False" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set sound#volume=0.5" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Keyboard and input settings
|
||||
echo "setting set keyboard#char_echo_mode=1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set keyboard#word_echo=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Screen control (ignore specific TTYs)
|
||||
echo "setting set screen#ignore_screen=1,2,3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Reset all settings to defaults
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Save current settings
|
||||
echo "setting save" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting saveas /tmp/my-fenrir-settings.conf" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
#### Clipboard Operations
|
||||
```bash
|
||||
# Place text into clipboard
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
#### Window Management
|
||||
```bash
|
||||
# Define a window area (x1 y1 x2 y2)
|
||||
echo "command window 0 0 80 24" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Reset window to full screen
|
||||
echo "command resetwindow" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
#### VMenu Control
|
||||
```bash
|
||||
# Set virtual menu context
|
||||
echo "command vmenu nano/file" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Reset virtual menu
|
||||
echo "command resetvmenu" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
#### Application Control
|
||||
```bash
|
||||
# Quit Fenrir
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
```
|
||||
|
||||
### Using TCP Driver
|
||||
|
||||
If using the TCP driver, replace socat commands with netcat:
|
||||
|
||||
```bash
|
||||
# Using netcat
|
||||
echo "command say Hello from TCP" | nc localhost 22447
|
||||
|
||||
# Using telnet
|
||||
echo "command interrupt" | telnet localhost 22447
|
||||
```
|
||||
|
||||
### Remote Command Reference
|
||||
|
||||
#### Command Format
|
||||
```
|
||||
command <action> [parameters]
|
||||
setting <action> [parameters]
|
||||
```
|
||||
|
||||
#### Available Commands
|
||||
|
||||
**Speech Commands:**
|
||||
- `command say <text>` - Speak the specified text
|
||||
- `command interrupt` - Stop current speech
|
||||
- `command tempdisablespeech` - Disable speech until next key press
|
||||
|
||||
**Clipboard Commands:**
|
||||
- `command clipboard <text>` - Add text to clipboard
|
||||
- `command exportclipboard` - Export clipboard to file
|
||||
|
||||
**Window Commands:**
|
||||
- `command window <x1> <y1> <x2> <y2>` - Define window area
|
||||
- `command resetwindow` - Reset to full screen
|
||||
|
||||
**VMenu Commands:**
|
||||
- `command vmenu <menu_path>` - Set vmenu context
|
||||
- `command resetvmenu` - Reset vmenu
|
||||
|
||||
**Application Commands:**
|
||||
- `command quitapplication` - Quit Fenrir
|
||||
|
||||
#### Available Settings
|
||||
|
||||
**Settings Commands:**
|
||||
- `setting set <section>#<key>=<value>` - Set configuration value
|
||||
- `setting reset` - Reset all settings to defaults
|
||||
- `setting save [path]` - Save current settings
|
||||
- `setting saveas <path>` - Save settings to specific file
|
||||
|
||||
**Common Settings:**
|
||||
|
||||
*Speech Settings:*
|
||||
- `speech#enabled=True/False` - Enable/disable speech
|
||||
- `speech#rate=0.1-1.0` - Speech rate (speed)
|
||||
- `speech#pitch=0.1-1.0` - Speech pitch (tone)
|
||||
- `speech#volume=0.1-1.0` - Speech volume
|
||||
- `speech#voice=voice_name` - Voice selection (e.g., "en-us+f3")
|
||||
- `speech#module=module_name` - TTS module (e.g., "espeak-ng")
|
||||
- `speech#driver=driver_name` - Speech driver (speechdDriver/genericDriver)
|
||||
- `speech#auto_read_incoming=True/False` - Auto-read new text
|
||||
|
||||
*Sound Settings:*
|
||||
- `sound#enabled=True/False` - Enable/disable sound
|
||||
- `sound#volume=0.1-1.0` - Sound volume
|
||||
- `sound#driver=driver_name` - Sound driver (genericDriver/gstreamerDriver)
|
||||
- `sound#theme=theme_name` - Sound theme
|
||||
|
||||
*General Settings:*
|
||||
- `general#punctuation_level=none/some/most/all` - Punctuation verbosity
|
||||
- `general#debug_level=0-3` - Debug level
|
||||
- `general#emoticons=True/False` - Enable emoticon replacement
|
||||
- `general#auto_spell_check=True/False` - Automatic spell checking
|
||||
|
||||
*Focus Settings:*
|
||||
- `focus#cursor=True/False` - Follow text cursor
|
||||
- `focus#highlight=True/False` - Follow text highlighting
|
||||
|
||||
*Keyboard Settings:*
|
||||
- `keyboard#char_echo_mode=0-2` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
- `keyboard#word_echo=True/False` - Echo complete words
|
||||
- `keyboard#char_delete_echo=True/False` - Echo deleted characters
|
||||
- `keyboard#interrupt_on_key_press=True/False` - Interrupt speech on key press
|
||||
|
||||
*Screen Settings:*
|
||||
- `screen#ignore_screen=1,2,3` - TTY screens to ignore
|
||||
- `screen#autodetect_ignore_screen=True/False` - Auto-detect screens to ignore
|
||||
- `screen#screen_update_delay=float` - Screen update delay
|
||||
|
||||
*Time Settings:*
|
||||
- `time#enabled=True/False` - Enable time announcements
|
||||
- `time#present_time=True/False` - Announce time
|
||||
- `time#present_date=True/False` - Announce date changes
|
||||
- `time#delay_sec=seconds` - Announcement interval
|
||||
- `time#on_minutes=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 `progress_monitoring=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
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# notify_fenrir.sh - Send notifications to Fenrir
|
||||
|
||||
SOCKET="/tmp/fenrirscreenreader-deamon.sock"
|
||||
|
||||
fenrir_say() {
|
||||
echo "command say $1" | socat - UNIX-CLIENT:$SOCKET
|
||||
}
|
||||
|
||||
fenrir_interrupt() {
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:$SOCKET
|
||||
}
|
||||
|
||||
# Usage examples
|
||||
fenrir_say "Build completed successfully"
|
||||
fenrir_interrupt
|
||||
```
|
||||
|
||||
#### Python Integration
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import socket
|
||||
import os
|
||||
|
||||
def send_fenrir_command(command):
|
||||
"""Send command to Fenrir via Unix socket"""
|
||||
socket_path = "/tmp/fenrirscreenreader-deamon.sock"
|
||||
if os.path.exists(socket_path):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
try:
|
||||
sock.connect(socket_path)
|
||||
sock.send(command.encode('utf-8'))
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
# Examples
|
||||
send_fenrir_command("command say Processing complete")
|
||||
send_fenrir_command("setting set speech#rate=0.9")
|
||||
```
|
||||
|
||||
### Security Considerations
|
||||
|
||||
- Unix sockets are accessible only to the user running Fenrir
|
||||
- TCP driver binds only to localhost (127.0.0.1)
|
||||
- Socket file permissions are set to write-only (0o222)
|
||||
- Commands are processed with Fenrir's privileges
|
||||
- Settings changes can be disabled via `enable_settings_remote=False`
|
||||
- Command execution can be disabled via `enable_command_remote=False`
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**Socket not found:**
|
||||
- Verify Fenrir is running: `ps aux | grep fenrir`
|
||||
- Check socket location: `/tmp/fenrirscreenreader-*`
|
||||
- Ensure remote driver is enabled in settings
|
||||
|
||||
**Commands not working:**
|
||||
- Verify `enable_command_remote=True` in settings
|
||||
- Check Fenrir debug logs: `/var/log/fenrir.log`
|
||||
- Test with simple command: `echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock`
|
||||
|
||||
## Command Line Options
|
||||
|
||||
Fenrir supports several command-line options for different use cases:
|
||||
|
||||
```
|
||||
fenrir [OPTIONS]
|
||||
```
|
||||
|
||||
### Options:
|
||||
- `-h, --help` - Show help message and exit
|
||||
- `-v, --version` - Show version information and exit
|
||||
- `-f, --foreground` - Run in foreground (don't daemonize)
|
||||
- `-s, --setting SETTING-FILE` - Path to custom settings file
|
||||
- `-o, --options SECTION#SETTING=VALUE;..` - Override settings file options
|
||||
- `-d, --debug` - Enable debug mode
|
||||
- `-p, --print` - Print debug messages to screen
|
||||
- `-e, --emulated-pty` - Use PTY emulation with escape sequences for input (enables desktop/X/Wayland usage)
|
||||
- `-E, --emulated-evdev` - Use PTY emulation with evdev for input (single instance)
|
||||
- `-F, --force-all-screens` - Force Fenrir to respond on all screens, ignoring ignore_screen setting
|
||||
- `-i, -I, --ignore-screen SCREEN` - Ignore specific screen(s). Can be used multiple times. Combines with existing ignore settings.
|
||||
|
||||
### Examples:
|
||||
```bash
|
||||
# Run in foreground with debug output
|
||||
sudo fenrir -f -d
|
||||
|
||||
# Use PTY emulation for desktop use
|
||||
sudo fenrir -e
|
||||
|
||||
# Override settings via command line
|
||||
sudo fenrir -o "speech#rate=0.8;sound#volume=0.5"
|
||||
|
||||
# Force Fenrir to work on all screens (ignore ignore_screen setting)
|
||||
sudo fenrir -F
|
||||
|
||||
# Ignore specific screens
|
||||
sudo fenrir --ignore-screen 1
|
||||
sudo fenrir -i 1 -i 2 # Ignore screens 1 and 2
|
||||
```
|
||||
|
||||
## Localization
|
||||
Translation files are located in the `locale/` directory. To install translations:
|
||||
|
||||
```bash
|
||||
# Copy translation file to system location
|
||||
sudo cp locale/your_language/LC_MESSAGES/fenrir.mo /usr/share/locale/your_language/LC_MESSAGES/fenrir.mo
|
||||
```
|
||||
|
||||
Available languages:
|
||||
- German (de)
|
||||
- Spanish (es)
|
||||
- Polish (pl)
|
||||
- Portuguese (pt)
|
||||
- Russian (ru)
|
||||
|
||||
|
||||
## Documentation and Support
|
||||
|
||||
- Email list: [stormux+subscribe@groups.io](mailto:stormux+subscribe@groups.io?subject=subscribe) with the subject subscribe.
|
||||
- [Fenrir Wiki](https://git.stormux.org/storm/fenrir/wiki)
|
||||
- IRC: irc.stormux.org #stormux
|
||||
- **Email list**: [stormux+subscribe@groups.io](mailto:stormux+subscribe@groups.io?subject=subscribe) with the subject subscribe
|
||||
- **Fenrir Wiki**: [https://git.stormux.org/storm/fenrir/wiki](https://git.stormux.org/storm/fenrir/wiki)
|
||||
- **IRC**: irc.stormux.org #stormux
|
||||
- **Issues**: Report bugs and feature requests on the project repository
|
||||
|
||||
192
RELEASE_CHECKLIST.md
Normal file
192
RELEASE_CHECKLIST.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Fenrir Release Validation Checklist
|
||||
|
||||
This checklist ensures thorough validation before releasing Fenrir packages.
|
||||
|
||||
## 🔧 Setup Tools (One-time setup)
|
||||
|
||||
### Install Pre-commit Hook
|
||||
```bash
|
||||
# Safely install composite hook (preserves existing version management)
|
||||
./tools/install_validation_hook.sh
|
||||
|
||||
# Test the hook
|
||||
./.git/hooks/pre-commit
|
||||
```
|
||||
|
||||
### Validation Scripts
|
||||
- `tools/validate_syntax.py` - Python syntax validation
|
||||
- `tools/validate_pep8.py` - PEP8 compliance checking with safe auto-fix
|
||||
- `tools/validate_release.py` - Comprehensive release validation
|
||||
- `tools/cleanup_cache.py` - Remove Python cache files and directories
|
||||
- `tools/pre-commit-hook` - Git pre-commit validation
|
||||
|
||||
## 📋 Pre-Release Checklist
|
||||
|
||||
### 1. Code Quality Validation ✅
|
||||
```bash
|
||||
# Comprehensive release validation (includes syntax, imports, structure)
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# If issues found, try auto-fix
|
||||
python3 tools/validate_release.py --fix
|
||||
|
||||
# Quick validation (skips slow dependency checks)
|
||||
python3 tools/validate_release.py --quick
|
||||
```
|
||||
|
||||
**Expected Result**: All tests pass, no syntax errors
|
||||
|
||||
### 2. Dependency Validation ✅
|
||||
```bash
|
||||
# Validate all dependencies are available
|
||||
python3 check-dependencies.py
|
||||
```
|
||||
|
||||
**Expected Result**: All required dependencies reported as available
|
||||
|
||||
### 3. Core Functionality Test ✅
|
||||
```bash
|
||||
# Test core imports (safe to run without sudo)
|
||||
cd src
|
||||
python3 -c "
|
||||
import fenrirscreenreader.core.fenrirManager
|
||||
import fenrirscreenreader.core.commandManager
|
||||
import fenrirscreenreader.core.eventManager
|
||||
print('Core imports successful')
|
||||
"
|
||||
cd ..
|
||||
```
|
||||
|
||||
**Expected Result**: No import errors
|
||||
|
||||
### 4. Installation Script Validation ✅
|
||||
```bash
|
||||
# Validate setup.py syntax
|
||||
python3 -m py_compile setup.py
|
||||
|
||||
# Check setup.py can be parsed
|
||||
python3 setup.py --help-commands >/dev/null
|
||||
```
|
||||
|
||||
**Expected Result**: No syntax errors, setup.py functional
|
||||
|
||||
### 5. Configuration Validation ✅
|
||||
```bash
|
||||
# Verify config files exist and are parseable
|
||||
ls -la config/settings/settings.conf
|
||||
ls -la config/keyboard/desktop.conf
|
||||
ls -la config/punctuation/default.conf
|
||||
```
|
||||
|
||||
**Expected Result**: All core config files present
|
||||
|
||||
### 6. Manual Testing (User/Package Maintainer) ⚠️
|
||||
|
||||
**Important**: These require user interaction as they need sudo access or specific hardware.
|
||||
|
||||
```bash
|
||||
# Test basic functionality (ask user to run)
|
||||
sudo ./src/fenrir --help
|
||||
|
||||
# Test in emulation mode (safer for desktop environments)
|
||||
sudo ./src/fenrir -e --version
|
||||
|
||||
# Quick functionality test (3-5 seconds)
|
||||
sudo timeout 5 ./src/fenrir -e -f || echo "Timeout reached (expected)"
|
||||
```
|
||||
|
||||
**Expected Result**: No immediate crashes, basic help/version output works
|
||||
|
||||
### 7. Package-Specific Validation ✅
|
||||
```bash
|
||||
# Test the same compilation process used by package managers
|
||||
python3 -m compileall src/fenrirscreenreader/ -q
|
||||
|
||||
# Verify no __pycache__ permission issues
|
||||
find src/ -name "*.pyc" -delete
|
||||
find src/ -name "__pycache__" -delete
|
||||
```
|
||||
|
||||
**Expected Result**: Clean compilation, no permission errors
|
||||
|
||||
## 🚨 Known Issue Categories
|
||||
|
||||
### Critical Issues (Block Release)
|
||||
- **Python syntax errors** (SyntaxError, unterminated strings)
|
||||
- **Missing core dependencies** (dbus-python, evdev, etc.)
|
||||
- **Import failures in core modules** (fenrirManager, commandManager)
|
||||
- **Missing critical config files** (settings.conf, desktop.conf)
|
||||
|
||||
### Warning Issues (Address if Possible)
|
||||
- **PEP8 violations** (cosmetic, don't block release)
|
||||
- **Missing optional dependencies** (for specific features)
|
||||
- **Command structure issues** (missing methods in command files)
|
||||
- **Very long lines** (>120 characters)
|
||||
|
||||
## 🔍 Root Cause Analysis
|
||||
|
||||
### Why These Errors Weren't Caught Previously
|
||||
|
||||
1. **No automated syntax validation** - The codebase relied on manual testing
|
||||
2. **No pre-commit hooks** - Syntax errors could be committed
|
||||
3. **No CI/CD pipeline** - Package compilation happens only during release
|
||||
4. **Manual PEP8 cleanup** - F-string refactoring introduced syntax errors during batch cleanup
|
||||
|
||||
## 📖 Usage Instructions
|
||||
|
||||
### For Developers
|
||||
```bash
|
||||
# Before committing changes
|
||||
git add .
|
||||
git commit # Pre-commit hook will run automatically
|
||||
|
||||
# Before creating tags/releases
|
||||
python3 tools/validate_release.py
|
||||
```
|
||||
|
||||
### For Package Maintainers
|
||||
```bash
|
||||
# Before packaging
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# If validation fails
|
||||
python3 tools/validate_release.py --fix
|
||||
|
||||
# Quick check (if dependencies are known good)
|
||||
python3 tools/validate_release.py --quick
|
||||
```
|
||||
|
||||
### For Release Managers
|
||||
```bash
|
||||
# Complete validation before tagging
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# Manual verification (requires sudo)
|
||||
sudo ./src/fenrir --version
|
||||
|
||||
# Tag release only after all validations pass
|
||||
git tag -a v2.x.x -m "Release v2.x.x"
|
||||
```
|
||||
|
||||
## 🎯 Future Improvements
|
||||
|
||||
### Recommended Additions
|
||||
1. **GitHub Actions CI/CD** - Automated validation on every push
|
||||
2. **Automated testing** - Unit tests for core functionality
|
||||
3. **Integration testing** - Test driver interactions
|
||||
4. **Package testing** - Validate actual package installation
|
||||
|
||||
### Modern Python Packaging
|
||||
- Consider migrating to `pyproject.toml` (PEP 621)
|
||||
- Use `build` instead of `setup.py` directly
|
||||
- Add `tox.ini` for multi-environment testing
|
||||
|
||||
## 📞 Support
|
||||
|
||||
If validation fails and auto-fix doesn't resolve issues:
|
||||
|
||||
1. **Check the specific error messages** in validation output
|
||||
2. **Review recent commits** that might have introduced issues
|
||||
3. **Run individual validation steps** to isolate problems
|
||||
|
||||
Remember: **Working code is better than perfect code** - especially for accessibility software where reliability is critical.
|
||||
@@ -4,12 +4,10 @@ Wants=systemd-udev-settle.service
|
||||
After=systemd-udev-settle.service getty.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
PIDFile=/run/fenrir.pid
|
||||
ExecStart=/usr/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
#Group=fenrirscreenreader
|
||||
#User=fenrirscreenreader
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
||||
|
||||
@@ -4,7 +4,7 @@ Wants=systemd-udev-settle.service
|
||||
After=systemd-udev-settle.service sound.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
PIDFile=/run/fenrir.pid
|
||||
ExecStart=/usr/local/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
|
||||
4
bugs
4
bugs
@@ -1,5 +1,5 @@
|
||||
Please report Bugs and feature requests to:
|
||||
https://github.com/chrys87/fenrir/issues
|
||||
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:
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -73,7 +73,8 @@ KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_KPSLASH=set_window_application
|
||||
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
|
||||
KEY_KPPLUS=last_incoming
|
||||
KEY_KPPLUS=progress_bar_monitor
|
||||
#KEY_FENRIR,KEY_KPPLUS=silence_until_prompt
|
||||
KEY_FENRIR,KEY_F2=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
@@ -82,6 +83,7 @@ KEY_FENRIR,KEY_CTRL,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_E=cycle_key_echo
|
||||
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||
@@ -113,6 +115,8 @@ KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_X=set_mark
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_X=marked_text
|
||||
KEY_FENRIR,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_F10=voice_browser_safe
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_F10=apply_tested_voice
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_RIGHT=next_quick_menu_entry
|
||||
@@ -123,6 +127,8 @@ KEY_FENRIR,KEY_CTRL,KEY_S=save_settings
|
||||
# linux specific
|
||||
KEY_FENRIR,KEY_F7=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume
|
||||
# Read-all functionality
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout
|
||||
|
||||
@@ -75,11 +75,13 @@ KEY_FENRIR,KEY_F2=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_FENRIR,KEY_ENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_P=progress_bar_monitor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_ENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_E=cycle_key_echo
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
|
||||
#=toggle_barrier
|
||||
@@ -111,6 +113,8 @@ KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_X=set_mark
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_X=marked_text
|
||||
KEY_FENRIR,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_F10=voice_browser_safe
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_F10=apply_tested_voice
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_RIGHT=next_quick_menu_entry
|
||||
@@ -123,6 +127,8 @@ KEY_FENRIR,KEY_CTRL,KEY_S=save_settings
|
||||
# linux specific
|
||||
KEY_FENRIR,KEY_F7=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume
|
||||
# Read-all functionality
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
KEY_FENRIR,KEY_F1=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_CTRL=shut_up
|
||||
KEY_SHIFT,KEY_KP9=review_bottom
|
||||
KEY_SHIFT,KEY_KP7=review_top
|
||||
KEY_KP8=review_curr_line
|
||||
KEY_KP7=review_prev_line
|
||||
KEY_KP9=review_next_line
|
||||
KEY_SHIFT,KEY_KP1=review_line_begin
|
||||
KEY_SHIFT,KEY_KP3=review_line_end
|
||||
KEY_FENRIR,KEY_KP1=review_line_first_char
|
||||
KEY_FENRIR,KEY_KP3=review_line_last_char
|
||||
KEY_FENRIR,KEY_ALT,KEY_1=present_first_line
|
||||
KEY_FENRIR,KEY_ALT,KEY_2=present_last_line
|
||||
KEY_KP5=review_curr_word
|
||||
KEY_KP4=review_prev_word
|
||||
KEY_KP6=review_next_word
|
||||
2,KEY_KP5=review_curr_word_phonetic
|
||||
2,KEY_KP4=review_prev_word_phonetic
|
||||
2,KEY_KP6=review_next_word_phonetic
|
||||
KEY_KP2=review_curr_char
|
||||
KEY_KP1=review_prev_char
|
||||
KEY_KP3=review_next_char
|
||||
2,KEY_KP2=review_curr_char_phonetic
|
||||
2,KEY_KP1=review_prev_char_phonetic
|
||||
2,KEY_KP3=review_next_char_phonetic
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP8=review_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP2=review_down
|
||||
KEY_FENRIR,KEY_KPDOT=exit_review
|
||||
KEY_KPDOT=cursor_position
|
||||
KEY_FENRIR,KEY_I=indent_curr_line
|
||||
KEY_FENRIR,KEY_B=curr_screen
|
||||
KEY_FENRIR,KEY_KP8=curr_screen_before_cursor
|
||||
KEY_FENRIR,KEY_KP2=curr_screen_after_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_PAGEDOWN=cursor_read_to_end_of_line
|
||||
#=cursor_column
|
||||
#=cursor_lineno
|
||||
#=braille_flush
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=braille_return_to_cursor
|
||||
#=braille_pan_left
|
||||
#=braille_pan_right
|
||||
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
|
||||
KEY_FENRIR,KEY_1=bookmark_1
|
||||
KEY_FENRIR,KEY_K=bookmark_1
|
||||
KEY_FENRIR,KEY_CTRL,KEY_2=clear_bookmark_2
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_2=set_bookmark_2
|
||||
KEY_FENRIR,KEY_2=bookmark_2
|
||||
KEY_FENRIR,KEY_CTRL,KEY_3=clear_bookmark_3
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_3=set_bookmark_3
|
||||
KEY_FENRIR,KEY_3=bookmark_3
|
||||
KEY_FENRIR,KEY_CTRL,KEY_4=clear_bookmark_4
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_4=set_bookmark_4
|
||||
KEY_FENRIR,KEY_4=bookmark_4
|
||||
KEY_FENRIR,KEY_CTRL,KEY_5=clear_bookmark_5
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_5=set_bookmark_5
|
||||
KEY_FENRIR,KEY_5=bookmark_5
|
||||
KEY_FENRIR,KEY_CTRL,KEY_6=clear_bookmark_6
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_6=set_bookmark_6
|
||||
KEY_FENRIR,KEY_6=bookmark_6
|
||||
KEY_FENRIR,KEY_CTRL,KEY_7=clear_bookmark_7
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_7=set_bookmark_7
|
||||
KEY_FENRIR,KEY_7=bookmark_7
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=clear_bookmark_8
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_8=set_bookmark_8
|
||||
KEY_FENRIR,KEY_8=bookmark_8
|
||||
KEY_FENRIR,KEY_CTRL,KEY_9=clear_bookmark_9
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_9=set_bookmark_9
|
||||
KEY_FENRIR,KEY_9=bookmark_9
|
||||
KEY_FENRIR,KEY_CTRL,KEY_0=clear_bookmark_10
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_KPSLASH=set_window_application
|
||||
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
|
||||
KEY_KPPLUS=last_incoming
|
||||
#=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_KPENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_S=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||
key_FENRIR,KEY_5=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||
KEY_FENRIR,KEY_KPMINUS=toggle_barrier
|
||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||
KEY_FENRIR,KEY_T=time
|
||||
KEY_FENRIR,KEY_F12=time
|
||||
2,KEY_FENRIR,KEY_T=date
|
||||
2,KEY_FENRIR,KEY_F12=date
|
||||
KEY_KPSLASH=toggle_auto_indent
|
||||
KEY_FENRIR,KEY_F=attribute_cursor
|
||||
#=toggle_has_attribute
|
||||
KEY_FENRIR,KEY_F7=spell_check
|
||||
2,KEY_FENRIR,KEY_S=add_word_to_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_S=remove_word_from_spell_check
|
||||
KEY_FENRIR,KEY_F2=forward_keypress
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
|
||||
#=clear_clipboard
|
||||
KEY_FENRIR,KEY_HOME=first_clipboard
|
||||
KEY_FENRIR,KEY_END=last_clipboard
|
||||
KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=copy_last_echo_to_clipboard
|
||||
KEY_FENRIR,KEY_V=paste_clipboard
|
||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_F9=set_mark
|
||||
KEY_FENRIR,KEY_F10=marked_text
|
||||
KEY_FENRIR,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_RIGHT=next_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=next_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_LEFT=prev_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=prev_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_C=save_settings
|
||||
# linux specific
|
||||
#=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_alsa_volume
|
||||
@@ -1,128 +0,0 @@
|
||||
KEY_FENRIR,KEY_F1=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_CTRL=shut_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_END=review_bottom
|
||||
KEY_FENRIR,KEY_CTRL,KEY_HOME=review_top
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_DOT=review_curr_line
|
||||
KEY_FENRIR,KEY_U=review_prev_line
|
||||
KEY_FENRIR,KEY_O=review_next_line
|
||||
KEY_FENRIR,KEY_HOME=review_line_begin
|
||||
KEY_FENRIR,KEY_END=review_line_end
|
||||
KEY_FENRIR,KEY_CTRL,KEY_J=review_line_first_char
|
||||
KEY_FENRIR,KEY_CTRL,KEY_L=review_line_last_char
|
||||
KEY_FENRIR,KEY_ALT,KEY_1=present_first_line
|
||||
KEY_FENRIR,KEY_ALT,KEY_2=present_last_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOT=review_curr_word
|
||||
KEY_FENRIR,KEY_J=review_prev_word
|
||||
KEY_FENRIR,KEY_L=review_next_word
|
||||
2,KEY_FENRIR,KEY_CTRL,KEY_DOT=review_curr_word_phonetic
|
||||
2,KEY_FENRIR,KEY_J=review_prev_word_phonetic
|
||||
2,KEY_FENRIR,KEY_L=review_next_word_phonetic
|
||||
KEY_FENRIR,KEY_COMMA=review_curr_char
|
||||
KEY_FENRIR,KEY_M=review_prev_char
|
||||
KEY_FENRIR,KEY_DOT=review_next_char
|
||||
2,KEY_FENRIR,KEY_COMMA=curr_char_phonetic
|
||||
2,KEY_FENRIR,KEY_M=prev_char_phonetic
|
||||
2,KEY_FENRIR,KEY_DOT=next_char_phonetic
|
||||
KEY_FENRIR,KEY_CTRL,KEY_I=review_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_COMMA=review_down
|
||||
KEY_FENRIR,KEY_SLASH=exit_review
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_DOT=cursor_position
|
||||
2,KEY_FENRIR,KEY_I=indent_curr_line
|
||||
KEY_FENRIR,KEY_B=curr_screen
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_I=curr_screen_before_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_COMMA=curr_screen_after_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_PAGEDOWN=cursor_read_to_end_of_line
|
||||
#=cursor_column
|
||||
#=cursor_lineno
|
||||
#=braille_flush
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=braille_return_to_cursor
|
||||
#=braille_pan_left
|
||||
#=braille_pan_right
|
||||
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
|
||||
KEY_FENRIR,KEY_1=bookmark_1
|
||||
KEY_FENRIR,KEY_K=bookmark_1
|
||||
KEY_FENRIR,KEY_CTRL,KEY_2=clear_bookmark_2
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_2=set_bookmark_2
|
||||
KEY_FENRIR,KEY_2=bookmark_2
|
||||
KEY_FENRIR,KEY_CTRL,KEY_3=clear_bookmark_3
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_3=set_bookmark_3
|
||||
KEY_FENRIR,KEY_3=bookmark_3
|
||||
KEY_FENRIR,KEY_CTRL,KEY_4=clear_bookmark_4
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_4=set_bookmark_4
|
||||
KEY_FENRIR,KEY_4=bookmark_4
|
||||
KEY_FENRIR,KEY_CTRL,KEY_5=clear_bookmark_5
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_5=set_bookmark_5
|
||||
KEY_FENRIR,KEY_5=bookmark_5
|
||||
KEY_FENRIR,KEY_CTRL,KEY_6=clear_bookmark_6
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_6=set_bookmark_6
|
||||
KEY_FENRIR,KEY_6=bookmark_6
|
||||
KEY_FENRIR,KEY_CTRL,KEY_7=clear_bookmark_7
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_7=set_bookmark_7
|
||||
KEY_FENRIR,KEY_7=bookmark_7
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=clear_bookmark_8
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_8=set_bookmark_8
|
||||
KEY_FENRIR,KEY_8=bookmark_8
|
||||
KEY_FENRIR,KEY_CTRL,KEY_9=clear_bookmark_9
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_9=set_bookmark_9
|
||||
KEY_FENRIR,KEY_9=bookmark_9
|
||||
KEY_FENRIR,KEY_CTRL,KEY_0=clear_bookmark_10
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=set_window_application
|
||||
2,KEY_FENRIR,KEY_CTRL,KEY_8=clear_window_application
|
||||
KEY_FENRIR,KEY_SEMICOLON=last_incoming
|
||||
#=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_FENRIR,KEY_ENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_S=toggle_output
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_5=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
|
||||
#=toggle_barrier
|
||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||
KEY_FENRIR,KEY_T=time
|
||||
KEY_FENRIR,KEY_F12=time
|
||||
2,KEY_FENRIR,KEY_T=date
|
||||
2,KEY_FENRIR,KEY_F12=date
|
||||
KEY_FENRIR,KEY_BACKSLASH=toggle_auto_indent
|
||||
KEY_FENRIR,KEY_F=attribute_cursor
|
||||
#=toggle_has_attribute
|
||||
KEY_FENRIR,KEY_F7=spell_check
|
||||
2,KEY_FENRIR,KEY_S=add_word_to_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_S=remove_word_from_spell_check
|
||||
KEY_FENRIR,KEY_F2=forward_keypress
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
|
||||
#=clear_clipboard
|
||||
#=first_clipboard
|
||||
#=last_clipboard
|
||||
KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=copy_last_echo_to_clipboard
|
||||
KEY_FENRIR,KEY_V=paste_clipboard
|
||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_F9=set_mark
|
||||
KEY_FENRIR,KEY_F10=marked_text
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_RIGHT=next_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=next_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_LEFT=prev_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=prev_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_C=save_settings
|
||||
# linux specific
|
||||
#=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_alsa_volume
|
||||
@@ -85,3 +85,5 @@ alt+f12 - quit fenrir
|
||||
^[[1;3F=temp_disable_speech
|
||||
# control+end - toggle auto read
|
||||
^[[1;5F=toggle_auto_read
|
||||
# F12 - cycle keyboard layout
|
||||
^[[24~=cycle_keyboard_layout
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
# Fenrir comment: copy of speakup DefaultKeyAssignments converted to fenrir syntax
|
||||
# Fenrir comment: https://android.googlesource.com/kernel/msm/+/android-7.1.0_r0.2/drivers/staging/speakup/DefaultKeyAssignments
|
||||
# Fenrir comment: The insert or shift key named below is the fenrir key
|
||||
|
||||
# This file is intended to give you an overview of the default keys used
|
||||
# by speakup for it's review functions. You may change them to be
|
||||
# anything you want but that will take some familiarity with key
|
||||
# mapping.
|
||||
|
||||
# We have remapped the insert or zero key on the keypad to act as a
|
||||
# shift key. Well, actually as an altgr key. So in the following list
|
||||
# InsKeyPad-period means hold down the insert key like a shift key and
|
||||
# hit the keypad period.
|
||||
|
||||
# KeyPad-8 Say current Line
|
||||
KEY_KP8=review_curr_line
|
||||
|
||||
# InsKeyPad-8 say from top of screen to reading cursor.
|
||||
KEY_FENRIR,KEY_KP8=curr_screen_before_cursor
|
||||
|
||||
# KeyPad-7 Say Previous Line (UP one line)
|
||||
KEY_KP7=review_prev_line
|
||||
|
||||
# KeyPad-9 Say Next Line (down one line)
|
||||
KEY_KP9=review_next_line
|
||||
|
||||
# KeyPad-5 Say Current Word
|
||||
KEY_KP5=review_curr_word
|
||||
|
||||
# InsKeyPad-5 Spell Current Word
|
||||
KEY_FENRIR,KEY_KP5=review_curr_word_phonetic
|
||||
|
||||
# KeyPad-4 Say Previous Word (left one word)
|
||||
KEY_KP4=review_prev_word
|
||||
|
||||
# InsKeyPad-4 say from left edge of line to reading cursor.
|
||||
KEY_FENRIR,KEY_KP4=cursor_read_line_to_cursor
|
||||
|
||||
# KeyPad-6 Say Next Word (right one word)
|
||||
KEY_KP6=review_next_word
|
||||
|
||||
# InsKeyPad-6 Say from reading cursor to right edge of line.
|
||||
KEY_FENRIR,KEY_KP6=cursor_read_to_end_of_line
|
||||
|
||||
# KeyPad-2 Say Current Letter
|
||||
KEY_KP2=review_curr_char
|
||||
|
||||
# InsKeyPad-2 say current letter phonetically
|
||||
KEY_FENRIR,KEY_KP2=review_curr_char_phonetic
|
||||
|
||||
# KeyPad-1 Say Previous Character (left one letter)
|
||||
KEY_KP1=review_prev_char
|
||||
|
||||
# KeyPad-3 Say Next Character (right one letter)
|
||||
KEY_KP3=review_next_char
|
||||
|
||||
# KeyPad-plus Say Entire Screen
|
||||
KEY_KPPLUS=curr_screen
|
||||
|
||||
# InsKeyPad-plus Say from reading cursor line to bottom of screen.
|
||||
KEY_FENRIR,KEY_KPPLUS=curr_screen_after_cursor
|
||||
|
||||
# KeyPad-Minus Park reading cursor (toggle)
|
||||
# TODO
|
||||
|
||||
# InsKeyPad-minus Say character hex and decimal value.
|
||||
# TODO
|
||||
|
||||
# KeyPad-period Say Position (current line, position and console)
|
||||
KEY_KPDOT=cursor_position
|
||||
|
||||
# InsKeyPad-period say colour attributes of current position.
|
||||
KEY_FENRIR,KEY_KPDOT=attribute_cursor
|
||||
|
||||
# InsKeyPad-9 Move reading cursor to top of screen (insert pgup)
|
||||
KEY_FENRIR,KEY_KP9=review_bottom
|
||||
|
||||
# InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn)
|
||||
KEY_FENRIR,KEY_KP3=review_top
|
||||
|
||||
# InsKeyPad-7 Move reading cursor to left edge of screen (insert home)
|
||||
KEY_FENRIR,KEY_KP7=review_screen_first_char
|
||||
|
||||
# InsKeyPad-1 Move reading cursor to right edge of screen (insert end)
|
||||
KEY_FENRIR,KEY_KP1=review_screen_last_char
|
||||
|
||||
# ControlKeyPad-1 Move reading cursor to last character on current line.
|
||||
KEY_CTRL,KEY_KP1=review_line_end
|
||||
|
||||
# KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor
|
||||
KEY_KPENTER=temp_disable_speech
|
||||
|
||||
# InsKeyPad-Enter Shut Up (until toggled back on).
|
||||
KEY_FENRIR,KEY_KPENTER=toggle_speech
|
||||
|
||||
# InsKeyPad-star n<x|y> go to line (y) or column (x). Where 'n' is any
|
||||
# allowed value for the row or column for your current screen.
|
||||
# TODO
|
||||
|
||||
# KeyPad-/ Mark and Cut screen region.
|
||||
KEY_KPSLASH=copy_marked_to_clipboard
|
||||
|
||||
# InsKeyPad-/ Paste screen region into any console.
|
||||
KEY_FENRIR,KEY_KPSLASH=paste_clipboard
|
||||
|
||||
|
||||
# Hitting any key while speakup is outputting speech will quiet the
|
||||
# synth until it has caught up with what is being printed on the
|
||||
# console.
|
||||
|
||||
# following by other fenrir commands
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_CTRL=shut_up
|
||||
|
||||
|
||||
KEY_FENRIR,KEY_KP4=review_line_begin
|
||||
#=review_line_end
|
||||
#=review_line_first_char
|
||||
#=review_line_last_char
|
||||
KEY_FENRIR,KEY_ALT,KEY_1=present_first_line
|
||||
KEY_FENRIR,KEY_ALT,KEY_2=present_last_line
|
||||
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_KP4=review_prev_word_phonetic
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_KP6=review_next_word_phonetic
|
||||
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_KP1=review_prev_char_phonetic
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_KP3=review_next_char_phonetic
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP8=review_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP2=review_down
|
||||
#=exit_review
|
||||
KEY_FENRIR,KEY_I=indent_curr_line
|
||||
KEY_KPPLUS=curr_screen
|
||||
#=cursor_column
|
||||
#=cursor_lineno
|
||||
#=braille_flush
|
||||
#=braille_return_to_cursor
|
||||
#=braille_pan_left
|
||||
#=braille_pan_right
|
||||
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
|
||||
KEY_FENRIR,KEY_1=bookmark_1
|
||||
KEY_FENRIR,KEY_CTRL,KEY_2=clear_bookmark_2
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_2=set_bookmark_2
|
||||
KEY_FENRIR,KEY_2=bookmark_2
|
||||
KEY_FENRIR,KEY_CTRL,KEY_3=clear_bookmark_3
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_3=set_bookmark_3
|
||||
KEY_FENRIR,KEY_3=bookmark_3
|
||||
KEY_FENRIR,KEY_CTRL,KEY_4=clear_bookmark_4
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_4=set_bookmark_4
|
||||
KEY_FENRIR,KEY_4=bookmark_4
|
||||
KEY_FENRIR,KEY_CTRL,KEY_5=clear_bookmark_5
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_5=set_bookmark_5
|
||||
KEY_FENRIR,KEY_5=bookmark_5
|
||||
KEY_FENRIR,KEY_CTRL,KEY_6=clear_bookmark_6
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_6=set_bookmark_6
|
||||
KEY_FENRIR,KEY_6=bookmark_6
|
||||
KEY_FENRIR,KEY_CTRL,KEY_7=clear_bookmark_7
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_7=set_bookmark_7
|
||||
KEY_FENRIR,KEY_7=bookmark_7
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=clear_bookmark_8
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_8=set_bookmark_8
|
||||
KEY_FENRIR,KEY_8=bookmark_8
|
||||
KEY_FENRIR,KEY_CTRL,KEY_9=clear_bookmark_9
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_9=set_bookmark_9
|
||||
KEY_FENRIR,KEY_9=bookmark_9
|
||||
KEY_FENRIR,KEY_CTRL,KEY_0=clear_bookmark_10
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_KPSLASH=set_window_application
|
||||
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
|
||||
#=last_incoming
|
||||
KEY_FENRIR,KEY_F2=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
|
||||
KEY_FENRIR,KEY_F9=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||
KEY_FENRIR,KEY_KPMINUS=toggle_barrier
|
||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||
KEY_FENRIR,KEY_T=time
|
||||
2,KEY_FENRIR,KEY_T=date
|
||||
KEY_KPSLASH=toggle_auto_indent
|
||||
#=toggle_has_attribute
|
||||
KEY_FENRIR,KEY_S=spell_check
|
||||
2,KEY_FENRIR,KEY_S=add_word_to_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_S=remove_word_from_spell_check
|
||||
KEY_FENRIR,KEY_BACKSPACE=forward_keypress
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=clear_clipboard
|
||||
KEY_FENRIR,KEY_HOME=first_clipboard
|
||||
KEY_FENRIR,KEY_END=last_clipboard
|
||||
KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||
KEY_FENRIR,KEY_CTRL,KEY_C=copy_last_echo_to_clipboard
|
||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_X=set_mark
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_X=marked_text
|
||||
KEY_FENRIR,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_RIGHT=next_quick_menu_entry
|
||||
KEY_FENRIR,KEY_UP=next_quick_menu_value
|
||||
KEY_FENRIR,KEY_LEFT=prev_quick_menu_entry
|
||||
KEY_FENRIR,KEY_DOWN=prev_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_S=save_settings
|
||||
# linux specific
|
||||
KEY_FENRIR,KEY_F7=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume
|
||||
@@ -4,8 +4,8 @@
|
||||
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
|
||||
[levelDict]
|
||||
none:===:
|
||||
some:===:-$~+*-/\@#_
|
||||
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
|
||||
some:===:-$~+*-/\@#
|
||||
most:===:.,:-_$~+*-/\@!#%^&*()[]}{<>;
|
||||
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~
|
||||
|
||||
[punctDict]
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
|
||||
[levelDict]
|
||||
none:===:
|
||||
some:===:-$~+*-/\@_
|
||||
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
|
||||
some:===:-$~+*-/\@
|
||||
most:===:.,:-$~+*-_/\@!#%^&*()[]}{<>;
|
||||
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~
|
||||
|
||||
[punctDict]
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
enabled=True
|
||||
|
||||
# Select the driver used to play sounds, choices are genericDriver and gstreamerDriver.
|
||||
# Sox is the default.
|
||||
#driver=gstreamerDriver
|
||||
driver=genericDriver
|
||||
# Generic driver uses fewer dependencies but spawns a process for each sound played including progress bar beeps
|
||||
# Gstreamer is the default.
|
||||
driver=gstreamerDriver
|
||||
#driver=genericDriver
|
||||
|
||||
# Sound themes. These are the pack of sounds used for sound alerts.
|
||||
# Sound packs may be located at /usr/share/sounds
|
||||
# For system wide availability, or ~/.local/share/fenrirscreenreader/sounds
|
||||
# For the current user.
|
||||
theme=default
|
||||
|
||||
# Sound volume controls how loud the sounds for your selected soundpack are.
|
||||
@@ -24,9 +23,12 @@ volume=0.7
|
||||
# fenrirFrequence = the frequency to play
|
||||
# fenrirDuration = the duration of the frequency
|
||||
# the following command is used to play a soundfile
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
#the following command is used to generate a frequency beep
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
|
||||
# Enable progress bar monitoring with ascending tones by default
|
||||
progress_monitoring=True
|
||||
|
||||
[speech]
|
||||
# Turn speech on or off:
|
||||
@@ -42,7 +44,13 @@ rate=0.5
|
||||
# Pitch controls the pitch of the voice, select from 0, lowest, to 1.0, highest.
|
||||
pitch=0.5
|
||||
# Pitch for capital letters
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
# How to indicate capital letters:
|
||||
# pitch = change speech pitch (uses capital_pitch value)
|
||||
# beep = play Caps.wav sound icon
|
||||
# both = play beep AND change pitch
|
||||
# none = no special indication
|
||||
capital_indicator=pitch
|
||||
|
||||
# Volume controls the loudness of the voice, select from 0, quietest, to 1.0, loudest.
|
||||
volume=1.0
|
||||
@@ -62,10 +70,26 @@ volume=1.0
|
||||
#language=en
|
||||
|
||||
# Read new text as it happens?
|
||||
autoReadIncoming=True
|
||||
auto_read_incoming=True
|
||||
|
||||
# Speak individual numbers instead of whole string.
|
||||
readNumbersAsDigits = False
|
||||
read_numbers_as_digits = False
|
||||
|
||||
# Flood control: batch rapid updates instead of speaking each one
|
||||
# Number of updates within rapid_update_window to trigger batching
|
||||
rapid_update_threshold=5
|
||||
|
||||
# Time window (seconds) for detecting rapid updates
|
||||
rapid_update_window=0.3
|
||||
|
||||
# How often to speak batched content (seconds)
|
||||
batch_flush_interval=0.5
|
||||
|
||||
# Maximum lines to keep when batching (keeps newest, drops oldest)
|
||||
max_batch_lines=100
|
||||
|
||||
# Only enable flood control if this many new lines appear in the window
|
||||
flood_line_threshold=500
|
||||
|
||||
# genericSpeechCommand is the command that is executed for talking
|
||||
# the following variables are replaced with values
|
||||
@@ -78,100 +102,135 @@ readNumbersAsDigits = False
|
||||
# fenrirVolume = is replaced with the current volume
|
||||
# fenrirPitch = is replaced with the current pitch
|
||||
# fenrirRate = is replaced with the current speed (speech rate)
|
||||
genericSpeechCommand=espeak-ng -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice -- "fenrirText"
|
||||
generic_speech_command=espeak-ng -a fenrir_volume -s fenrir_rate -p fenrir_pitch -v fenrir_voice -- "fenrir_text"
|
||||
|
||||
# min and max values of the TTS system that is used in genericSpeechCommand
|
||||
fenrirMinVolume=0
|
||||
fenrirMaxVolume=200
|
||||
fenrirMinPitch=0
|
||||
fenrirMaxPitch=99
|
||||
fenrirMinRate=80
|
||||
fenrirMaxRate=450
|
||||
# min and max values of the TTS system that is used in generic_speech_command
|
||||
fenrir_min_volume=0
|
||||
fenrir_max_volume=200
|
||||
fenrir_min_pitch=0
|
||||
fenrir_max_pitch=99
|
||||
fenrir_min_rate=80
|
||||
fenrir_max_rate=450
|
||||
|
||||
[screen]
|
||||
# Screen driver: vcsaDriver (Linux TTY/virtual console), ptyDriver (terminal emulation)
|
||||
driver=vcsaDriver
|
||||
# Text encoding: auto (auto-detect), utf-8, latin1, etc.
|
||||
encoding=auto
|
||||
screenUpdateDelay=0.05
|
||||
ignoreScreen=
|
||||
autodetectIgnoreScreen=True
|
||||
# Delay in seconds between screen updates (lower = more responsive, higher = less CPU)
|
||||
# Recommended: 0.05 for most systems
|
||||
screen_update_delay=0.05
|
||||
# TTY number to completely ignore (e.g., 7 for X11/graphical login screen)
|
||||
ignore_screen=7
|
||||
# Automatically detect and ignore graphical TTYs (X11, Wayland sessions)
|
||||
autodetect_ignore_screen=True
|
||||
|
||||
[keyboard]
|
||||
driver=evdevDriver
|
||||
# filter input devices NOMICE, ALL or a DEVICE NAME
|
||||
device=ALL
|
||||
# gives Fenrir exclusive access to the keyboard and lets it control keystrokes.
|
||||
grabDevices=True
|
||||
ignoreShortcuts=False
|
||||
grab_devices=True
|
||||
# Ignore shortcut bindings and pass all keys through without processing Fenrir commands.
|
||||
# When True, Fenrir will only monitor screen content without intercepting keyboard input.
|
||||
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
|
||||
keyboardLayout=desktop
|
||||
ignore_shortcuts=False
|
||||
keyboard_layout=desktop
|
||||
# echo chars while typing.
|
||||
# 0 = None
|
||||
# 1 = always
|
||||
# 2 = only while capslock
|
||||
charEchoMode=1
|
||||
# 2 = only while capslock (not compatible with capslock as fenrir key)
|
||||
char_echo_mode=1
|
||||
# echo deleted chars
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
# echo word after pressing space
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
# interrupt speech on any keypress
|
||||
interruptOnKeyPress=True
|
||||
interrupt_on_key_press=True
|
||||
# you can filter the keys on that the speech should interrupt (empty = all keys, otherwhise the given keys)
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
# timeout for double tap in sec
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
|
||||
[general]
|
||||
debugLevel=0
|
||||
# Debug levels: 0=NONE, 1=ERROR, 2=WARNING, 3=INFO (most verbose)
|
||||
# For production use, WARNING (2) provides good balance of useful info without spam
|
||||
# The default is 0, no logging.
|
||||
debug_level=0
|
||||
# debugMode sets where the debug output should send to:
|
||||
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
|
||||
# debugMode=File writes to debug_file (Default:/tmp/fenrir-PID.log)
|
||||
# debugMode=Print just prints on the screen
|
||||
debugMode=File
|
||||
debugFile=
|
||||
punctuationProfile=default
|
||||
punctuationLevel=some
|
||||
respectPunctuationPause=True
|
||||
newLinePause=True
|
||||
numberOfClipboards=50
|
||||
debug_mode=File
|
||||
debug_file=
|
||||
# Punctuation settings control how punctuation is spoken during text review.
|
||||
# Profile selects a punctuation definition file from config/punctuation/ (e.g., default.conf)
|
||||
punctuation_profile=default
|
||||
punctuation_level=some
|
||||
respect_punctuation_pause=True
|
||||
# Replace undefined punctuation with spaces instead of removing them
|
||||
# This improves readability of text with punctuation like [X]mute, IP addresses, etc.
|
||||
replace_undefined_punctuation_with_space=True
|
||||
# Pause speech briefly at newline characters for better readability
|
||||
new_line_pause=True
|
||||
number_of_clipboards=50
|
||||
# used path for "export_clipboard_to_file"
|
||||
# $user is replaced by username
|
||||
#clipboardExportPath=/home/$user/fenrirClipboard
|
||||
clipboardExportPath=/tmp/fenrirClipboard
|
||||
clipboard_export_path=/tmp/fenrirClipboard
|
||||
# Convert text emoticons like :) to descriptive text (e.g., "smiling face")
|
||||
emoticons=True
|
||||
# define the current Fenrir key
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
scriptKeys=KEY_COMPOSE
|
||||
timeFormat=%H:%M:%P
|
||||
dateFormat=%A, %B %d, %Y
|
||||
autoSpellCheck=True
|
||||
spellCheckLanguage=en_US
|
||||
# path for your scripts "scriptKeys" functionality
|
||||
scriptPath=/usr/share/fenrirscreenreader/scripts
|
||||
# overload commands, and create new one without changing Fenrir default
|
||||
commandPath=
|
||||
#fenrirBGColor = the backgroundcolor
|
||||
#fenrirFGColor = the foregroundcolor
|
||||
#fenrirUnderline = speak the underline attribute
|
||||
#fenrirBold = speak the bold attribute
|
||||
#fenrirBlink = speak the blink attribute
|
||||
#fenrirFont = the font
|
||||
#fenrirFontSize = the fontsize
|
||||
attributeFormatString=Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize
|
||||
# present indentation
|
||||
autoPresentIndent=False
|
||||
# speak is only invoked on changeing ident level, sound always
|
||||
# 0 = sound and speak
|
||||
# 1 = sound only
|
||||
# 2 = speak only
|
||||
autoPresentIndentMode=1
|
||||
# play a sound when attributes are changeing
|
||||
hasAttributes=True
|
||||
# shell for PTY emulatiun (empty = default shell)
|
||||
# Define the Fenrir modifier key(s) - used to trigger Fenrir commands
|
||||
# Examples: KEY_KP0 (numpad 0), KEY_META (Super/Windows), KEY_INSERT
|
||||
# Multiple keys: KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
# Script key - used to execute custom scripts in script_path
|
||||
script_keys=KEY_COMPOSE
|
||||
# Time format using Python strftime codes (https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior)
|
||||
# Default: %%I:%%M%%P (12-hour format, e.g., "06:38pm")
|
||||
# 24-hour format: %%H:%%M (e.g., "18:38")
|
||||
# Common codes: %%I=12hr hour, %%H=24hr hour, %%M=minute, %%S=second, %%P=am/pm lowercase, %%p=AM/PM uppercase
|
||||
time_format=%%I:%%M%%P
|
||||
# Date format using Python strftime codes
|
||||
# Default: %%A, %%B %%d, %%Y (e.g., "Tuesday, December 10, 2024")
|
||||
# ISO format: %%Y-%%m-%%d (e.g., "2024-12-10")
|
||||
# Common codes: %%A=weekday name, %%B=month name, %%d=day, %%Y=year with century, %%m=month number
|
||||
date_format=%%A, %%B %%d, %%Y
|
||||
# Automatically spell check words when reviewing character-by-character
|
||||
auto_spell_check=True
|
||||
# Language for spell checking (format: language_COUNTRY, e.g., en_US, en_GB, es_ES)
|
||||
spell_check_language=en_US
|
||||
# path for your scripts "script_keys" functionality
|
||||
script_path=/usr/share/fenrirscreenreader/scripts
|
||||
# Override default commands or add custom commands without modifying Fenrir installation
|
||||
# Leave empty to use default commands only
|
||||
command_path=
|
||||
# Format string for announcing text attributes (colors, formatting)
|
||||
# Available variables:
|
||||
# fenrirBGColor = the background color
|
||||
# fenrirFGColor = the foreground color
|
||||
# fenrirUnderline = speak the underline attribute
|
||||
# fenrirBold = speak the bold attribute
|
||||
# fenrirBlink = speak the blink attribute
|
||||
# fenrirFont = the font name
|
||||
# fenrirFontSize = the font size
|
||||
attribute_format_string=Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize
|
||||
# Automatically announce indentation level changes (useful for Python, YAML, etc.)
|
||||
auto_present_indent=False
|
||||
# How to present indentation changes:
|
||||
# 0 = sound and speak (both audio feedback and voice announcement)
|
||||
# 1 = sound only (just play a tone)
|
||||
# 2 = speak only (just voice announcement)
|
||||
auto_present_indent_mode=1
|
||||
# Play a sound when text attributes (color, bold, etc.) change
|
||||
has_attributes=True
|
||||
# Shell to use for PTY emulation mode (empty = use system default shell)
|
||||
# Examples: /bin/bash, /bin/zsh, /usr/bin/fish
|
||||
shell=
|
||||
|
||||
[focus]
|
||||
#follow the text cursor
|
||||
# Follow and announce text cursor position changes
|
||||
cursor=True
|
||||
#follow highlighted text changes
|
||||
# Follow and announce highlighted/selected text changes (useful in menus)
|
||||
highlight=False
|
||||
|
||||
[remote]
|
||||
@@ -183,47 +242,86 @@ driver=unixDriver
|
||||
# tcp port
|
||||
port=22447
|
||||
# socket filepath
|
||||
socketFile=
|
||||
socket_file=
|
||||
# allow settings to overwrite
|
||||
enableSettingsRemote=True
|
||||
enable_settings_remote=True
|
||||
# allow commands to be executed
|
||||
enableCommandRemote=True
|
||||
enable_command_remote=True
|
||||
|
||||
[barrier]
|
||||
# Enable barrier detection - automatically detects table/box borders for improved navigation
|
||||
enabled=False
|
||||
leftBarriers=│└┌─
|
||||
rightBarriers=│┘┐─
|
||||
# Characters that represent left-side barriers/borders (for table/box detection)
|
||||
left_barriers=│└┌─
|
||||
# Characters that represent right-side barriers/borders (for table/box detection)
|
||||
right_barriers=│┘┐─
|
||||
|
||||
[review]
|
||||
lineBreak=True
|
||||
endOfScreen=True
|
||||
# leave the review when pressing a key
|
||||
leaveReviewOnCursorChange=True
|
||||
# leave the review when changing the screen
|
||||
leaveReviewOnScreenChange=True
|
||||
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=
|
||||
# Announce line breaks during review mode
|
||||
line_break=True
|
||||
# Announce when reaching the end of screen during review
|
||||
end_of_screen=True
|
||||
# Exit review mode when cursor position changes (e.g., when typing)
|
||||
leave_review_on_cursor_change=True
|
||||
# Exit review mode when switching to a different TTY/screen
|
||||
leave_review_on_screen_change=True
|
||||
|
||||
[menu]
|
||||
vmenuPath=
|
||||
quickMenu=speech#rate;speech#pitch;speech#volume
|
||||
# Custom path for VMenu (virtual menu) profiles
|
||||
# Leave empty to use default location (/etc/fenrirscreenreader/vmenu-profiles/)
|
||||
vmenu_path=
|
||||
# Quick menu: Semicolon-separated list of settings for rapid adjustment via VMenu
|
||||
# Access with Fenrir+F10, navigate to "Quick Settings"
|
||||
# Format: section#setting;section#setting;...
|
||||
# Supported settings:
|
||||
# - speech#rate, speech#pitch, speech#volume (0.0-1.0)
|
||||
# - speech#module, speech#voice (speechdDriver only, auto-added)
|
||||
# Note: speech#module and speech#voice are automatically added when
|
||||
# speechdDriver is active. Do not add them manually.
|
||||
quick_menu=speech#rate;speech#pitch;speech#volume
|
||||
|
||||
[prompt]
|
||||
# Custom prompt patterns for silence until prompt feature
|
||||
# You can add your own shell prompt patterns as regular expressions
|
||||
# Each pattern should be on a separate line, format: customPatterns=pattern1,pattern2,pattern3
|
||||
#
|
||||
# Built-in patterns include:
|
||||
# - Shell prompts: $, #, >, user@host$, [user@host]$, bash-5.1$
|
||||
# - Package manager prompts: [Y/n], [y/N], [Yes/No], (Y/n), (y/N)
|
||||
# - sudo prompts: [sudo] password for user:, Password:, user's password:
|
||||
# - Confirmation prompts: Press any key, Are you sure?, Please confirm
|
||||
#
|
||||
# Custom pattern examples:
|
||||
# For PS1='[\u@\h \W] \$ ' use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For "[user@hostname ~] $" use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For custom prompts ending with specific strings, use patterns like: .*your_prompt_ending$
|
||||
# For custom package manager prompts: .*your_package_manager.*\[[YyNn]/[YyNn]\].*
|
||||
custom_patterns=
|
||||
|
||||
# Specific prompt strings to match exactly (useful for very specific custom prompts)
|
||||
# Format: exact_matches=prompt1,prompt2,prompt3
|
||||
# Examples:
|
||||
# exact_matches=[storm@fenrir ~] $,[root@fenrir ~] #,Continue installation? [Y/n]
|
||||
exact_matches=
|
||||
|
||||
[time]
|
||||
# automatic time anouncement
|
||||
# Enable automatic time announcements
|
||||
enabled=False
|
||||
# present time
|
||||
presentTime=True
|
||||
# present date (on change)
|
||||
presentDate=True
|
||||
# present time after a given period of seconds
|
||||
delaySec=0
|
||||
# present time after to given minutes example every 15 minutes: 00,15,30,45
|
||||
# if delaySec is >0 onMinutes is ignored
|
||||
onMinutes=00,30
|
||||
# announce via soundicon (not interrupting)
|
||||
# Announce the current time
|
||||
present_time=True
|
||||
# Announce the date (only when it changes, e.g., at midnight)
|
||||
present_date=True
|
||||
# Announce time every N seconds (0 = disabled)
|
||||
# If delay_sec > 0, on_minutes is ignored
|
||||
delay_sec=0
|
||||
# Announce time at specific minutes of each hour (comma-separated)
|
||||
# Examples:
|
||||
# 00 = Only on the hour (1:00, 2:00, 3:00, etc.)
|
||||
# 00,30 = On the hour and half-hour (1:00, 1:30, 2:00, 2:30, etc.)
|
||||
# 00,15,30,45 = Every 15 minutes
|
||||
# Note: This is ignored if delay_sec > 0
|
||||
on_minutes=00,30
|
||||
# Play a sound icon before time announcement (non-interrupting)
|
||||
announce=True
|
||||
# interrupt current speech for time announcement
|
||||
# Interrupt current speech to announce time immediately
|
||||
interrupt=False
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,9 +30,6 @@ ContentChanged='ContentChanged.wav'
|
||||
# Speech has turned On or Off
|
||||
SpeechOn='SpeechOn.wav'
|
||||
SpeechOff='SpeechOff.wav'
|
||||
# Braille has turned On or Off
|
||||
BrailleOn='BrailleOn.wav'
|
||||
BrailleOff='BrailleOff.wav'
|
||||
# SoundIcons has turned On or Off
|
||||
SoundOn='SoundOn.wav'
|
||||
SoundOff='SoundOff.wav'
|
||||
@@ -44,14 +41,11 @@ PlaceEndMark='PlaceEndMark.wav'
|
||||
CopyToClipboard='CopyToClipboard.wav'
|
||||
# Pasted on the screen
|
||||
PasteClipboardOnScreen='PasteClipboardOnScreen.wav'
|
||||
# An error accoured while speech or braille output or reading the screen
|
||||
# An error accoured while speech output or reading the screen
|
||||
ErrorSpeech='ErrorSpeech.wav'
|
||||
ErrorBraille='ErrorBraille.wav'
|
||||
ErrorScreen='ErrorScreen.wav'
|
||||
# If you cursor over an text that has attributs (like color)
|
||||
HasAttributes='has_attribute.wav'
|
||||
# fenrir can promote strings if they appear on the screen.
|
||||
PromotedText='PromotedText.wav'
|
||||
# missspelled indicator
|
||||
mispell='mispell.wav'
|
||||
# the for capital letter
|
||||
|
||||
@@ -50,8 +50,6 @@ ErrorBraille=''
|
||||
ErrorScreen=''
|
||||
# If you cursor over an text that has attributs (like color)
|
||||
HasAttributes=''
|
||||
# fenrir can promote strings if they appear on the screen.
|
||||
PromotedText=''
|
||||
# misspelled indicator
|
||||
mispell=''
|
||||
# the for capital letter:
|
||||
|
||||
@@ -1,4 +1,389 @@
|
||||
1. Basic
|
||||
2. Commands
|
||||
3. Useful API
|
||||
# Fenrir Development Guide
|
||||
|
||||
This document provides information for developers who want to contribute to Fenrir or understand its architecture.
|
||||
|
||||
## Project Structure
|
||||
|
||||
Fenrir follows a modular, driver-based architecture:
|
||||
|
||||
```
|
||||
src/fenrirscreenreader/
|
||||
├── core/ # Core system modules
|
||||
│ ├── fenrirManager.py # Main application manager
|
||||
│ ├── screenManager.py # Screen handling
|
||||
│ ├── inputManager.py # Input handling
|
||||
│ ├── outputManager.py # Speech/sound output
|
||||
│ ├── commandManager.py # Command system
|
||||
│ └── settingsManager.py # Configuration management
|
||||
├── commands/ # Command implementations
|
||||
│ ├── commands/ # User-invoked commands
|
||||
│ ├── onCursorChange/ # Cursor movement hooks
|
||||
│ ├── onScreenUpdate/ # Screen update hooks
|
||||
│ ├── onKeyInput/ # Key input hooks
|
||||
│ └── help/ # Tutorial system
|
||||
├── drivers/ # Driver implementations
|
||||
│ ├── inputDriver/ # Input drivers (evdev, pty, atspi)
|
||||
│ ├── screenDriver/ # Screen drivers (vcsa, pty)
|
||||
│ ├── speechDriver/ # Speech drivers (speechd, generic)
|
||||
│ └── soundDriver/ # Sound drivers (generic, gstreamer)
|
||||
└── utils/ # Utility modules
|
||||
```
|
||||
|
||||
## Core Architecture
|
||||
|
||||
### Driver System
|
||||
Fenrir uses a pluggable driver architecture:
|
||||
|
||||
1. **Input Drivers**: Capture keyboard input
|
||||
- evdevDriver: Linux evdev (recommended)
|
||||
- ptyDriver: Terminal emulation
|
||||
- atspiDriver: AT-SPI for desktop
|
||||
|
||||
2. **Screen Drivers**: Read screen content
|
||||
- vcsaDriver: Linux VCSA devices
|
||||
- ptyDriver: Terminal emulation
|
||||
|
||||
3. **Speech Drivers**: Text-to-speech output
|
||||
- speechdDriver: Speech-dispatcher
|
||||
- genericDriver: Command-line TTS
|
||||
|
||||
4. **Sound Drivers**: Audio output
|
||||
- genericDriver: Sox-based
|
||||
- gstreamerDriver: GStreamer
|
||||
|
||||
5. **Remote Drivers**: Remote control interfaces
|
||||
- unixDriver: Unix socket control
|
||||
- tcpDriver: TCP socket control
|
||||
|
||||
### Command System
|
||||
Commands are Python modules that implement specific functionality:
|
||||
|
||||
```python
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def getDescription(self):
|
||||
return _('Command description')
|
||||
|
||||
def run(self):
|
||||
# Command implementation
|
||||
pass
|
||||
```
|
||||
|
||||
### Event Hooks
|
||||
Fenrir supports various event hooks:
|
||||
|
||||
- **onCursorChange**: Triggered when cursor moves
|
||||
- **onScreenUpdate**: Triggered on screen content changes
|
||||
- **onKeyInput**: Triggered on key presses
|
||||
- **onByteInput**: Triggered on byte-level input
|
||||
- **onScreenChanged**: Triggered when switching screens
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Requirements
|
||||
- Python 3.6+
|
||||
- python3-evdev
|
||||
- python3-pyudev
|
||||
- speech-dispatcher
|
||||
- sox
|
||||
|
||||
### Getting Started
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://git.stormux.org/storm/fenrir.git
|
||||
cd fenrir
|
||||
|
||||
# Install dependencies
|
||||
sudo pip3 install -r requirements.txt
|
||||
|
||||
# Run from source
|
||||
cd src/
|
||||
sudo ./fenrir -f -d
|
||||
```
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Run in debug mode
|
||||
sudo ./fenrir -f -d -p
|
||||
|
||||
# Debug output goes to:
|
||||
# - Console (with -p flag)
|
||||
# - /var/log/fenrir.log
|
||||
```
|
||||
|
||||
## Creating Commands
|
||||
|
||||
### Basic Command
|
||||
Create a file in `src/fenrirscreenreader/commands/commands/`:
|
||||
|
||||
```python
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def getDescription(self):
|
||||
return _('My custom command')
|
||||
|
||||
def run(self):
|
||||
# Get current text
|
||||
text = self.env['screen']['newContentText']
|
||||
|
||||
# Speak something
|
||||
self.env['runtime']['outputManager'].presentText('Hello World')
|
||||
|
||||
# Play sound
|
||||
self.env['runtime']['outputManager'].playSoundIcon('Accept')
|
||||
```
|
||||
|
||||
### Key Bindings
|
||||
Add key bindings in keyboard layout files:
|
||||
`config/keyboard/desktop.conf` or `config/keyboard/laptop.conf`
|
||||
|
||||
```ini
|
||||
[KEY_CTRL]#[KEY_ALT]#[KEY_H]=my_command
|
||||
```
|
||||
|
||||
### Event Hooks
|
||||
Create event handlers in appropriate directories:
|
||||
|
||||
```python
|
||||
# onCursorChange/my_hook.py
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def getDescription(self):
|
||||
return _('My cursor change handler')
|
||||
|
||||
def run(self):
|
||||
if self.env['runtime']['cursorManager'].isCursorHorizontalMove():
|
||||
# Handle horizontal cursor movement
|
||||
pass
|
||||
```
|
||||
|
||||
## Creating Drivers
|
||||
|
||||
### Driver Template
|
||||
```python
|
||||
class driver():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
# Driver-specific methods...
|
||||
```
|
||||
|
||||
### Input Driver
|
||||
Implement these methods:
|
||||
- `getInputEvent()`: Return input events
|
||||
- `writeEventBuffer()`: Handle output events
|
||||
- `grabDevices()`: Take exclusive control
|
||||
- `releaseDevices()`: Release control
|
||||
|
||||
### Screen Driver
|
||||
Implement these methods:
|
||||
- `getCurrScreen()`: Get current screen content
|
||||
- `getSessionInformation()`: Get session info
|
||||
|
||||
### Speech Driver
|
||||
Implement these methods:
|
||||
- `speak()`: Speak text
|
||||
- `cancel()`: Stop speech
|
||||
- `setCallback()`: Set callback functions
|
||||
|
||||
### Remote Driver
|
||||
Implement these methods:
|
||||
- `initialize()`: Setup socket/connection
|
||||
- `watchDog()`: Listen for incoming commands
|
||||
- `shutdown()`: Clean up connections
|
||||
|
||||
#### Remote Driver Example
|
||||
```python
|
||||
class driver(remoteDriver):
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
# Start watchdog thread
|
||||
self.env['runtime']['processManager'].addCustomEventThread(
|
||||
self.watchDog, multiprocess=True
|
||||
)
|
||||
|
||||
def watchDog(self, active, eventQueue):
|
||||
# Listen for connections and process commands
|
||||
while active.value:
|
||||
# Accept connections
|
||||
# Parse incoming data
|
||||
# Send to event queue
|
||||
eventQueue.put({
|
||||
"Type": fenrirEventType.RemoteIncomming,
|
||||
"Data": command_text
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Settings System
|
||||
Settings are hierarchical:
|
||||
1. Command-line options (`-o`)
|
||||
2. Configuration file
|
||||
3. Hard-coded defaults
|
||||
|
||||
### Adding Settings
|
||||
1. Add default value to `core/settingsData.py`
|
||||
2. Access via `self.env['runtime']['settingsManager'].getSetting(section, key)`
|
||||
|
||||
## Debugging
|
||||
|
||||
### Debug Levels
|
||||
- 0: DEACTIVE
|
||||
- 1: ERROR
|
||||
- 2: WARNING
|
||||
- 3: INFO
|
||||
|
||||
### Debug Output
|
||||
```python
|
||||
self.env['runtime']['debug'].writeDebugOut(
|
||||
'Debug message',
|
||||
debug.debugLevel.INFO
|
||||
)
|
||||
```
|
||||
|
||||
### Testing Commands
|
||||
```bash
|
||||
# Test specific functionality
|
||||
sudo fenrir -f -d -o "general#debugLevel=3"
|
||||
|
||||
# Test with custom config
|
||||
sudo fenrir -f -s /path/to/test.conf
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
### Code Style
|
||||
- Follow PEP 8
|
||||
- Use descriptive variable names
|
||||
- Add docstrings for complex functions
|
||||
- Handle exceptions gracefully
|
||||
|
||||
### Testing
|
||||
- Test with different drivers
|
||||
- Test keyboard layouts
|
||||
- Test on different terminals
|
||||
- Verify accessibility features
|
||||
|
||||
### Submitting Changes
|
||||
1. Fork the repository
|
||||
2. Create feature branch
|
||||
3. Make changes with clear commit messages
|
||||
4. Test thoroughly
|
||||
5. Submit pull request
|
||||
|
||||
## API Reference
|
||||
|
||||
### Environment Structure
|
||||
The `environment` dict contains all runtime data:
|
||||
|
||||
```python
|
||||
environment = {
|
||||
'runtime': {
|
||||
'settingsManager': settingsManager,
|
||||
'commandManager': commandManager,
|
||||
'screenManager': screenManager,
|
||||
'inputManager': inputManager,
|
||||
'outputManager': outputManager,
|
||||
'debug': debugManager,
|
||||
# ... other managers
|
||||
},
|
||||
'screen': {
|
||||
'newContentText': '',
|
||||
'oldContentText': '',
|
||||
'newCursor': {'x': 0, 'y': 0},
|
||||
'oldCursor': {'x': 0, 'y': 0},
|
||||
# ... screen data
|
||||
},
|
||||
'general': {
|
||||
'prevCommand': '',
|
||||
'currCommand': '',
|
||||
# ... general data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Common Operations
|
||||
|
||||
#### Speaking Text
|
||||
```python
|
||||
self.env['runtime']['outputManager'].presentText('Hello')
|
||||
```
|
||||
|
||||
#### Playing Sounds
|
||||
```python
|
||||
self.env['runtime']['outputManager'].playSoundIcon('Accept')
|
||||
```
|
||||
|
||||
#### Getting Settings
|
||||
```python
|
||||
rate = self.env['runtime']['settingsManager'].getSetting('speech', 'rate')
|
||||
```
|
||||
|
||||
#### Cursor Information
|
||||
```python
|
||||
x = self.env['screen']['newCursor']['x']
|
||||
y = self.env['screen']['newCursor']['y']
|
||||
```
|
||||
|
||||
#### Screen Content
|
||||
```python
|
||||
text = self.env['screen']['newContentText']
|
||||
lines = text.split('\n')
|
||||
current_line = lines[self.env['screen']['newCursor']['y']]
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Release Process
|
||||
1. Update version in `fenrirVersion.py`
|
||||
2. Update changelog
|
||||
3. Test on multiple systems
|
||||
4. Tag release
|
||||
5. Update documentation
|
||||
|
||||
### Compatibility
|
||||
- Maintain Python 3.6+ compatibility
|
||||
- Test on multiple Linux distributions
|
||||
- Ensure driver compatibility
|
||||
- Check dependencies
|
||||
|
||||
## Resources
|
||||
|
||||
- **Repository**: https://git.stormux.org/storm/fenrir
|
||||
- **Wiki**: https://git.stormux.org/storm/fenrir/wiki
|
||||
- **Issues**: Use repository issue tracker
|
||||
- **Community**: IRC irc.stormux.org #stormux
|
||||
- **Email**: stormux+subscribe@groups.io
|
||||
3263
docs/fenrir.1
3263
docs/fenrir.1
File diff suppressed because it is too large
Load Diff
296
docs/fenrir.adoc
296
docs/fenrir.adoc
@@ -7,14 +7,14 @@ configurable and easy to customize and extend.
|
||||
=== Credit and intended audience
|
||||
|
||||
This document is just a customization for Slint of the genuine
|
||||
https://github.com/chrys87/fenrir/blob/master/docu/user.txt[Fenrir User
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/docs/user.txt[Fenrir User
|
||||
Manual] motly written by Chrys, main developer of Fenrir.
|
||||
|
||||
It has been adapted to its intended audience: end users of Fenrir on
|
||||
Slint where it is already installed, thus concentrates on its setting
|
||||
and usage. You will find more information about its features,
|
||||
installation and how customize and troubleshoot it and contribute to its
|
||||
development on https://github.com/chrys87/fenrir[the Fenrir Git
|
||||
development on https://git.stormux.org/storm/fenrir[the Fenrir Git
|
||||
repository].
|
||||
|
||||
=== Getting started with Fenrir
|
||||
@@ -1095,23 +1095,6 @@ announce=True
|
||||
interrupt=False
|
||||
....
|
||||
|
||||
==== Promoted List
|
||||
|
||||
Promoted Lists are a nice feature if you are away from your computer or
|
||||
performing more longer tasks. you can define a list of words which you
|
||||
want to hear a sound icon for after a period of inactivity. Example if
|
||||
the word "Chrys" appears after 120 Seconds of inactivity:
|
||||
|
||||
....
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=Chrys
|
||||
....
|
||||
|
||||
See section link:#Promote[Promote] in `+settings.conf+` for more
|
||||
information.
|
||||
|
||||
=== Dictionary
|
||||
|
||||
You can make use of different kinds of built-in dictionary's. A
|
||||
@@ -1202,6 +1185,47 @@ link:#Settings[Settings]
|
||||
|
||||
=== Commandline Arguments
|
||||
|
||||
Fenrir supports several command-line options:
|
||||
|
||||
....
|
||||
fenrir [OPTIONS]
|
||||
....
|
||||
|
||||
==== Available Options
|
||||
|
||||
`+-h, --help+`::
|
||||
Show help message and exit.
|
||||
|
||||
`+-v, --version+`::
|
||||
Show version information and exit.
|
||||
|
||||
`+-f, --foreground+`::
|
||||
Run Fenrir in the foreground instead of as a daemon.
|
||||
|
||||
`+-s, --setting SETTING-FILE+`::
|
||||
Path to a custom settings file.
|
||||
|
||||
`+-o, --options SECTION#SETTING=VALUE;..+`::
|
||||
Override settings file options (see below for details).
|
||||
|
||||
`+-d, --debug+`::
|
||||
Enable debug mode. Debug information will be logged.
|
||||
|
||||
`+-p, --print+`::
|
||||
Print debug messages to screen in addition to logging them.
|
||||
|
||||
`+-e, --emulated-pty+`::
|
||||
Use PTY emulation with escape sequences for input. This enables usage in desktop/X11/Wayland environments and terminal emulators.
|
||||
|
||||
`+-E, --emulated-evdev+`::
|
||||
Use PTY emulation with evdev for input (single instance mode).
|
||||
|
||||
`+-F, --force-all-screens+`::
|
||||
Force Fenrir to respond on all screens, ignoring the ignoreScreen setting. This temporarily overrides screen filtering for the current session.
|
||||
|
||||
`+-i, -I, --ignore-screen <SCREEN>+`::
|
||||
Ignore specific screen(s). Can be used multiple times to ignore multiple screens. This is equivalent to setting ignoreScreen in the configuration file and will be combined with any existing ignore settings.
|
||||
|
||||
==== Set settings options
|
||||
|
||||
You can specify options that overwrite the setting.conf. This is done
|
||||
@@ -1224,9 +1248,154 @@ or change the debug level to verbose
|
||||
fenrir -o "general#debugLevel=3"
|
||||
....
|
||||
|
||||
Example using force all screens option:
|
||||
|
||||
....
|
||||
fenrir -F
|
||||
....
|
||||
|
||||
You can find the available sections and variables here #Settings See
|
||||
Syntax link:#settings.conf syntax[#settings.conf syntax]
|
||||
|
||||
=== Remote Control
|
||||
|
||||
Fenrir includes a powerful remote control system that allows external applications and scripts to control Fenrir through Unix sockets or TCP connections.
|
||||
|
||||
==== Configuration
|
||||
|
||||
Enable remote control in settings.conf:
|
||||
|
||||
....
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver
|
||||
enable_settings_remote=True
|
||||
enable_command_remote=True
|
||||
....
|
||||
|
||||
==== Using socat with Unix Sockets
|
||||
|
||||
The `+socat+` command provides the easiest way to send commands to Fenrir:
|
||||
|
||||
===== Basic Speech Control
|
||||
|
||||
....
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Temporarily disable speech (until next keystroke)
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
....
|
||||
|
||||
===== Settings Control
|
||||
|
||||
....
|
||||
# Enable highlight tracking mode
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Change speech rate
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Voice and TTS control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Reset all settings to defaults
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
....
|
||||
|
||||
===== Clipboard Operations
|
||||
|
||||
....
|
||||
# Place text into clipboard
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
....
|
||||
|
||||
===== Application Control
|
||||
|
||||
....
|
||||
# Quit Fenrir
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
....
|
||||
|
||||
==== Command Reference
|
||||
|
||||
===== Available Commands
|
||||
|
||||
*Speech Commands:*
|
||||
|
||||
* `+command say <text>+` - Speak the specified text
|
||||
* `+command interrupt+` - Stop current speech
|
||||
* `+command tempdisablespeech+` - Disable speech until next key press
|
||||
|
||||
*Clipboard Commands:*
|
||||
|
||||
* `+command clipboard <text>+` - Add text to clipboard
|
||||
* `+command exportclipboard+` - Export clipboard to file
|
||||
|
||||
*Window Commands:*
|
||||
|
||||
* `+command window <x1> <y1> <x2> <y2>+` - Define window area
|
||||
* `+command resetwindow+` - Reset to full screen
|
||||
|
||||
*VMenu Commands:*
|
||||
|
||||
* `+command vmenu <menu_path>+` - Set virtual menu context
|
||||
* `+command resetvmenu+` - Reset virtual menu
|
||||
|
||||
*Application Commands:*
|
||||
|
||||
* `+command quitapplication+` - Quit Fenrir
|
||||
|
||||
===== Available Settings
|
||||
|
||||
*Settings Commands:*
|
||||
|
||||
* `+setting set <section>#<key>=<value>+` - Set configuration value
|
||||
* `+setting reset+` - Reset all settings to defaults
|
||||
* `+setting save [path]+` - Save current settings
|
||||
|
||||
*Key Settings You Can Control:*
|
||||
|
||||
*Speech Settings:*
|
||||
* `+speech#enabled=True/False+` - Enable/disable speech
|
||||
* `+speech#rate=0.1-1.0+` - Speech rate (speed)
|
||||
* `+speech#pitch=0.1-1.0+` - Speech pitch (tone)
|
||||
* `+speech#volume=0.1-1.0+` - Speech volume
|
||||
* `+speech#voice=voice_name+` - Voice selection (e.g., "en-us+f3")
|
||||
* `+speech#module=module_name+` - TTS module (e.g., "espeak-ng")
|
||||
|
||||
*General Settings:*
|
||||
* `+general#punctuation_level=none/some/most/all+` - Punctuation verbosity
|
||||
* `+general#auto_spell_check=True/False+` - Automatic spell checking
|
||||
* `+general#emoticons=True/False+` - Enable emoticon replacement
|
||||
|
||||
*Sound Settings:*
|
||||
* `+sound#enabled=True/False+` - Enable/disable sound
|
||||
* `+sound#volume=0.1-1.0+` - Sound volume
|
||||
|
||||
*Focus Settings:*
|
||||
* `+focus#cursor=True/False+` - Follow text cursor
|
||||
* `+focus#highlight=True/False+` - Follow text highlighting
|
||||
|
||||
*Keyboard Settings:*
|
||||
* `+keyboard#char_echo_mode=0-2+` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
* `+keyboard#word_echo=True/False+` - Echo complete words
|
||||
|
||||
*Screen Settings:*
|
||||
* `+screen#ignore_screen=1,2,3+` - TTY screens to ignore
|
||||
|
||||
==== settings.conf syntax
|
||||
|
||||
the syntax of the link:#Settings[settings.conf] is quite simple and
|
||||
@@ -1325,14 +1494,14 @@ frequencies.
|
||||
sound file.
|
||||
|
||||
....
|
||||
genericPlayFileCommand=<your command for playing a file>
|
||||
generic_play_file_command=<your command for playing a file>
|
||||
....
|
||||
|
||||
`+genericFrequencyCommand+` defines the command that is used playing
|
||||
frequencies.
|
||||
|
||||
....
|
||||
genericFrequencyCommand=<your command for playing a frequence>
|
||||
generic_frequency_command=<your command for playing a frequence>
|
||||
....
|
||||
|
||||
The following variables are substituted in `+genericPlayFileCommand+`
|
||||
@@ -1346,13 +1515,13 @@ and `+genericFrequencyCommand+`:
|
||||
Example genericPlayFileCommand (default)
|
||||
|
||||
....
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
....
|
||||
|
||||
Example genericFrequencyCommand (default)
|
||||
|
||||
....
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
....
|
||||
|
||||
==== Speech
|
||||
@@ -1393,7 +1562,7 @@ Values: Range Minimum:`+0.0+` is lowest, Maximum:`+1.0+` is highest.
|
||||
A Pitch for capital letters can be set.
|
||||
|
||||
....
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
....
|
||||
|
||||
Values: Range Minimum:`+0.0+` is lowest, Maximum:`+1.0+` is highest.
|
||||
@@ -1495,7 +1664,7 @@ the pico module:
|
||||
language=de-DE
|
||||
....
|
||||
|
||||
Read new text as it occurs autoReadIncoming=True Values: on=`+True+`,
|
||||
Read new text as it occurs auto_read_incoming=True Values: on=`+True+`,
|
||||
off=`+False+`
|
||||
|
||||
==== Screen
|
||||
@@ -1525,7 +1694,7 @@ Values:`+cp850+` is used for Western languages like USA or Europe.
|
||||
The driver updates Fenrir with changes on the screen.
|
||||
|
||||
....
|
||||
screenUpdateDelay=0.05
|
||||
screen_update_delay=0.05
|
||||
....
|
||||
|
||||
Values: in Seconds
|
||||
@@ -1590,7 +1759,7 @@ Gives Fenrir exclusive access to the keyboard and lets it control
|
||||
keystrokes. This is needed to intercept Fenrir related shortcuts.
|
||||
|
||||
....
|
||||
grabDevices=True
|
||||
grab_devices=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1599,7 +1768,7 @@ The following makes sense if you are using a second screenreader and
|
||||
want to have some hooked events. Fenrir ignores all shortcuts then.
|
||||
|
||||
....
|
||||
ignoreShortcuts=False
|
||||
ignore_shortcuts=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1607,7 +1776,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
The current keyboard layout used for shortcuts.
|
||||
|
||||
....
|
||||
keyboardLayout=desktop
|
||||
keyboard_layout=desktop
|
||||
....
|
||||
|
||||
Values: An absolute Path to a Keyboard definition file or a Filename
|
||||
@@ -1624,7 +1793,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Announce deleted characters
|
||||
|
||||
....
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1632,7 +1801,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Announce word after pressing space
|
||||
|
||||
....
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1640,7 +1809,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Interrupt speech on any keypress
|
||||
|
||||
....
|
||||
interruptOnKeyPress=False
|
||||
interrupt_on_key_press=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1648,7 +1817,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
You can filter the keys that speech should interrupt
|
||||
|
||||
....
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
....
|
||||
|
||||
Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
@@ -1656,7 +1825,7 @@ Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
The timeout that is used for double tap shortcuts
|
||||
|
||||
....
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
....
|
||||
|
||||
Values: Seconds
|
||||
@@ -1676,7 +1845,7 @@ Values: off=0, error=1, warning=2, info=3
|
||||
the current punctuation and dict file in use:
|
||||
|
||||
....
|
||||
punctuationProfile=default
|
||||
punctuation_profile=default
|
||||
....
|
||||
|
||||
Values: Text, see available profiles in `+/etc/fenrir/punctuation+` or
|
||||
@@ -1685,7 +1854,7 @@ in `+sourceTree/config/punctuation+`
|
||||
The current punctuation level in use:
|
||||
|
||||
....
|
||||
punctuationLevel=some
|
||||
punctuation_level=some
|
||||
....
|
||||
|
||||
Values: Text, See available levels in the used punctuation file.
|
||||
@@ -1693,7 +1862,7 @@ Values: Text, See available levels in the used punctuation file.
|
||||
Respect pause for punctuations:
|
||||
|
||||
....
|
||||
respectPunctuationPause=True
|
||||
respect_punctuation_pause=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1701,7 +1870,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Add a pause on Line break:
|
||||
|
||||
....
|
||||
newLinePause=True
|
||||
new_line_pause=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1719,7 +1888,7 @@ Values: Text, Systemfilepath
|
||||
The number of available clipboards:
|
||||
|
||||
....
|
||||
numberOfClipboards=10
|
||||
number_of_clipboards=10
|
||||
....
|
||||
|
||||
Values: Integer, 1 - 999
|
||||
@@ -1735,7 +1904,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Define the current Fenrir keys:
|
||||
|
||||
....
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
....
|
||||
|
||||
Values, Text list, separated by comma.
|
||||
@@ -1769,7 +1938,7 @@ https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior[d
|
||||
Enable or Disable spellcheck whilst typing:
|
||||
|
||||
....
|
||||
autoSpellCheck=True
|
||||
auto_spell_check=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1777,7 +1946,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
The use of the dictionary with spellcheck:
|
||||
|
||||
....
|
||||
spellCheckLanguage=en_US
|
||||
spell_check_language=en_US
|
||||
....
|
||||
|
||||
Values: Text, see aspell dictionary's.
|
||||
@@ -1858,44 +2027,11 @@ Values: on=`+True+`, off=`+False+`
|
||||
Leave the review mode when changing the screen (From TTY3 to TTY4):
|
||||
|
||||
....
|
||||
leaveReviewOnScreenChange=True
|
||||
leave_review_on_screen_change=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
|
||||
==== Promote
|
||||
|
||||
"Promoted Lists" are configured in the section `+[promote]+`. Turn
|
||||
Promoted Lists" on or off:
|
||||
|
||||
....
|
||||
enabled=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
|
||||
The minimum time interval of inactivity to activate promoting. By
|
||||
default it promotes after 120 Seconds inactivity:
|
||||
|
||||
....
|
||||
inactiveTimeoutSec=120
|
||||
....
|
||||
|
||||
Values: in Seconds
|
||||
|
||||
Define a list of promoted words comma seperated:
|
||||
|
||||
....
|
||||
list=
|
||||
....
|
||||
|
||||
Values: text (comma seperated) Example to promote the word "nickname" or
|
||||
a bash prompt:
|
||||
|
||||
....
|
||||
list=nickname,$:,#:
|
||||
....
|
||||
|
||||
==== Time
|
||||
|
||||
The automated time announcement is configured in the section `+[time]+`.
|
||||
@@ -2007,9 +2143,9 @@ settings.conf). Commands are python files with a special scheme. You can
|
||||
assign them to a shortcut using the filename without an extension or
|
||||
place them in a hook trigger like OnInput or OnScreenChange. For further
|
||||
information see developer guide. Good Examples:
|
||||
https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py["date.py"]
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/date.py["date.py"]
|
||||
(announce the Date),
|
||||
https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py["shut_up.py"]
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/shut_up.py["shut_up.py"]
|
||||
(interrupt output) the basic scheme for a command is as follows:
|
||||
|
||||
....
|
||||
@@ -2032,7 +2168,7 @@ class command():
|
||||
pass
|
||||
....
|
||||
|
||||
* https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py[Template
|
||||
* https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/command_template.py[Template
|
||||
lives here]
|
||||
* The class needs to have the name "command".
|
||||
* "initialize" is running once whilst loading the command.
|
||||
@@ -2090,7 +2226,7 @@ root.
|
||||
=== Bugreports and feature requests
|
||||
|
||||
Please report Bugs and feature requests to:
|
||||
https://github.com/chrys87/fenrir/issues
|
||||
https://git.stormux.org/storm/fenrir/issues
|
||||
|
||||
for bugs please provide a link:#Howto create a debug file[debug] file
|
||||
that shows the issue.
|
||||
|
||||
1937
docs/user.md
1937
docs/user.md
File diff suppressed because it is too large
Load Diff
@@ -160,7 +160,7 @@ For Arch there are PKGBUILDs in the AUR:
|
||||
|
||||
- Download the latest stable version from the [[https://linux-a11y.org/index.php?page=fenrir-screenreader|Fenrir-Project]] site.
|
||||
- Unpack the archive
|
||||
- Check the needed Dependencys by running [[https://github.com/chrys87/fenrir/blob/master/check-dependencies.py|check-dependencys.py]] script
|
||||
- Check the needed Dependencys by running [[https://git.stormux.org/storm/fenrir/src/branch/master/check-dependencies.py|check-dependencys.py]] script
|
||||
- install the missing dependencies an standard installation requires the following:
|
||||
* python3 >= 3.3 (and all the following is needed for python3 )
|
||||
* python3-speechd (screen)
|
||||
@@ -171,7 +171,7 @@ For Arch there are PKGBUILDs in the AUR:
|
||||
* python3-pyenchant (spellchecker)
|
||||
* your language for aspell (aspell-<lang>) (spellchecker)
|
||||
* sox (sound)
|
||||
* For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://github.com/chrys87/fenrir/blob/master/README.md|Readme]])
|
||||
* For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://git.stormux.org/storm/fenrir/src/branch/master/README.md|Readme]])
|
||||
- run "install.sh" as root
|
||||
|
||||
this installs Fenrir as the following
|
||||
@@ -185,7 +185,7 @@ to remove Fenrir just run uninstall.sh as root
|
||||
|
||||
if you want to get the latest code you can use git to get a development snapshot:
|
||||
|
||||
git clone https://github.com/chrys87/fenrir.git
|
||||
git clone https://git.stormux.org/storm/fenrir.git
|
||||
|
||||
===== Auto Start =====
|
||||
|
||||
@@ -729,15 +729,6 @@ Example on fix minutes in an hour. example every quarter "delaySec=0" and "onMin
|
||||
onMinutes=00,15,30,45
|
||||
announce=True
|
||||
interrupt=False
|
||||
==== Promoted List ====
|
||||
Promoted Lists are a nice feature if you are away from your computer or performing more longer tasks.
|
||||
you can define a list of words which you want to hear a sound icon for after a period of inactivity.
|
||||
Example if the word "Chrys" appears after 120 Seconds of inactivity:
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=Chrys
|
||||
See section [[#Promote|Promote]] in ''settings.conf'' for more information.
|
||||
==== Punctuation ====
|
||||
Fenrir handles punctuation levels and names for you with several provided dictionaries.
|
||||
|
||||
@@ -867,9 +858,9 @@ Values: ''0.0'' is quietest, ''1.0'' is loudest.
|
||||
The generic sound driver uses shell commands for play sound and frequencies.
|
||||
|
||||
''genericPlayFileCommand'' defines the command that is used to play a sound file.
|
||||
genericPlayFileCommand=<your command for playing a file>
|
||||
generic_play_file_command=<your command for playing a file>
|
||||
''genericFrequencyCommand'' defines the command that is used playing frequencies.
|
||||
genericFrequencyCommand=<your command for playing a frequence>
|
||||
generic_frequency_command=<your command for playing a frequence>
|
||||
|
||||
The following variables are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'':
|
||||
* ''fenrirVolume'' = the current volume setting
|
||||
@@ -878,9 +869,9 @@ The following variables are substituted in ''genericPlayFileCommand'' and ''gene
|
||||
* ''fenrirDuration'' = the duration of the frequency
|
||||
|
||||
Example genericPlayFileCommand (default)
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
Example genericFrequencyCommand (default)
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
==== Speech ====
|
||||
Speech is configured in section ''[speech]''.
|
||||
Turn speech on or off:
|
||||
@@ -910,7 +901,7 @@ Pitch controls the pitch of the voice.
|
||||
Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest.
|
||||
|
||||
A Pitch for capital letters can be set.
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest.
|
||||
|
||||
The Volume controls the loudness of the voice.
|
||||
@@ -931,7 +922,7 @@ Select the language you want Fenrir to use.
|
||||
Values: Text, see your TTS synths documentation what is available.
|
||||
|
||||
Read new text as it occurs
|
||||
autoReadIncoming=True
|
||||
auto_read_incoming=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
=== Generic Driver ===
|
||||
@@ -948,16 +939,16 @@ The following variables are substituted in ''genericSpeechCommand'':
|
||||
* ''fenrirRate'' = is replaced with the current speed (speech rate)
|
||||
|
||||
Example genericSpeechCommand (default):
|
||||
genericSpeechCommand=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"
|
||||
generic_speech_command=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"
|
||||
|
||||
These are the minimum and maximum values of the TTS system used in genericSpeechCommand. They are needed to calculate the abstract range in volume, rate and pitch 0.0 - 1.0.
|
||||
|
||||
FenrirMinVolume=0
|
||||
fenrirMaxVolume=200
|
||||
fenrirMinPitch=0
|
||||
fenrirMaxPitch=99
|
||||
fenrirMinRate=80
|
||||
fenrirMaxRate=450
|
||||
fenrir_max_volume=200
|
||||
fenrir_min_pitch=0
|
||||
fenrir_max_pitch=99
|
||||
fenrir_min_rate=80
|
||||
fenrir_max_rate=450
|
||||
|
||||
The current volume, pitch and rate is calculated like this
|
||||
value = min + [volume,pitch,rate] * (min - max )
|
||||
@@ -1033,7 +1024,7 @@ The encoding of the screen
|
||||
Values:''cp850'' is used for Western languages like USA or Europe.
|
||||
|
||||
The driver updates Fenrir with changes on the screen.
|
||||
screenUpdateDelay=0.05
|
||||
screen_update_delay=0.05
|
||||
Values: in Seconds
|
||||
|
||||
If you want Fenrir to not be active on any screen for various reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with:
|
||||
@@ -1064,15 +1055,15 @@ Values:
|
||||
* ''<Device Name>'' just use the device with the given name.
|
||||
|
||||
Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to intercept Fenrir related shortcuts.
|
||||
grabDevices=True
|
||||
grab_devices=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The following makes sense if you are using a second screenreader and want to have some hooked events. Fenrir ignores all shortcuts then.
|
||||
ignoreShortcuts=False
|
||||
ignore_shortcuts=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The current keyboard layout used for shortcuts.
|
||||
keyboardLayout=desktop
|
||||
keyboard_layout=desktop
|
||||
Values: An absolute Path to a Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard''
|
||||
|
||||
Announce characters while typing.
|
||||
@@ -1080,23 +1071,23 @@ Announce characters while typing.
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Announce deleted characters
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Announce word after pressing space
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Interrupt speech on any keypress
|
||||
interruptOnKeyPress=False
|
||||
interrupt_on_key_press=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
You can filter the keys that speech should interrupt
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
|
||||
The timeout that is used for double tap shortcuts
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
Values: Seconds
|
||||
==== General ====
|
||||
Overall settings can be configured from the section ''[general]''.
|
||||
@@ -1106,19 +1097,19 @@ Set the current debug level:
|
||||
Values: off=0, error=1, warning=2, info=3
|
||||
|
||||
the current punctuation and dict file in use:
|
||||
punctuationProfile=default
|
||||
punctuation_profile=default
|
||||
Values: Text, see available profiles in ''/etc/fenrir/punctuation'' or in ''sourceTree/config/punctuation''
|
||||
|
||||
The current punctuation level in use:
|
||||
punctuationLevel=some
|
||||
punctuation_level=some
|
||||
Values: Text, See available levels in the used punctuation file.
|
||||
|
||||
Respect pause for punctuations:
|
||||
respectPunctuationPause=True
|
||||
respect_punctuation_pause=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Add a pause on Line break:
|
||||
newLinePause=True
|
||||
new_line_pause=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Specify the path where the clipboard should be exported to.
|
||||
@@ -1128,7 +1119,7 @@ The variable ''$user'' is replaced by the current logged username.
|
||||
Values: Text, Systemfilepath
|
||||
|
||||
The number of available clipboards:
|
||||
numberOfClipboards=10
|
||||
number_of_clipboards=10
|
||||
Values: Integer, 1 - 999
|
||||
|
||||
Replace emoticons like :) or ;) with text insertions:
|
||||
@@ -1136,7 +1127,7 @@ Replace emoticons like :) or ;) with text insertions:
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Define the current Fenrir keys:
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
Values, Text list, separated by comma.
|
||||
|
||||
Define the current script keys:
|
||||
@@ -1152,11 +1143,11 @@ The date format to be used for (date command) output:
|
||||
Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]]
|
||||
|
||||
Enable or Disable spellcheck whilst typing:
|
||||
autoSpellCheck=True
|
||||
auto_spell_check=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The use of the dictionary with spellcheck:
|
||||
spellCheckLanguage=en_US
|
||||
spell_check_language=en_US
|
||||
Values: Text, see aspell dictionary's.
|
||||
|
||||
Folder Path for your scripts "scriptKey" functionality:
|
||||
@@ -1197,25 +1188,8 @@ Leave the review mode when pressing a key:
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Leave the review mode when changing the screen (From TTY3 to TTY4):
|
||||
leaveReviewOnScreenChange=True
|
||||
leave_review_on_screen_change=True
|
||||
Values: on=''True'', off=''False''
|
||||
==== Promote ====
|
||||
"Promoted Lists" are configured in the section ''[promote]''.
|
||||
Turn Promoted Lists" on or off:
|
||||
enabled=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The minimum time interval of inactivity to activate promoting.
|
||||
By default it promotes after 120 Seconds inactivity:
|
||||
inactiveTimeoutSec=120
|
||||
Values: in Seconds
|
||||
|
||||
Define a list of promoted words comma seperated:
|
||||
list=
|
||||
Values: text (comma seperated)
|
||||
Example to promote the word "nickname" or a bash prompt:
|
||||
list=nickname,$:,#:
|
||||
|
||||
==== Time ====
|
||||
The automated time announcement is configured in the section ''[time]''.
|
||||
Time announcement is disabled by default.
|
||||
@@ -1270,7 +1244,7 @@ File: ''/usr/share/fenrirscreenreader/scripts/helloWorld__-__key_h.sh'':
|
||||
===== Commands =====
|
||||
You can place your own commands in "/usr/share/fenrirscreenreader/commands" (path is configurable in settings.conf).
|
||||
Commands are python files with a special scheme. You can assign them to a shortcut using the filename without an extension or place them in a hook trigger like OnInput or OnScreenChange. For further information see developer guide.
|
||||
Good Examples: [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py|"date.py"]] (announce the Date), [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output)
|
||||
Good Examples: [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/date.py|"date.py"]] (announce the Date), [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output)
|
||||
the basic scheme for a command is as follows:
|
||||
|
||||
from core import debug
|
||||
@@ -1289,7 +1263,7 @@ the basic scheme for a command is as follows:
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
* [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py|Template lives here]]
|
||||
* [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/command_template.py|Template lives here]]
|
||||
* The class needs to have the name "command".
|
||||
* "initialize" is running once whilst loading the command.
|
||||
* "shutdown" is running on unload like the command (quit fenrir)
|
||||
@@ -1319,7 +1293,7 @@ the basic scheme for a command is as follows:
|
||||
- You can test if speech-dispatcher works by invoking it as root\\ ''sudo spd-say "hello world"''
|
||||
===== Bugreports and feature requests =====
|
||||
Please report Bugs and feature requests to:
|
||||
[[https://github.com/chrys87/fenrir/issues|https://github.com/chrys87/fenrir/issues]]
|
||||
[[https://git.stormux.org/storm/fenrir/issues|https://git.stormux.org/storm/fenrir/issues]]
|
||||
|
||||
for bugs please provide a [[#Howto create a debug file|debug]] file that shows the issue.
|
||||
==== How-to create a debug file ====
|
||||
|
||||
@@ -56,7 +56,7 @@ To test Fenrir:
|
||||
sudo fenrir
|
||||
|
||||
To have Fenrir start on system boot using systemd:
|
||||
download service file: https://raw.githubusercontent.com/chrys87/fenrir/master/autostart/systemd/Arch/fenrir.service
|
||||
download service file: https://git.stormux.org/storm/fenrir/raw/branch/master/autostart/systemd/Arch/fenrir.service
|
||||
move the service file to: /etc/systemd/system/fenrir.service
|
||||
sudo systemctl enable fenrir
|
||||
|
||||
|
||||
69
pytest.ini
Normal file
69
pytest.ini
Normal file
@@ -0,0 +1,69 @@
|
||||
[pytest]
|
||||
# Pytest configuration for Fenrir screen reader
|
||||
|
||||
# Test discovery patterns
|
||||
python_files = test_*.py *_test.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Test paths
|
||||
testpaths = tests
|
||||
|
||||
# Minimum Python version
|
||||
minversion = 3.7
|
||||
|
||||
# Output options
|
||||
addopts =
|
||||
# Verbose output with test names
|
||||
-v
|
||||
# Show extra test summary info
|
||||
-ra
|
||||
# Enable strict markers (only registered markers allowed)
|
||||
--strict-markers
|
||||
# Show local variables in tracebacks
|
||||
--showlocals
|
||||
# Warnings configuration
|
||||
-W ignore::DeprecationWarning
|
||||
# Optional plugins (uncomment if installed):
|
||||
# --timeout=30 # Requires pytest-timeout
|
||||
# --cov-report=term-missing # Requires pytest-cov
|
||||
# -x # Stop on first failure
|
||||
|
||||
# Register custom markers
|
||||
markers =
|
||||
unit: Unit tests (fast, no mocking)
|
||||
integration: Integration tests (require mocking)
|
||||
driver: Driver tests (require root access)
|
||||
slow: Tests that take more than 1 second
|
||||
remote: Tests for remote control functionality
|
||||
settings: Tests for settings and configuration
|
||||
commands: Tests for command system
|
||||
vmenu: Tests for VMenu system
|
||||
|
||||
# Coverage configuration
|
||||
[coverage:run]
|
||||
source = src/fenrirscreenreader
|
||||
omit =
|
||||
*/tests/*
|
||||
*/vmenu-profiles/*
|
||||
*/__pycache__/*
|
||||
*/site-packages/*
|
||||
|
||||
[coverage:report]
|
||||
# Fail if coverage falls below this percentage
|
||||
# fail_under = 70
|
||||
exclude_lines =
|
||||
# Standard pragma
|
||||
pragma: no cover
|
||||
# Don't complain about missing debug code
|
||||
def __repr__
|
||||
# Don't complain if tests don't hit defensive assertion code
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
# Don't complain about abstract methods
|
||||
@abstractmethod
|
||||
# Don't complain about initialization
|
||||
if __name__ == .__main__.:
|
||||
|
||||
[coverage:html]
|
||||
directory = htmlcov
|
||||
@@ -1,4 +1,5 @@
|
||||
daemonize
|
||||
dbus-python
|
||||
evdev
|
||||
pexpect
|
||||
pyenchant
|
||||
|
||||
2
setup.py
2
setup.py
@@ -37,7 +37,7 @@ for directory in directories:
|
||||
if not forceSettingsFlag:
|
||||
try:
|
||||
files = [f for f in files if not f.endswith('settings.conf')]
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
elif 'config/scripts' in directory:
|
||||
destDir = '/usr/share/fenrirscreenreader/scripts'
|
||||
|
||||
64
src/fenrir
64
src/fenrir
@@ -4,19 +4,22 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import argparse
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import inspect
|
||||
import argparse
|
||||
|
||||
from daemonize import Daemonize
|
||||
|
||||
from fenrirscreenreader import fenrirVersion
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
|
||||
# Get the fenrir installation path
|
||||
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
if not fenrirPath in sys.path:
|
||||
fenrirPath = os.path.dirname(os.path.realpath(
|
||||
os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
if fenrirPath not in sys.path:
|
||||
sys.path.append(fenrirPath)
|
||||
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
from fenrirscreenreader import fenrirVersion
|
||||
|
||||
def create_argument_parser():
|
||||
"""Create and return the argument parser for Fenrir"""
|
||||
@@ -27,7 +30,7 @@ def create_argument_parser():
|
||||
argumentParser.add_argument(
|
||||
'-v', '--version',
|
||||
action='version',
|
||||
version=f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}',
|
||||
version=f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.code_name}',
|
||||
help='Show version information and exit'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
@@ -67,31 +70,65 @@ def create_argument_parser():
|
||||
action='store_true',
|
||||
help='Use PTY emulation with evdev for input (single instance)'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-F',
|
||||
'--force-all-screens',
|
||||
action='store_true',
|
||||
help='Force Fenrir to respond on all screens, ignoring ignoreScreen setting')
|
||||
argumentParser.add_argument(
|
||||
'-i', '-I', '--ignore-screen',
|
||||
metavar='SCREEN',
|
||||
action='append',
|
||||
help='Ignore specific screen(s). Can be used multiple times. Same as ignoreScreen setting.'
|
||||
)
|
||||
return argumentParser
|
||||
|
||||
|
||||
def validate_arguments(cliArgs):
|
||||
"""Validate command line arguments"""
|
||||
if cliArgs.options:
|
||||
for option in cliArgs.options.split(';'):
|
||||
if option and ('#' not in option or '=' not in option):
|
||||
return False, f"Invalid option format: {option}\nExpected format: SECTION#SETTING=VALUE"
|
||||
|
||||
|
||||
if cliArgs.emulated_pty and cliArgs.emulated_evdev:
|
||||
return False, "Cannot use both --emulated-pty and --emulated-evdev simultaneously"
|
||||
|
||||
|
||||
return True, None
|
||||
|
||||
|
||||
def run_fenrir():
|
||||
"""Main function that runs Fenrir"""
|
||||
fenrirApp = fenrirManager.fenrirManager(cliArgs)
|
||||
fenrirApp.proceed()
|
||||
del fenrirApp
|
||||
fenrirApp = None
|
||||
try:
|
||||
fenrirApp = fenrirManager.FenrirManager(cliArgs)
|
||||
fenrirApp.proceed()
|
||||
except Exception as e:
|
||||
print(f"Error starting Fenrir: {e}", file=sys.stderr)
|
||||
if fenrirApp and hasattr(fenrirApp, 'cleanup_on_error'):
|
||||
try:
|
||||
fenrirApp.cleanup_on_error()
|
||||
except Exception as cleanup_error:
|
||||
print(
|
||||
f"Error during cleanup: {cleanup_error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if fenrirApp:
|
||||
del fenrirApp
|
||||
# Clean up PID file if it exists
|
||||
pidFile = "/run/fenrir.pid"
|
||||
if os.path.exists(pidFile):
|
||||
try:
|
||||
os.remove(pidFile)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
global cliArgs
|
||||
argumentParser = create_argument_parser()
|
||||
cliArgs = argumentParser.parse_args()
|
||||
|
||||
|
||||
# Validate arguments
|
||||
isValid, errorMsg = validate_arguments(cliArgs)
|
||||
if not isValid:
|
||||
@@ -112,5 +149,6 @@ def main():
|
||||
)
|
||||
daemonProcess.start()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -2,20 +2,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No description found'
|
||||
|
||||
def get_description(self):
|
||||
return "No description found"
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
def setCallback(self, callback):
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,25 +2,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
# this command is just to initialize stuff.
|
||||
# like init index lists in memoryManager
|
||||
# like init index lists in MemoryManager
|
||||
# it is not useful to execute it
|
||||
class command():
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
# clipboard
|
||||
self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards'))
|
||||
self.env["runtime"]["MemoryManager"].add_index_list(
|
||||
"clipboardHistory",
|
||||
self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "number_of_clipboards"
|
||||
),
|
||||
)
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No description found'
|
||||
|
||||
def get_description(self):
|
||||
return "No description found"
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
def setCallback(self, callback):
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,53 +2,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import word_utils
|
||||
import string
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import word_utils
|
||||
|
||||
initialized = False
|
||||
try:
|
||||
import enchant
|
||||
|
||||
initialized = True
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
class command():
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
self.language = ''
|
||||
self.language = ""
|
||||
self.spellChecker = None
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.updateSpellLanguage()
|
||||
self.update_spell_language()
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('adds the current word to the exceptions dictionary')
|
||||
def updateSpellLanguage(self):
|
||||
self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage'))
|
||||
self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')
|
||||
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("adds the current word to the exceptions dictionary")
|
||||
|
||||
def update_spell_language(self):
|
||||
self.spellChecker = enchant.Dict(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
)
|
||||
self.language = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
if not initialized:
|
||||
return
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language:
|
||||
return
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
!= self.language
|
||||
):
|
||||
try:
|
||||
self.updateSpellLanguage()
|
||||
self.update_spell_language()
|
||||
except Exception as e:
|
||||
return
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
return
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
# get the word
|
||||
newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']]
|
||||
x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent)
|
||||
currWord = currWord.strip(string.whitespace + r'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~')
|
||||
new_content = self.env["screen"]["new_content_text"].split("\n")[
|
||||
cursor_pos["y"]
|
||||
]
|
||||
x, y, curr_word, end_of_screen, line_break = (
|
||||
word_utils.get_current_word(cursor_pos["x"], 0, new_content)
|
||||
)
|
||||
curr_word = curr_word.strip(
|
||||
string.whitespace + r'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~'
|
||||
)
|
||||
|
||||
if currWord != '':
|
||||
if self.spellChecker.is_added(currWord):
|
||||
self.env['runtime']['outputManager'].presentText(_('{0} is already in dictionary').format(currWord,), soundIcon='Cancel', interrupt=True)
|
||||
if curr_word != "":
|
||||
if self.spellChecker.is_added(curr_word):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("{0} is already in dictionary").format(
|
||||
curr_word,
|
||||
),
|
||||
sound_icon="Cancel",
|
||||
interrupt=True,
|
||||
)
|
||||
else:
|
||||
self.spellChecker.add(currWord)
|
||||
self.env['runtime']['outputManager'].presentText(_('{0} added to dictionary').format(currWord,), soundIcon='Accept', interrupt=True)
|
||||
self.spellChecker.add(curr_word)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("{0} added to dictionary").format(
|
||||
curr_word,
|
||||
),
|
||||
sound_icon="Accept",
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
108
src/fenrirscreenreader/commands/commands/adjustment_base.py
Normal file
108
src/fenrirscreenreader/commands/commands/adjustment_base.py
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import math
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class adjustment_command:
|
||||
"""Base class for speech and sound adjustment commands"""
|
||||
|
||||
def __init__(self, section, setting, direction, step=0.1):
|
||||
self.section = section # 'speech' or 'sound'
|
||||
self.setting = setting # 'rate', 'pitch', 'volume'
|
||||
self.direction = direction # 'inc' or 'dec'
|
||||
self.step = step
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
action = "Increase" if self.direction == "inc" else "Decrease"
|
||||
if self.section == "speech":
|
||||
return _(f"{action} the speech {self.setting}")
|
||||
else:
|
||||
return _(f"{action} the {self.section} {self.setting}")
|
||||
|
||||
def run(self):
|
||||
if self.section == "sound" and self.setting == "volume":
|
||||
# Sound volume uses different method
|
||||
self._adjust_sound_volume()
|
||||
else:
|
||||
# Speech rate, pitch, volume use standard method
|
||||
self._adjust_speech_setting()
|
||||
|
||||
def _adjust_speech_setting(self):
|
||||
"""Adjust speech settings (rate, pitch, volume)"""
|
||||
value = self.env["runtime"]["SettingsManager"].get_setting_as_float(
|
||||
self.section, self.setting
|
||||
)
|
||||
|
||||
# Apply adjustment with rounding
|
||||
if self.direction == "inc":
|
||||
value = round((math.ceil(10 * value) / 10) + self.step, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
else: # dec
|
||||
value = round((math.ceil(10 * value) / 10) - self.step, 2)
|
||||
if value < 0.0:
|
||||
value = 0.0
|
||||
|
||||
# Set the new value
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
self.section, self.setting, str(value)
|
||||
)
|
||||
|
||||
# Present feedback
|
||||
percentage = int(value * 100)
|
||||
if self.section == "speech":
|
||||
feedback = _("{0} percent speech {1}").format(
|
||||
percentage, self.setting
|
||||
)
|
||||
else:
|
||||
feedback = _("{0} percent {1} {2}").format(
|
||||
percentage, self.section, self.setting
|
||||
)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
feedback, sound_icon="", interrupt=True
|
||||
)
|
||||
|
||||
def _adjust_sound_volume(self):
|
||||
"""Adjust sound volume using same logic as speech"""
|
||||
value = self.env["runtime"]["SettingsManager"].get_setting_as_float(
|
||||
self.section, self.setting
|
||||
)
|
||||
|
||||
# Sound volume uses same math as speech settings
|
||||
if self.direction == "inc":
|
||||
value = round((math.ceil(10 * value) / 10) + self.step, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
else: # dec
|
||||
value = round((math.ceil(10 * value) / 10) - self.step, 2)
|
||||
if value < 0.0:
|
||||
value = 0.0
|
||||
|
||||
# Set the new value
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
self.section, self.setting, str(value)
|
||||
)
|
||||
|
||||
# Present feedback with appropriate sound icon
|
||||
percentage = int(value * 100)
|
||||
sound_icon = "SoundOn" if self.direction == "inc" else "SoundOff"
|
||||
feedback = _("{0} percent sound volume").format(percentage)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
feedback, sound_icon=sound_icon, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -2,26 +2,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader import fenrirVersion
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Present the version of Fenrir currrrently in use.')
|
||||
|
||||
|
||||
def get_description(self):
|
||||
return _("Present the version of Fenrir currently in use.")
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.env['runtime']['outputManager'].presentText(f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}', interrupt=True)
|
||||
except exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(_('Version information is unavailable.'), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Fenrir screen reader version "
|
||||
f"{fenrirVersion.version}-{fenrirVersion.code_name}",
|
||||
interrupt=True,
|
||||
)
|
||||
except Exception as e:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Version information is unavailable."), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return "Apply the last tested voice from safe voice browser"
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# Check if we have a tested voice
|
||||
if (
|
||||
"commandBuffer" not in self.env
|
||||
or "lastTestedModule" not in self.env["commandBuffer"]
|
||||
or "lastTestedVoice" not in self.env["commandBuffer"]
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"No voice has been tested yet", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Use voice browser first", interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
module = self.env["commandBuffer"]["lastTestedModule"]
|
||||
voice = self.env["commandBuffer"]["lastTestedVoice"]
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Applying {voice} from {module}", interrupt=True
|
||||
)
|
||||
|
||||
# Apply to runtime settings only (temporary until saved)
|
||||
SettingsManager = self.env["runtime"]["SettingsManager"]
|
||||
|
||||
# Store old values for safety
|
||||
old_driver = SettingsManager.get_setting("speech", "driver")
|
||||
old_module = SettingsManager.get_setting("speech", "module")
|
||||
old_voice = SettingsManager.get_setting("speech", "voice")
|
||||
|
||||
try:
|
||||
# Apply new settings to runtime only (use set_setting to update
|
||||
# settingArgDict)
|
||||
SettingsManager.set_setting(
|
||||
"speech", "driver", "speechdDriver"
|
||||
)
|
||||
SettingsManager.set_setting("speech", "module", module)
|
||||
SettingsManager.set_setting("speech", "voice", voice)
|
||||
|
||||
# Apply to speech driver instance directly
|
||||
if "SpeechDriver" in self.env["runtime"]:
|
||||
SpeechDriver = self.env["runtime"]["SpeechDriver"]
|
||||
|
||||
# Set the module and voice on the driver instance
|
||||
SpeechDriver.set_module(module)
|
||||
SpeechDriver.set_voice(voice)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Voice applied successfully!", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Use save settings to make permanent", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].play_sound("Accept")
|
||||
|
||||
except Exception as e:
|
||||
# Revert on failure
|
||||
SettingsManager.set_setting("speech", "driver", old_driver)
|
||||
SettingsManager.set_setting("speech", "module", old_module)
|
||||
SettingsManager.set_setting("speech", "voice", old_voice)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Failed to apply voice, reverted: {str(e)}",
|
||||
interrupt=True,
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].play_sound("Error")
|
||||
|
||||
except Exception as e:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Apply voice error: {str(e)}", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].play_sound("Error")
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -2,29 +2,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import screen_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Reads attributes of current cursor position')
|
||||
|
||||
def get_description(self):
|
||||
return _("Reads attributes of current cursor position")
|
||||
|
||||
def run(self):
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
try:
|
||||
attributes = self.env['runtime']['attributeManager'].getAttributeByXY( cursorPos['x'], cursorPos['y'])
|
||||
attributes = self.env["runtime"][
|
||||
"AttributeManager"
|
||||
].get_attribute_by_xy(cursor_pos["x"], cursor_pos["y"])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString')
|
||||
attributeFormatString = self.env['runtime']['attributeManager'].formatAttributes(attributes, attributeFormatString)
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(attributeFormatString, soundIcon='', interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
print(e)
|
||||
attribute_format_string = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "attribute_format_string")
|
||||
attribute_format_string = self.env["runtime"][
|
||||
"AttributeManager"
|
||||
].format_attributes(attributes, attribute_format_string)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
attribute_format_string, sound_icon="", interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '1'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(1, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '10'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(10, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '2'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(2, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '3'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(3, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '4'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(4, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '5'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(5, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '6'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(6, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '7'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(7, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '8'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(8, "read")
|
||||
|
||||
@@ -2,47 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '9'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True)
|
||||
return
|
||||
|
||||
# set marks
|
||||
marked = ''
|
||||
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy()
|
||||
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']:
|
||||
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
|
||||
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText'])
|
||||
else:
|
||||
x, y, marked = \
|
||||
line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText'])
|
||||
if marked.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(marked, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(9, "read")
|
||||
|
||||
211
src/fenrirscreenreader/commands/commands/bookmark_base.py
Normal file
211
src/fenrirscreenreader/commands/commands/bookmark_base.py
Normal file
@@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
|
||||
|
||||
class bookmark_command:
|
||||
"""Base class for bookmark operations - read, set, clear"""
|
||||
|
||||
def __init__(self, bookmark_id, action="read"):
|
||||
self.ID = str(bookmark_id)
|
||||
self.action = action
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
# Always initialize bookmark structure - all commands need this
|
||||
if self.ID not in self.env["commandBuffer"]["bookMarks"]:
|
||||
self.env["commandBuffer"]["bookMarks"][self.ID] = {}
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
if self.action == "read":
|
||||
return _("read Bookmark {0}").format(self.ID)
|
||||
elif self.action == "set":
|
||||
return _("set Bookmark {0}").format(self.ID)
|
||||
elif self.action == "clear":
|
||||
return _("remove Bookmark {0}").format(self.ID)
|
||||
return f"{self.action} Bookmark {self.ID}"
|
||||
|
||||
def run(self):
|
||||
if self.action == "read":
|
||||
self._read_bookmark()
|
||||
elif self.action == "set":
|
||||
self._set_bookmark()
|
||||
elif self.action == "clear":
|
||||
self._clear_bookmark()
|
||||
|
||||
def _read_bookmark(self):
|
||||
curr_app = self.env["runtime"][
|
||||
"ApplicationManager"
|
||||
].get_current_application()
|
||||
|
||||
if not self.env["commandBuffer"]["bookMarks"][self.ID]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Bookmark {0} not set".format(self.ID), interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
if curr_app not in self.env["commandBuffer"]["bookMarks"][self.ID]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Bookmark for application {0} not set".format(curr_app),
|
||||
interrupt=True,
|
||||
)
|
||||
return
|
||||
|
||||
if not self.env["commandBuffer"]["bookMarks"][self.ID][curr_app].get(
|
||||
"1"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Bookmark for application {0} not set".format(curr_app),
|
||||
interrupt=True,
|
||||
)
|
||||
return
|
||||
|
||||
# Get bookmarked text
|
||||
marked = ""
|
||||
start_mark = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app][
|
||||
"1"
|
||||
].copy()
|
||||
|
||||
if self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]["2"]:
|
||||
end_mark = self.env["commandBuffer"]["bookMarks"][self.ID][
|
||||
curr_app
|
||||
]["2"].copy()
|
||||
marked = mark_utils.get_text_between_marks(
|
||||
start_mark, end_mark, self.env["screen"]["new_content_text"]
|
||||
)
|
||||
else:
|
||||
x, y, marked = line_utils.get_current_line(
|
||||
start_mark["x"],
|
||||
start_mark["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
|
||||
if marked.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
marked, interrupt=True
|
||||
)
|
||||
|
||||
def _set_bookmark(self):
|
||||
if not self.env["commandBuffer"]["Marks"]["1"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("No mark found"), interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
curr_app = self.env["runtime"][
|
||||
"ApplicationManager"
|
||||
].get_current_application()
|
||||
self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] = {}
|
||||
|
||||
bookmarks = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
|
||||
bookmarks["1"] = self.env["commandBuffer"]["Marks"]["1"].copy()
|
||||
|
||||
if self.env["commandBuffer"]["Marks"]["2"]:
|
||||
bookmarks["2"] = self.env["commandBuffer"]["Marks"]["2"].copy()
|
||||
else:
|
||||
bookmarks["2"] = None
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Bookmark {0} set for application {1}").format(
|
||||
self.ID, curr_app
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
# Clear marks after setting bookmark
|
||||
self.env["commandBuffer"]["Marks"]["1"] = None
|
||||
self.env["commandBuffer"]["Marks"]["2"] = None
|
||||
|
||||
def _clear_bookmark(self):
|
||||
curr_app = self.env["runtime"][
|
||||
"ApplicationManager"
|
||||
].get_current_application()
|
||||
|
||||
bookmarks = self.env["commandBuffer"]["bookMarks"]
|
||||
if self.ID in bookmarks and curr_app in bookmarks[self.ID]:
|
||||
del self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Bookmark {0} removed for application {1}").format(
|
||||
self.ID, curr_app
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Bookmark {0} not set for application {1}").format(
|
||||
self.ID, curr_app
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
|
||||
# Factory function to create bookmark command instances
|
||||
|
||||
|
||||
def create_bookmark_commands():
|
||||
"""Create all bookmark command instances"""
|
||||
commands = {}
|
||||
|
||||
# Create read bookmark commands (bookmark_1 through bookmark_10)
|
||||
for i in range(1, 11):
|
||||
commands[f"bookmark_{i}"] = lambda i=i: bookmark_command(i, "read")
|
||||
|
||||
# Create set bookmark commands (set_bookmark_1 through set_bookmark_10)
|
||||
for i in range(1, 11):
|
||||
commands[f"set_bookmark_{i}"] = lambda i=i: bookmark_command(i, "set")
|
||||
|
||||
# Create clear bookmark commands (clear_bookmark_1 through
|
||||
# clear_bookmark_10)
|
||||
for i in range(1, 11):
|
||||
commands[f"clear_bookmark_{i}"] = lambda i=i: bookmark_command(
|
||||
i, "clear"
|
||||
)
|
||||
|
||||
return commands
|
||||
|
||||
|
||||
# For backwards compatibility, provide individual command classes
|
||||
# This allows the existing command loading system to work unchanged
|
||||
|
||||
|
||||
def _make_command_class(bookmark_id, action):
|
||||
"""Create a command class for a specific bookmark and action"""
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
super().__init__(bookmark_id, action)
|
||||
|
||||
return command
|
||||
|
||||
|
||||
# Generate individual command classes for each bookmark operation
|
||||
# These will be used by the existing command loading system
|
||||
|
||||
|
||||
# Read bookmarks (bookmark_1.py style)
|
||||
for i in range(1, 11):
|
||||
globals()[f"bookmark_{i}_command"] = _make_command_class(i, "read")
|
||||
|
||||
# Set bookmarks (set_bookmark_1.py style)
|
||||
for i in range(1, 11):
|
||||
globals()[f"set_bookmark_{i}_command"] = _make_command_class(i, "set")
|
||||
|
||||
# Clear bookmarks (clear_bookmark_1.py style)
|
||||
for i in range(1, 11):
|
||||
globals()[f"clear_bookmark_{i}_command"] = _make_command_class(i, "clear")
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '1'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(1, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '10'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(10, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '2'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(2, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '3'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(3, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '4'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(4, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '5'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(5, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '6'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(6, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '7'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(7, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '8'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(8, "clear")
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
bookmark_command = _module.bookmark_command
|
||||
|
||||
|
||||
class command(bookmark_command):
|
||||
def __init__(self):
|
||||
self.ID = '9'
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('remove Bookmark {0}').format(self.ID,)
|
||||
|
||||
def run(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
|
||||
del self.env['commandBuffer']['bookMarks'][self.ID][currApp]
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__(9, "clear")
|
||||
|
||||
@@ -2,23 +2,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('clears the currently selected clipboard')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("clears the currently selected clipboard")
|
||||
|
||||
def run(self):
|
||||
self.env['runtime']['memoryManager'].clearCurrentIndexList('clipboardHistory')
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard cleared'), interrupt=True)
|
||||
return
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["MemoryManager"].clear_current_index_list(
|
||||
"clipboardHistory"
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard cleared"), interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,26 +2,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Turn off window mode for application')
|
||||
|
||||
def run(self):
|
||||
if self.env['runtime']['cursorManager'].clearWindowForApplication():
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
self.env['runtime']['outputManager'].presentText(_('Window Mode off for application {0}').format(currApp,), interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(_("Not in window Mode"), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Turn off window mode for application")
|
||||
|
||||
def run(self):
|
||||
if self.env["runtime"]["CursorManager"].clear_window_for_application():
|
||||
curr_app = self.env["runtime"][
|
||||
"ApplicationManager"
|
||||
].get_current_application()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Window Mode off for application {0}").format(
|
||||
curr_app,
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Not in window Mode"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,27 +2,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('copies last presented text to the clipboard')
|
||||
|
||||
def run(self):
|
||||
lastEcho = self.env['runtime']['outputManager'].getLastEcho()
|
||||
if lastEcho.rstrip() != "":
|
||||
lastEcho = lastEcho.rstrip()
|
||||
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', lastEcho)
|
||||
self.env['runtime']['outputManager'].presentText(lastEcho, soundIcon='CopyToClipboard', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("copies last presented text to the clipboard")
|
||||
|
||||
def run(self):
|
||||
last_echo = self.env["runtime"]["OutputManager"].get_last_echo()
|
||||
if last_echo.rstrip() != "":
|
||||
last_echo = last_echo.rstrip()
|
||||
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
|
||||
"clipboardHistory", last_echo
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
last_echo, sound_icon="CopyToClipboard", interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,73 +2,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
class command():
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def getDescription(self):
|
||||
return _('copies marked text to the currently selected clipboard')
|
||||
|
||||
def getTextFromScreen(self, startMark, endMark):
|
||||
screenContent = self.env['screen']['newContentText']
|
||||
screenLines = screenContent.split('\n')
|
||||
|
||||
startY = min(startMark['y'], len(screenLines) - 1)
|
||||
endY = min(endMark['y'], len(screenLines) - 1)
|
||||
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("copies marked text to the currently selected clipboard")
|
||||
|
||||
def get_text_from_screen(self, start_mark, end_mark):
|
||||
screen_content = self.env["screen"]["new_content_text"]
|
||||
screen_lines = screen_content.split("\n")
|
||||
|
||||
start_y = min(start_mark["y"], len(screen_lines) - 1)
|
||||
end_y = min(end_mark["y"], len(screen_lines) - 1)
|
||||
|
||||
# If marks are on the same line
|
||||
if startY == endY:
|
||||
line = screenLines[startY]
|
||||
startX = min(startMark['x'], len(line))
|
||||
endX = min(endMark['x'], len(line)) + 1
|
||||
return line[startX:endX]
|
||||
|
||||
if start_y == end_y:
|
||||
line = screen_lines[start_y]
|
||||
start_x = min(start_mark["x"], len(line))
|
||||
end_x = min(end_mark["x"], len(line)) + 1
|
||||
return line[start_x:end_x]
|
||||
|
||||
# Handle multi-line selection
|
||||
result = []
|
||||
|
||||
|
||||
# First line (from start mark to end of line)
|
||||
firstLine = screenLines[startY]
|
||||
startX = min(startMark['x'], len(firstLine))
|
||||
result.append(firstLine[startX:].rstrip())
|
||||
|
||||
first_line = screen_lines[start_y]
|
||||
start_x = min(start_mark["x"], len(first_line))
|
||||
result.append(first_line[start_x:].rstrip())
|
||||
|
||||
# Middle lines (complete lines)
|
||||
for lineNum in range(startY + 1, endY):
|
||||
result.append(screenLines[lineNum].rstrip())
|
||||
|
||||
for lineNum in range(start_y + 1, end_y):
|
||||
result.append(screen_lines[lineNum].rstrip())
|
||||
|
||||
# Last line (from start to end mark)
|
||||
if endY > startY:
|
||||
lastLine = screenLines[endY]
|
||||
endX = min(endMark['x'], len(lastLine)) + 1
|
||||
result.append(lastLine[:endX].rstrip())
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
if end_y > start_y:
|
||||
last_line = screen_lines[end_y]
|
||||
end_x = min(end_mark["x"], len(last_line)) + 1
|
||||
result.append(last_line[:end_x].rstrip())
|
||||
|
||||
return "\n".join(result)
|
||||
|
||||
def run(self):
|
||||
if not self.env['commandBuffer']['Marks']['1']:
|
||||
self.env['runtime']['outputManager'].presentText(_("One or two marks are needed"), interrupt=True)
|
||||
if not self.env["commandBuffer"]["Marks"]["1"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("One or two marks are needed"), interrupt=True
|
||||
)
|
||||
return
|
||||
if not self.env['commandBuffer']['Marks']['2']:
|
||||
self.env['runtime']['cursorManager'].setMark()
|
||||
|
||||
if not self.env["commandBuffer"]["Marks"]["2"]:
|
||||
self.env["runtime"]["CursorManager"].set_mark()
|
||||
|
||||
# use the last first and the last setted mark as range
|
||||
startMark = self.env['commandBuffer']['Marks']['1'].copy()
|
||||
endMark = self.env['commandBuffer']['Marks']['2'].copy()
|
||||
|
||||
# Replace mark_utils.getTextBetweenMarks with our new method
|
||||
marked = self.getTextFromScreen(startMark, endMark)
|
||||
|
||||
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', marked)
|
||||
start_mark = self.env["commandBuffer"]["Marks"]["1"].copy()
|
||||
end_mark = self.env["commandBuffer"]["Marks"]["2"].copy()
|
||||
|
||||
# Replace mark_utils.get_text_between_marks with our new method
|
||||
marked = self.get_text_from_screen(start_mark, end_mark)
|
||||
|
||||
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
|
||||
"clipboardHistory", marked
|
||||
)
|
||||
# reset marks
|
||||
self.env['runtime']['cursorManager'].clearMarks()
|
||||
self.env['runtime']['outputManager'].presentText(marked, soundIcon='CopyToClipboard', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["CursorManager"].clear_marks()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
marked, sound_icon="CopyToClipboard", interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,26 +2,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('speaks the contents of the currently selected clipboard')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("speaks the contents of the currently selected clipboard")
|
||||
|
||||
def run(self):
|
||||
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
|
||||
return
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
self.env['runtime']['outputManager'].presentText(clipboard , interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
if self.env["runtime"]["MemoryManager"].is_index_list_empty(
|
||||
"clipboardHistory"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard empty"), interrupt=True
|
||||
)
|
||||
return
|
||||
clipboard = self.env["runtime"][
|
||||
"MemoryManager"
|
||||
].get_index_list_element("clipboardHistory")
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
clipboard, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,25 +2,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('reads the contents of the current screen')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("reads the contents of the current screen")
|
||||
|
||||
def run(self):
|
||||
if self.env['screen']['newContentText'].isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("screen is empty"), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'],interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
if self.env["screen"]["new_content_text"].isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("screen is empty"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
self.env["screen"]["new_content_text"], interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,31 +2,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('reads from the cursor to the bottom of the screen')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("reads from the cursor to the bottom of the screen")
|
||||
|
||||
def run(self):
|
||||
# Prefer review cursor over text cursor
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
|
||||
textAfterCursor = mark_utils.getTextAfterMark(cursorPos, self.env['screen']['newContentText'])
|
||||
text_after_cursor = mark_utils.get_text_after_mark(
|
||||
cursor_pos, self.env["screen"]["new_content_text"]
|
||||
)
|
||||
|
||||
if textAfterCursor.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
if text_after_cursor.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(textAfterCursor, interrupt=True)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
text_after_cursor, interrupt=True
|
||||
)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,35 +2,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Reads from the top of the screen to the cursor position')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Reads from the top of the screen to the cursor position")
|
||||
|
||||
def run(self):
|
||||
# Prefer review cursor over text cursor
|
||||
if self.env['screen']['newCursorReview']:
|
||||
cursorPos = self.env['screen']['newCursorReview'].copy()
|
||||
if self.env["screen"]["newCursorReview"]:
|
||||
cursor_pos = self.env["screen"]["newCursorReview"].copy()
|
||||
else:
|
||||
cursorPos = self.env['screen']['newCursor'].copy()
|
||||
cursor_pos = self.env["screen"]["new_cursor"].copy()
|
||||
|
||||
textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screen']['newContentText'])
|
||||
text_before_cursor = mark_utils.get_text_before_mark(
|
||||
cursor_pos, self.env["screen"]["new_content_text"]
|
||||
)
|
||||
|
||||
if textBeforeCursor.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
if text_before_cursor.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(textBeforeCursor, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
text_before_cursor, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
|
||||
@@ -2,25 +2,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('get current quick menu entry')
|
||||
def run(self):
|
||||
menu = ''
|
||||
value = ''
|
||||
menu = self.env['runtime']['quickMenuManager'].getCurrentEntry()
|
||||
if menu != '':
|
||||
value = self.env['runtime']['quickMenuManager'].getCurrentValue()
|
||||
self.env['runtime']['outputManager'].presentText(menu + ' ' + value, interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("get current quick menu entry")
|
||||
|
||||
def run(self):
|
||||
menu = ""
|
||||
value = ""
|
||||
menu = self.env["runtime"]["QuickMenuManager"].get_current_entry()
|
||||
if menu != "":
|
||||
value = self.env["runtime"]["QuickMenuManager"].get_current_value()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
menu + " " + value, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,21 +2,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('get current quick menu value')
|
||||
def run(self):
|
||||
value = self.env['runtime']['quickMenuManager'].getCurrentValue()
|
||||
self.env['runtime']['outputManager'].presentText(value, interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("get current quick menu value")
|
||||
|
||||
def run(self):
|
||||
value = self.env["runtime"]["QuickMenuManager"].get_current_value()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
value, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,24 +2,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Column number for cursor')
|
||||
|
||||
def get_description(self):
|
||||
return _("Column number for cursor")
|
||||
|
||||
def run(self):
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
self.env['runtime']['outputManager'].presentText(str(cursorPos['x'] + 1) , interrupt=True)
|
||||
self.env['runtime']['outputManager'].announceActiveCursor()
|
||||
self.env['runtime']['outputManager'].presentText(' column number' , interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
str(cursor_pos["x"] + 1), interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].announce_active_cursor()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
" column number", interrupt=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,24 +2,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Line number for cursor')
|
||||
|
||||
def get_description(self):
|
||||
return _("Line number for cursor")
|
||||
|
||||
def run(self):
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
self.env['runtime']['outputManager'].presentText(str(cursorPos['y'] + 1), interrupt=True)
|
||||
self.env['runtime']['outputManager'].announceActiveCursor()
|
||||
self.env['runtime']['outputManager'].presentText(' line number' , interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
str(cursor_pos["y"] + 1), interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].announce_active_cursor()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
" line number", interrupt=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,25 +2,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('displays the position of the review cursor')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("displays the position of the review cursor")
|
||||
|
||||
def run(self):
|
||||
# Prefer review cursor over text cursor
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("line {0}, column {1}, Terminal {2}").format(cursorPos['y']+1, cursorPos['x']+1, self.env['screen']['newTTY']), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("line {0}, column {1}, Terminal {2}").format(
|
||||
cursor_pos["y"] + 1,
|
||||
cursor_pos["x"] + 1,
|
||||
self.env["screen"]["newTTY"],
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,32 +2,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read line to cursor pos, use review cursor if you are in review mode, otherwhise use text cursor')
|
||||
|
||||
def run(self):
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
|
||||
x, y, currLine = \
|
||||
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
|
||||
|
||||
if currLine.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(currLine[:cursorPos['x']], interrupt=True)
|
||||
self.env['runtime']['outputManager'].announceActiveCursor()
|
||||
def setCallback(self, callback):
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _(
|
||||
"read line to cursor pos, use review cursor if you are in review mode, "
|
||||
"otherwhise use text cursor"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
|
||||
x, y, curr_line = line_utils.get_current_line(
|
||||
cursor_pos["x"],
|
||||
cursor_pos["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
|
||||
if curr_line.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_line[: cursor_pos["x"]], interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].announce_active_cursor()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,32 +2,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('read to end of line, use review cursor if you are in review mode, otherwhise use text cursor')
|
||||
|
||||
def run(self):
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
|
||||
x, y, currLine = \
|
||||
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
|
||||
|
||||
if currLine.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(currLine[cursorPos['x']:], interrupt=True)
|
||||
self.env['runtime']['outputManager'].announceActiveCursor()
|
||||
def setCallback(self, callback):
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _(
|
||||
"read to end of line, use review cursor if you are in review mode, "
|
||||
"otherwhise use text cursor"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
cursor_pos = self.env["runtime"][
|
||||
"CursorManager"
|
||||
].get_review_or_text_cursor()
|
||||
|
||||
x, y, curr_line = line_utils.get_current_line(
|
||||
cursor_pos["x"],
|
||||
cursor_pos["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
|
||||
if curr_line.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_line[cursor_pos["x"] :], interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].announce_active_cursor()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
57
src/fenrirscreenreader/commands/commands/cycle_key_echo.py
Normal file
57
src/fenrirscreenreader/commands/commands/cycle_key_echo.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Cycle through key echo modes: character, word, off")
|
||||
|
||||
def run(self):
|
||||
settings_manager = self.env["runtime"]["SettingsManager"]
|
||||
output_manager = self.env["runtime"]["OutputManager"]
|
||||
|
||||
# Get current settings
|
||||
char_echo_mode = settings_manager.get_setting("keyboard", "char_echo_mode")
|
||||
word_echo = settings_manager.get_setting_as_bool("keyboard", "word_echo")
|
||||
|
||||
# Determine current state and cycle to next
|
||||
# States: character (char=1, word=False) -> word (char=0, word=True) -> off (char=0, word=False)
|
||||
if char_echo_mode == "1" and not word_echo:
|
||||
# Currently character echo, switch to word echo
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "0")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "True")
|
||||
output_manager.present_text(
|
||||
_("Echo by word"), interrupt=True
|
||||
)
|
||||
elif word_echo:
|
||||
# Currently word echo, switch to off
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "0")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "False")
|
||||
output_manager.present_text(
|
||||
_("Echo off"), interrupt=True
|
||||
)
|
||||
else:
|
||||
# Currently off (or caps mode), switch to character echo
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "1")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "False")
|
||||
output_manager.present_text(
|
||||
_("Echo by character"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import os
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("cycles between available keyboard layouts")
|
||||
|
||||
def get_available_layouts(self):
|
||||
"""Get list of available keyboard layout files"""
|
||||
layouts = []
|
||||
|
||||
# Check standard locations for keyboard layouts
|
||||
settings_root = "/etc/fenrirscreenreader/"
|
||||
if not os.path.exists(settings_root):
|
||||
# Fallback to source directory
|
||||
import fenrirscreenreader
|
||||
|
||||
fenrir_path = os.path.dirname(fenrirscreenreader.__file__)
|
||||
settings_root = fenrir_path + "/../../config/"
|
||||
|
||||
keyboard_path = settings_root + "keyboard/"
|
||||
|
||||
if os.path.exists(keyboard_path):
|
||||
for file in os.listdir(keyboard_path):
|
||||
if (
|
||||
file.endswith(".conf")
|
||||
and not file.startswith("__")
|
||||
and not file.lower().startswith("pty")
|
||||
):
|
||||
layout_name = file.replace(".conf", "")
|
||||
if layout_name not in layouts:
|
||||
layouts.append(layout_name)
|
||||
|
||||
# Ensure we have at least basic layouts
|
||||
if not layouts:
|
||||
layouts = ["desktop", "laptop"]
|
||||
else:
|
||||
layouts.sort()
|
||||
|
||||
return layouts
|
||||
|
||||
def run(self):
|
||||
current_layout = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"keyboard", "keyboard_layout"
|
||||
)
|
||||
|
||||
# Extract layout name from full path if needed
|
||||
if "/" in current_layout:
|
||||
current_layout = os.path.basename(current_layout).replace(
|
||||
".conf", ""
|
||||
)
|
||||
|
||||
# Get available layouts
|
||||
available_layouts = self.get_available_layouts()
|
||||
|
||||
# Find next layout in cycle
|
||||
try:
|
||||
current_index = available_layouts.index(current_layout)
|
||||
next_index = (current_index + 1) % len(available_layouts)
|
||||
except ValueError:
|
||||
# If current layout not found, start from beginning
|
||||
next_index = 0
|
||||
|
||||
next_layout = available_layouts[next_index]
|
||||
|
||||
# Update setting and reload shortcuts
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"keyboard", "keyboard_layout", next_layout
|
||||
)
|
||||
|
||||
# Reload shortcuts with new layout
|
||||
try:
|
||||
self.env["runtime"]["InputManager"].reload_shortcuts()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Switched to {} keyboard layout").format(next_layout),
|
||||
interrupt=True,
|
||||
)
|
||||
except Exception as e:
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"Error reloading shortcuts: " + str(e), debug.DebugLevel.ERROR
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Error switching keyboard layout"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -2,29 +2,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import datetime
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('presents the date')
|
||||
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("presents the date")
|
||||
|
||||
def run(self):
|
||||
dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat')
|
||||
date_format = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "date_format"
|
||||
)
|
||||
|
||||
# get the time formatted
|
||||
dateString = datetime.datetime.strftime(datetime.datetime.now(), dateFormat)
|
||||
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
|
||||
self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=True)
|
||||
# present the time via speak and braile, there is no soundicon,
|
||||
# interrupt the current speech
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
date_string, sound_icon="", interrupt=True
|
||||
)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
initialized = False
|
||||
try:
|
||||
import alsaaudio
|
||||
initialized = True
|
||||
except:
|
||||
pass
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _("Decrease system volume")
|
||||
|
||||
def run(self):
|
||||
if not initialized:
|
||||
self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True)
|
||||
return
|
||||
mixer = alsaaudio.Mixer()
|
||||
value = mixer.getvolume()[0]
|
||||
value = value - 5
|
||||
if value < 5:
|
||||
value = 5
|
||||
mixer.setvolume(value)
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -2,32 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('decrease sound volume')
|
||||
|
||||
def run(self):
|
||||
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')
|
||||
|
||||
value = round((math.ceil(10 * value) / 10) - 0.1, 2)
|
||||
if value < 0.1:
|
||||
value = 0.1
|
||||
self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOff', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
super().__init__("sound", "volume", "dec")
|
||||
|
||||
@@ -2,28 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Decreases the pitch of the speech')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch')
|
||||
value = round((math.ceil(10 * value) / 10) - 0.1, 2)
|
||||
if value < 0.0:
|
||||
value = 0.0
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value))
|
||||
self.env['runtime']['outputManager'].presentText(_('{0} percent speech pitch').format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("speech", "pitch", "dec")
|
||||
|
||||
@@ -2,29 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Decreases the rate of the speech')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate')
|
||||
value = round((math.ceil(10 * value) / 10) - 0.1, 2)
|
||||
if value < 0.0:
|
||||
value = 0.0
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("speech", "rate", "dec")
|
||||
|
||||
@@ -2,30 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Decreases the volume of the speech')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume')
|
||||
value = round((math.ceil(10 * value) / 10) - 0.1, 2)
|
||||
if value < 0.1:
|
||||
value = 0.1
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
super().__init__("speech", "volume", "dec")
|
||||
|
||||
@@ -2,27 +2,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('exits review mode')
|
||||
|
||||
def run(self):
|
||||
if not self.env['runtime']['cursorManager'].isReviewMode():
|
||||
self.env['runtime']['outputManager'].presentText(_("Not in Review Mode"), interrupt=True)
|
||||
return
|
||||
|
||||
self.env['runtime']['cursorManager'].clearReviewCursor()
|
||||
self.env['runtime']['outputManager'].presentText(_("Exiting Review Mode"), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("exits review mode")
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["CursorManager"].is_review_mode():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Not in Review Mode"), interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
self.env["runtime"]["CursorManager"].clear_review_cursor()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Exiting Review Mode"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,38 +2,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment, scriptPath=''):
|
||||
|
||||
def initialize(self, environment, script_path=""):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('export the current fenrir clipboard to a file')
|
||||
def run(self):
|
||||
clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath')
|
||||
clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser'])
|
||||
clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser'])
|
||||
clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser'])
|
||||
clipboardFile = open(clipboardFilePath,'w')
|
||||
|
||||
def get_description(self):
|
||||
return _("export the current fenrir clipboard to a file")
|
||||
|
||||
def run(self):
|
||||
clipboard_file_path = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "clipboard_export_path")
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$user", self.env["general"]["curr_user"]
|
||||
)
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$USER", self.env["general"]["curr_user"]
|
||||
)
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$User", self.env["general"]["curr_user"]
|
||||
)
|
||||
clipboard_file = open(clipboard_file_path, "w")
|
||||
try:
|
||||
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
|
||||
return
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
clipboardFile.write(clipboard)
|
||||
clipboardFile.close()
|
||||
os.chmod(clipboardFilePath, 0o666)
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True)
|
||||
if self.env["runtime"]["MemoryManager"].is_index_list_empty(
|
||||
"clipboardHistory"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard empty"), interrupt=True
|
||||
)
|
||||
return
|
||||
clipboard = self.env["runtime"][
|
||||
"MemoryManager"
|
||||
].get_index_list_element("clipboardHistory")
|
||||
clipboard_file.write(clipboard)
|
||||
clipboard_file.close()
|
||||
os.chmod(clipboard_file_path, 0o644)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard exported to file"), interrupt=True
|
||||
)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"export_clipboard_to_file:run: Filepath:"
|
||||
+ clipboard_file
|
||||
+ " trace:"
|
||||
+ str(e),
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,70 +2,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import os
|
||||
import importlib
|
||||
import _thread
|
||||
import importlib
|
||||
import os
|
||||
|
||||
import pyperclip
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment, scriptPath=''):
|
||||
|
||||
def initialize(self, environment, script_path=""):
|
||||
self.env = environment
|
||||
self.scriptPath = scriptPath
|
||||
self.script_path = script_path
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Export current fenrir clipboard to X or GUI clipboard')
|
||||
def run(self):
|
||||
_thread.start_new_thread(self._threadRun , ())
|
||||
def _threadRun(self):
|
||||
|
||||
def get_description(self):
|
||||
return _("Export current fenrir clipboard to X or GUI clipboard")
|
||||
|
||||
def run(self):
|
||||
_thread.start_new_thread(self._thread_run, ())
|
||||
|
||||
def _thread_run(self):
|
||||
try:
|
||||
# Check if clipboard is empty
|
||||
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
|
||||
if self.env["runtime"]["MemoryManager"].is_index_list_empty(
|
||||
"clipboardHistory"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard empty"), interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
# Get current clipboard content
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
|
||||
clipboard = self.env["runtime"][
|
||||
"MemoryManager"
|
||||
].get_index_list_element("clipboardHistory")
|
||||
|
||||
# Remember original display environment variable if it exists
|
||||
originalDisplay = os.environ.get('DISPLAY', '')
|
||||
original_display = os.environ.get("DISPLAY", "")
|
||||
success = False
|
||||
|
||||
|
||||
# Try different display options
|
||||
for i in range(10):
|
||||
display = f":{i}"
|
||||
try:
|
||||
# Set display environment variable
|
||||
os.environ['DISPLAY'] = display
|
||||
os.environ["DISPLAY"] = display
|
||||
# Attempt to set clipboard content
|
||||
importlib.reload(pyperclip) # Weird workaround for some distros
|
||||
# Weird workaround for some distros
|
||||
importlib.reload(pyperclip)
|
||||
pyperclip.copy(clipboard)
|
||||
# If we get here without exception, we found a working display
|
||||
# If we get here without exception, we found a working
|
||||
# display
|
||||
success = True
|
||||
break
|
||||
except Exception:
|
||||
# Failed for this display, try next one
|
||||
continue
|
||||
|
||||
|
||||
# Restore original display setting
|
||||
if originalDisplay:
|
||||
os.environ['DISPLAY'] = originalDisplay
|
||||
if original_display:
|
||||
os.environ["DISPLAY"] = original_display
|
||||
else:
|
||||
os.environ.pop('DISPLAY', None)
|
||||
|
||||
os.environ.pop("DISPLAY", None)
|
||||
|
||||
# Notify the user of the result
|
||||
if success:
|
||||
self.env['runtime']['outputManager'].presentText(_('exported to the X session.'), interrupt=True)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("exported to the X session."), interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(_('failed to export to X clipboard. No available display found.'), interrupt=True)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_(
|
||||
"failed to export to X clipboard. No available display "
|
||||
"found."
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
str(e), sound_icon="", interrupt=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,27 +2,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('selects the first clipboard')
|
||||
|
||||
def run(self):
|
||||
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
|
||||
return
|
||||
self.env['runtime']['memoryManager'].setFirstIndex('clipboardHistory')
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("selects the first clipboard")
|
||||
|
||||
def run(self):
|
||||
if self.env["runtime"]["MemoryManager"].is_index_list_empty(
|
||||
"clipboardHistory"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard empty"), interrupt=True
|
||||
)
|
||||
return
|
||||
self.env["runtime"]["MemoryManager"].set_first_index(
|
||||
"clipboardHistory"
|
||||
)
|
||||
clipboard = self.env["runtime"][
|
||||
"MemoryManager"
|
||||
].get_index_list_element("clipboardHistory")
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
clipboard, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,23 +2,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('sends the following keypress to the terminal or application')
|
||||
|
||||
def run(self):
|
||||
self.env['input']['keyForeward'] = 3
|
||||
self.env['runtime']['outputManager'].presentText(_('Forward next keypress'), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("sends the following keypress to the terminal or application")
|
||||
|
||||
def run(self):
|
||||
self.env["input"]["key_forward"] = 3
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Forward next keypress"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,38 +2,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import mark_utils
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('imports text from clipboard file to the clipboard')
|
||||
|
||||
def run(self):
|
||||
clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath')
|
||||
clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser'])
|
||||
clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser'])
|
||||
clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser'])
|
||||
if not os.path.exists(clipboardFilePath):
|
||||
self.env['runtime']['outputManager'].presentText(_('File does not exist'), soundIcon='', interrupt=True)
|
||||
return
|
||||
clipboardFile = open(clipboardFilePath,'r')
|
||||
imported = clipboardFile.read()
|
||||
clipboardFile.close()
|
||||
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', imported)
|
||||
|
||||
self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True)
|
||||
self.env['runtime']['outputManager'].presentText(imported, soundIcon='', interrupt=False)
|
||||
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("imports text from clipboard file to the clipboard")
|
||||
|
||||
def run(self):
|
||||
clipboard_file_path = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "clipboard_export_path")
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$user", self.env["general"]["curr_user"]
|
||||
)
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$USER", self.env["general"]["curr_user"]
|
||||
)
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$User", self.env["general"]["curr_user"]
|
||||
)
|
||||
if not os.path.exists(clipboard_file_path):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("File does not exist"), sound_icon="", interrupt=True
|
||||
)
|
||||
return
|
||||
clipboard_file = open(clipboard_file_path, "r")
|
||||
imported = clipboard_file.read()
|
||||
clipboard_file.close()
|
||||
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
|
||||
"clipboardHistory", imported
|
||||
)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Import to Clipboard", sound_icon="CopyToClipboard", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
imported, sound_icon="", interrupt=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,63 +2,86 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import importlib
|
||||
import _thread
|
||||
import pyperclip
|
||||
import importlib
|
||||
import os
|
||||
|
||||
class command():
|
||||
import pyperclip
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment, scriptPath=''):
|
||||
|
||||
def initialize(self, environment, script_path=""):
|
||||
self.env = environment
|
||||
self.scriptPath = scriptPath
|
||||
self.script_path = script_path
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
|
||||
def get_description(self):
|
||||
return _("imports the graphical clipboard to Fenrir's clipboard")
|
||||
def run(self):
|
||||
_thread.start_new_thread(self._threadRun , ())
|
||||
def _threadRun(self):
|
||||
|
||||
def run(self):
|
||||
_thread.start_new_thread(self._thread_run, ())
|
||||
|
||||
def _thread_run(self):
|
||||
try:
|
||||
# Remember original display environment variable if it exists
|
||||
originalDisplay = os.environ.get('DISPLAY', '')
|
||||
clipboardContent = None
|
||||
|
||||
original_display = os.environ.get("DISPLAY", "")
|
||||
clipboard_content = None
|
||||
|
||||
# Try different display options
|
||||
for i in range(10):
|
||||
display = f":{i}"
|
||||
try:
|
||||
# Set display environment variable
|
||||
os.environ['DISPLAY'] = display
|
||||
os.environ["DISPLAY"] = display
|
||||
# Attempt to get clipboard content
|
||||
importlib.reload(pyperclip) # Weird workaround for some distros
|
||||
clipboardContent = pyperclip.paste()
|
||||
# If we get here without exception, we found a working display
|
||||
if clipboardContent:
|
||||
# Weird workaround for some distros
|
||||
importlib.reload(pyperclip)
|
||||
clipboard_content = pyperclip.paste()
|
||||
# If we get here without exception, we found a working
|
||||
# display
|
||||
if clipboard_content:
|
||||
break
|
||||
except Exception:
|
||||
# Failed for this display, try next one
|
||||
continue
|
||||
|
||||
|
||||
# Restore original display setting
|
||||
if originalDisplay:
|
||||
os.environ['DISPLAY'] = originalDisplay
|
||||
if original_display:
|
||||
os.environ["DISPLAY"] = original_display
|
||||
else:
|
||||
os.environ.pop('DISPLAY', None)
|
||||
|
||||
os.environ.pop("DISPLAY", None)
|
||||
|
||||
# Process the clipboard content if we found any
|
||||
if clipboardContent and isinstance(clipboardContent, str):
|
||||
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', clipboardContent)
|
||||
self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True)
|
||||
self.env['runtime']['outputManager'].presentText(clipboardContent, soundIcon='', interrupt=False)
|
||||
if clipboard_content and isinstance(clipboard_content, str):
|
||||
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
|
||||
"clipboardHistory", clipboard_content
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Import to Clipboard",
|
||||
sound_icon="CopyToClipboard",
|
||||
interrupt=True,
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
clipboard_content, sound_icon="", interrupt=False
|
||||
)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText('No text found in clipboard or no accessible display', interrupt=True)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"No text found in clipboard or no accessible display",
|
||||
interrupt=True,
|
||||
)
|
||||
except Exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
str(e), sound_icon="", interrupt=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
initialized = False
|
||||
try:
|
||||
import alsaaudio
|
||||
initialized = True
|
||||
except:
|
||||
pass
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _("Increase system volume")
|
||||
|
||||
def run(self):
|
||||
if not initialized:
|
||||
self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True)
|
||||
return
|
||||
mixer = alsaaudio.Mixer()
|
||||
value = mixer.getvolume()[0]
|
||||
value = value + 5
|
||||
if value > 100:
|
||||
value = 100
|
||||
mixer.setvolume(value)
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -2,31 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('adjusts the volume for in coming sounds')
|
||||
|
||||
def run(self):
|
||||
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')
|
||||
|
||||
value = round((math.ceil(10 * value) / 10) + 0.1, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOn', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("sound", "volume", "inc")
|
||||
|
||||
@@ -2,29 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Increases the pitch of the speech')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch')
|
||||
value = round((math.ceil(10 * value) / 10) + 0.1, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent speech pitch").format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("speech", "pitch", "inc")
|
||||
|
||||
@@ -2,29 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Increase the speech rate')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate')
|
||||
value = round((math.ceil(10 * value) / 10) + 0.1, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("speech", "rate", "inc")
|
||||
|
||||
@@ -2,29 +2,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import math
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Increase the speech volume')
|
||||
|
||||
def run(self):
|
||||
value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume')
|
||||
value = round((math.ceil(10 * value) / 10) + 0.1, 2)
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value))
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
super().__init__("speech", "volume", "inc")
|
||||
|
||||
@@ -2,35 +2,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
|
||||
class command():
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Presents the indentation level for the current line')
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Presents the indentation level for the current line")
|
||||
|
||||
def run(self):
|
||||
# Prefer review cursor over text cursor
|
||||
|
||||
if self.env['screen']['newCursorReview']:
|
||||
cursorPos = self.env['screen']['newCursorReview'].copy()
|
||||
if self.env["screen"]["newCursorReview"]:
|
||||
cursor_pos = self.env["screen"]["newCursorReview"].copy()
|
||||
else:
|
||||
cursorPos = self.env['screen']['newCursor'].copy()
|
||||
x, y, currLine = \
|
||||
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
|
||||
|
||||
if currLine.isspace():
|
||||
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(_("indent {0}").format(len(currLine) - len(currLine.lstrip())), interrupt=True)
|
||||
cursor_pos = self.env["screen"]["new_cursor"].copy()
|
||||
x, y, curr_line = line_utils.get_current_line(
|
||||
cursor_pos["x"],
|
||||
cursor_pos["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
|
||||
def setCallback(self, callback):
|
||||
if curr_line.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("indent {0}").format(
|
||||
len(curr_line) - len(curr_line.lstrip())
|
||||
),
|
||||
interrupt=True,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -2,27 +2,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('selects the last clipboard')
|
||||
|
||||
def run(self):
|
||||
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
|
||||
return
|
||||
self.env['runtime']['memoryManager'].setLastIndex('clipboardHistory')
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("selects the last clipboard")
|
||||
|
||||
def run(self):
|
||||
if self.env["runtime"]["MemoryManager"].is_index_list_empty(
|
||||
"clipboardHistory"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("clipboard empty"), interrupt=True
|
||||
)
|
||||
return
|
||||
self.env["runtime"]["MemoryManager"].set_last_index("clipboardHistory")
|
||||
clipboard = self.env["runtime"][
|
||||
"MemoryManager"
|
||||
].get_index_list_element("clipboardHistory")
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
clipboard, interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user