26 Commits

Author SHA1 Message Date
Storm Dragon
7bbc45bda2 Worked on updating installation files, e.g. install.sh, requirements.txt, and setup.py. Maybe broken, proceed with caution. 2025-06-16 01:24:06 -04:00
Storm Dragon
d81d563bb6 Add page up and page down to move through the voice browser by 10%. 2025-06-16 01:08:05 -04:00
Storm Dragon
43871cea3c Fixes to the voice driver. It should actually work completely now. 2025-06-15 19:52:18 -04:00
Storm Dragon
72bd334d65 Very experimental attempt to move the configure_fenrir script into fenrir itself using the vmenu system. Lots of testing please. 2025-06-15 14:04:14 -04:00
Storm Dragon
e76b914d6e Ignore screen 7 by default in case auto ignore screen doesn't work. 2025-06-12 18:43:12 -04:00
Storm Dragon
83cb330d34 Potential fixes to progress bar. Better handling of punctuation while reading. 2025-06-10 18:10:08 -04:00
Storm Dragon
b0ac6e1409 improved documentation for the diff generation. 2025-06-09 16:53:05 -04:00
Storm Dragon
6998706934 Testing fixes for security improvement, thread safety, and memory management. 2025-06-09 14:41:33 -04:00
Storm Dragon
62e1001679 Add keybinding for progress bar monitoring for laptop mode. Fenrir+Shift+P. 2025-06-09 13:11:51 -04:00
Storm Dragon
d935ef2e3c The fix for hopefully not reading all spaces broke review by character. Hopefully fix that. 2025-06-09 12:48:02 -04:00
Storm Dragon
e2fb28d92f Attempt to fix the bug where fenrir sometimes reads all the spaces in a message. 2025-06-09 02:33:36 -04:00
Storm Dragon
8a223282df Some modifications to progress bar detection, can revert if needed. 2025-06-09 02:19:39 -04:00
Storm Dragon
91c97dd1dd Fixed error in settings file, Time and date need %% instead of just a single %. 2025-06-08 18:04:06 -04:00
Storm Dragon
5cc719a6f3 Commit 2 of 2, code refactor and cleanup. 2025-06-08 14:26:24 -04:00
Storm Dragon
ddc1b43304 Commit 1 of 2, code refactor and cleanup. 2025-06-08 13:49:22 -04:00
Storm Dragon
6ad11effc6 Enhanced prompt detection 2025-06-08 13:31:37 -04:00
Storm Dragon
ca0e3b5987 Reverted changes to remot driver because some settings, e.g. highlight mode, stopped working. 2025-06-07 18:22:31 -04:00
Storm Dragon
0009d90a68 Updated .gitignore 2025-06-07 13:35:10 -04:00
Storm Dragon
2c2efc56f0 Progress beeps should now rok with dd's progress flag. 2025-06-07 13:23:45 -04:00
Storm Dragon
27c35939b1 A few minor tweaks to progressbar beeps. 2025-06-07 11:13:15 -04:00
Storm Dragon
7e87ebf04b Attempt to improve how Fenrir reads multiple characters in a row, e.g. [------]. 2025-06-07 10:51:02 -04:00
Storm Dragon
ec6c135581 Keybinding for silence until prompt returns added to laptop.conf. Fenrir+Shift+Enter 2025-06-07 10:20:09 -04:00
Storm Dragon
998c63cc71 Fixed a few typos in settings file, changed progressbars to true by default. 2025-06-07 01:48:58 -04:00
Storm Dragon
26c6e32c59 Add the ability to add custom prompts to the settings file, generic prompts are covered with the existing detection code. 2025-06-07 01:26:21 -04:00
Storm Dragon
97e2da614b 2 new features, silence speech until prompt returns and progress bar beeps. 2025-06-07 00:52:13 -04:00
Storm Dragon
0930a86ce7 --ignore-screen (-i) flag added. 2025-06-06 22:58:08 -04:00
342 changed files with 4161 additions and 3095 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ dist/
build/
*.kate-swp
.directory
CLAUDE.md

View File

@@ -511,6 +511,7 @@ fenrir [OPTIONS]
- `-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 ignoreScreen setting
- `-i, -I, --ignore-screen SCREEN` - Ignore specific screen(s). Can be used multiple times. Combines with existing ignore settings.
### Examples:
```bash
@@ -525,6 +526,10 @@ sudo fenrir -o "speech#rate=0.8;sound#volume=0.5"
# Force Fenrir to work on all screens (ignore ignoreScreen setting)
sudo fenrir -F
# Ignore specific screens
sudo fenrir --ignore-screen 1
sudo fenrir -i 1 -i 2 # Ignore screens 1 and 2
```
## Localization

View File

@@ -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
@@ -113,6 +114,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

View File

@@ -75,9 +75,11 @@ 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=silence_until_prompt
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_T=toggle_auto_time
@@ -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

View File

@@ -72,7 +72,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
#=toggle_braille
KEY_FENRIR,KEY_F3=toggle_sound
KEY_FENRIR,KEY_F4=toggle_speech

View File

@@ -28,6 +28,9 @@ genericPlayFileCommand=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
# Enable progress bar monitoring with ascending tones by default
progressMonitoring=True
[speech]
# Turn speech on or off:
enabled=True
@@ -92,7 +95,7 @@ fenrirMaxRate=450
driver=vcsaDriver
encoding=auto
screenUpdateDelay=0.05
ignoreScreen=
ignoreScreen=7
autodetectIgnoreScreen=True
[keyboard]
@@ -140,8 +143,8 @@ 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
timeFormat=%%I:%%M%%P
dateFormat=%%A, %%B %%d, %%Y
autoSpellCheck=True
spellCheckLanguage=en_US
# path for your scripts "scriptKeys" functionality
@@ -163,7 +166,7 @@ autoPresentIndent=False
# 1 = sound only
# 2 = speak only
autoPresentIndentMode=1
# play a sound when attributes are changeing
# play a sound when attributes change
hasAttributes=True
# shell for PTY emulatiun (empty = default shell)
shell=
@@ -211,8 +214,32 @@ list=
vmenuPath=
quickMenu=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]\].*
customPatterns=
# Specific prompt strings to match exactly (useful for very specific custom prompts)
# Format: exactMatches=prompt1,prompt2,prompt3
# Examples:
# exactMatches=[storm@fenrir ~] $,[root@fenrir ~] #,Continue installation? [Y/n]
exactMatches=
[time]
# automatic time anouncement
# automatic time announcement
enabled=False
# present time
presentTime=True

Binary file not shown.

Binary file not shown.

View File

@@ -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,9 +41,8 @@ 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'

View File

@@ -65,6 +65,10 @@ Use PTY emulation with evdev for input (single instance mode).
.BR \-F ", " \-\-force-all-screens
Force Fenrir to respond on all screens, ignoring the ignoreScreen setting. This temporarily overrides screen filtering for the current session.
.TP
.BR \-i ", " \-I ", " \-\-ignore-screen " \fISCREEN\fR"
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.
.SH KEY CONCEPTS
.SS Fenrir Key

View File

@@ -1240,6 +1240,9 @@ 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

View File

@@ -297,6 +297,7 @@ fenrir [OPTIONS]
- `-e, --emulated-pty` - PTY emulation for desktop use
- `-E, --emulated-evdev` - PTY + evdev emulation
- `-F, --force-all-screens` - Ignore ignoreScreen setting
- `-i, -I, --ignore-screen SCREEN` - Ignore specific screen(s), can be used multiple times
## Troubleshooting

View File

@@ -1,12 +1,141 @@
#!/usr/bin/env bash
#Basic install script for Fenrir.
read -rp "This will install Fenrir. Press ctrl+C to cancel, or enter to continue."
# Install script for Fenrir Screen Reader
set -e
# Check if running as root
if [[ $(whoami) != "root" ]]; then
echo "This script must be run as root"
exit 1
fi
# Check Python version
pythonVersion=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
requiredVersion="3.8"
if ! python3 -c "import sys; exit(0 if sys.version_info >= (3, 8) else 1)" 2>/dev/null; then
echo "Python ${requiredVersion} or higher is required. Current version: ${pythonVersion}"
exit 1
fi
echo "Fenrir Screen Reader Installation"
echo "=================================="
read -rp "This will install the Fenrir screen reader. Press Ctrl+C to cancel, or Enter to continue."
# Check for pip3
if ! command -v pip3 &> /dev/null; then
echo "pip3 is required but not installed. Please install pip3 first."
exit 1
fi
# Function to check dependencies
checkDependencies() {
echo "Checking dependencies..."
if python3 check-dependencies.py; then
return 0
else
return 1
fi
}
# Function to install dependencies with pip
installWithPip() {
echo "Installing Python dependencies with pip..."
pip3 install -r requirements.txt --break-system-packages
}
# Function to detect package manager and provide instructions
detectPackageManager() {
if command -v apt &> /dev/null; then
echo "apt"
elif command -v dnf &> /dev/null; then
echo "dnf"
elif command -v yum &> /dev/null; then
echo "yum"
elif command -v pacman &> /dev/null; then
echo "pacman"
elif command -v zypper &> /dev/null; then
echo "zypper"
else
echo "unknown"
fi
}
# Function to show package manager instructions
showPackageInstructions() {
local pm=$1
echo "Package manager installation instructions:"
case $pm in
"apt")
echo " sudo apt update"
echo " sudo apt install python3-evdev python3-daemonize python3-dbus python3-pyudev python3-pexpect"
echo " sudo apt install python3-pyte python3-setproctitle python3-enchant python3-xdg"
echo " sudo apt install speech-dispatcher espeak-ng sox alsa-utils"
;;
"dnf"|"yum")
echo " sudo $pm install python3-evdev python3-daemonize python3-dbus python3-pyudev python3-pexpect"
echo " sudo $pm install python3-pyte python3-setproctitle python3-enchant python3-pyxdg"
echo " sudo $pm install speech-dispatcher espeak-ng sox alsa-utils"
;;
"pacman")
echo " sudo pacman -S python-evdev python-daemonize python-dbus python-pyudev python-pexpect"
echo " sudo pacman -S python-pyte python-setproctitle python-pyenchant python-pyxdg"
echo " sudo pacman -S speech-dispatcher espeak-ng sox alsa-utils"
;;
"zypper")
echo " sudo zypper install python3-evdev python3-daemonize python3-dbus python3-pyudev python3-pexpect"
echo " sudo zypper install python3-pyte python3-setproctitle python3-enchant python3-pyxdg"
echo " sudo zypper install speech-dispatcher espeak-ng sox alsa-utils"
;;
*)
echo " Unknown package manager. Please install the dependencies manually."
echo " Required packages: evdev, daemonize, dbus-python, pyudev, pexpect, pyte, setproctitle"
echo " System packages: speech-dispatcher, espeak-ng, sox, alsa-utils"
;;
esac
}
# Initial dependency check
echo "Performing initial dependency check..."
if ! checkDependencies; then
echo ""
echo "Some dependencies are missing. You have two options:"
echo "1. Install using pip (not recommended uses --break-system-packages)"
echo "2. Install using your system package manager (recommended assuming I got the package names and package manager syntax right)"
echo ""
read -rp "Use pip to install Python dependencies? (y/N): " usePip
usePip="${usePip:0:1}"
if [[ "${usePip^}" == "Y" ]]; then
installWithPip
else
packageManager=$(detectPackageManager)
echo ""
showPackageInstructions "$packageManager"
echo ""
echo "Please install the packages above, then press Enter to continue..."
read -r
fi
# Check dependencies again
echo "Rechecking dependencies..."
if ! checkDependencies; then
echo "Some dependencies are still missing. Please install them manually."
echo "You can run 'python3 check-dependencies.py' to see which ones are missing."
exit 1
fi
fi
echo "All dependencies satisfied!"
# Install Fenrir application files
echo "Installing Fenrir application files..."
# Fenrir main application
install -m755 -d /opt/fenrirscreenreader
cp -af src/* /opt/fenrirscreenreader
ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir
# tools
install -m755 -d /usr/share/fenrirscreenreader/tools
cp -af tools/* /usr/share/fenrirscreenreader/tools
@@ -43,24 +172,49 @@ if [ -f "/etc/fenrirscreenreader/settings/settings.conf" ]; then
fi
else
install -m644 -D "config/settings/settings.conf" /etc/fenrirscreenreader/settings/settings.conf
fi
fi
# Install systemd service if systemd is available
if command -v systemctl &> /dev/null; then
echo "Installing systemd service..."
# Detect which service file to use
if [ -f "/etc/arch-release" ] || [ -f "/etc/manjaro-release" ]; then
serviceFile="autostart/systemd/Arch/fenrir.service"
else
serviceFile="autostart/systemd/Debian/fenrir.service"
fi
if [ -f "$serviceFile" ]; then
install -m644 "$serviceFile" /etc/systemd/system/fenrir.service
systemctl daemon-reload
echo "Systemd service installed. Enable with: sudo systemctl enable fenrir"
else
echo "Warning: Systemd service file not found: $serviceFile"
fi
else
echo "Warning: Systemd not detected. Manual service setup may be required."
fi
# end message
# Final message
cat << EOF
Installation complete.
install path:/opt/fenrirscreenreader
settings path:/etc/fenrirscreenreader
To test Fenrir:
sudo fenrir
Installation complete!
=============================
Install path: /opt/fenrirscreenreader
Settings path: /etc/fenrirscreenreader
To have Fenrir start on system boot using systemd:
download service file: https://raw.githubusercontent.com/chrys87/fenrir/master/autostart/systemd/Arch/fenrir.service
move the service file to: /etc/systemd/system/fenrir.service
sudo systemctl enable fenrir
Next steps:
1. Test Fenrir: sudo fenrir
2. Enable autostart: sudo systemctl enable fenrir
3. Configure audio (run both as user and root):
- PulseAudio: /usr/share/fenrirscreenreader/tools/configure_pulse.sh
- PipeWire: /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
Pulseaudio users may want to run
/usr/share/fenrirscreenreader/tools/configure_pulse.sh
once from their user account, then once from the root.
For help:
- Documentation: https://git.stormux.org/storm/fenrir
- Configuration: sudo fenrir --help
- Dependency check: python3 check-dependencies.py
Fenrir installation successful!
EOF

View File

@@ -1,9 +1,16 @@
daemonize
evdev
pexpect
pyenchant
pyperclip
pyte
pyudev
pyxdg
setproctitle
daemonize>=2.5.0
evdev>=1.4.0
dbus-python>=1.3.0
pyperclip>=1.8.0
pyudev>=0.24.0
pyte>=0.8.0
setproctitle>=1.3.0
setuptools>=65.0.0
pexpect>=4.8.0
# Optional dependencies for enhanced functionality:
# pyenchant>=3.2.0 # For spell checking commands
# pyxdg>=0.28 # For XDG base directory support
# PyGObject>=3.42.0 # For GStreamer sound driver
# pyatspi>=2.40.0 # For AT-SPI input driver
# speechd>=0.11.0 # For speech-dispatcher Python bindings

View File

@@ -94,17 +94,17 @@ setup(
data_files=dataFiles,
# Dependent packages (distributions)
python_requires='>=3.6',
python_requires='>=3.8',
install_requires=[
"evdev>=1.1.2",
"evdev>=1.4.0",
"daemonize>=2.5.0",
"dbus-python>=1.2.8",
"pyperclip",
"pyudev>=0.21.0",
"setuptools",
"setproctitle",
"pexpect",
"pyte>=0.7.0",
"dbus-python>=1.3.0",
"pyperclip>=1.8.0",
"pyudev>=0.24.0",
"setuptools>=65.0.0",
"setproctitle>=1.3.0",
"pexpect>=4.8.0",
"pyte>=0.8.0",
],
)
@@ -113,12 +113,12 @@ if not forceSettingsFlag:
# create settings file from example if not exist
if not os.path.isfile('/etc/fenrirscreenreader/settings/settings.conf'):
try:
copyfile('config/fenrirscreenreader/settings/settings.conf', '/etc/fenrirscreenreader/settings/settings.conf')
copyfile('config/settings/settings.conf', '/etc/fenrirscreenreader/settings/settings.conf')
print('create settings file in /etc/fenrirscreenreader/settings/settings.conf')
except OSError as e:
print(f"Could not copy settings file to destination: {e}")
else:
print('settings.conf file found. It is not overwritten automatical')
print('settings.conf file found. It is not overwritten automatically')
print('')
print('To have Fenrir start at boot:')

View File

@@ -72,6 +72,12 @@ def create_argument_parser():
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):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
# this command is just to initialize stuff.
# like init index lists in memoryManager

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import word_utils
import string
initialized = False

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import math
class AdjustmentCommand():
"""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 getDescription(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'].getSettingAsFloat(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'].setSetting(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'].presentText(feedback, soundIcon='', interrupt=True)
def _adjust_sound_volume(self):
"""Adjust sound volume using same logic as speech"""
value = self.env['runtime']['settingsManager'].getSettingAsFloat(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'].setSetting(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'].presentText(feedback, soundIcon=sound_icon, interrupt=True)
def setCallback(self, callback):
pass

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader import fenrirVersion
class command():

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def getDescription(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'].presentText("No voice has been tested yet", interrupt=True)
self.env['runtime']['outputManager'].presentText("Use voice browser first", interrupt=True)
return
module = self.env['commandBuffer']['lastTestedModule']
voice = self.env['commandBuffer']['lastTestedVoice']
self.env['runtime']['outputManager'].presentText(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
oldDriver = settingsManager.getSetting('speech', 'driver')
oldModule = settingsManager.getSetting('speech', 'module')
oldVoice = settingsManager.getSetting('speech', 'voice')
try:
# Apply new settings to runtime only (use setSetting to update settingArgDict)
settingsManager.setSetting('speech', 'driver', 'speechdDriver')
settingsManager.setSetting('speech', 'module', module)
settingsManager.setSetting('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.setModule(module)
speechDriver.setVoice(voice)
self.env['runtime']['outputManager'].presentText("Voice applied successfully!", interrupt=True)
self.env['runtime']['outputManager'].presentText("Use save settings to make permanent", interrupt=True)
self.env['runtime']['outputManager'].playSound('Accept')
except Exception as e:
# Revert on failure
settingsManager.setSetting('speech', 'driver', oldDriver)
settingsManager.setSetting('speech', 'module', oldModule)
settingsManager.setSetting('speech', 'voice', oldVoice)
self.env['runtime']['outputManager'].presentText(f"Failed to apply voice, reverted: {str(e)}", interrupt=True)
self.env['runtime']['outputManager'].playSound('Error')
except Exception as e:
self.env['runtime']['outputManager'].presentText(f"Apply voice error: {str(e)}", interrupt=True)
self.env['runtime']['outputManager'].playSound('Error')
def setCallback(self, callback):
pass

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import screen_utils
class command():

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,45 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -0,0 +1,150 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import gettext
_ = gettext.gettext
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils
class BookmarkCommand():
"""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 getDescription(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):
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 currApp not in self.env['commandBuffer']['bookMarks'][self.ID]:
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].get('1'):
self.env['runtime']['outputManager'].presentText('Bookmark for application {0} not set'.format(currApp), interrupt=True)
return
# Get bookmarked text
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 _set_bookmark(self):
if not self.env['commandBuffer']['Marks']['1']:
self.env['runtime']['outputManager'].presentText(_("No mark found"), interrupt=True)
return
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {}
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy()
if self.env['commandBuffer']['Marks']['2']:
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy()
else:
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True)
# Clear marks after setting bookmark
self.env['commandBuffer']['Marks']['1'] = None
self.env['commandBuffer']['Marks']['2'] = None
def _clear_bookmark(self):
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
if self.ID in self.env['commandBuffer']['bookMarks'] and currApp in self.env['commandBuffer']['bookMarks'][self.ID]:
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)
else:
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set for application {1}').format(self.ID, currApp), interrupt=True)
def setCallback(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: BookmarkCommand(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: BookmarkCommand(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: BookmarkCommand(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(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,24 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib.util
_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)
BookmarkCommand = _module.BookmarkCommand
class command():
class command(BookmarkCommand):
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')

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
class command():

View File

@@ -2,7 +2,6 @@
# -*- coding: utf-8 -*-
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import datetime
class command():

View File

@@ -4,36 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
initialized = False
try:
import alsaaudio
initialized = True
except:
pass
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
from fenrirscreenreader.core import debug
class command():
class command(AdjustmentCommand):
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
super().__init__('alsa', 'volume', 'dec')

View File

@@ -4,30 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,26 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,27 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,28 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib
import _thread

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
import os

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import importlib
import _thread
import pyperclip

View File

@@ -4,36 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
initialized = False
try:
import alsaaudio
initialized = True
except:
pass
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
from fenrirscreenreader.core import debug
class command():
class command(AdjustmentCommand):
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
super().__init__('alsa', 'volume', 'inc')

View File

@@ -4,29 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,27 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,27 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,27 +4,14 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import math
import os
import importlib.util
_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)
AdjustmentCommand = _module.AdjustmentCommand
class command():
class command(AdjustmentCommand):
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')

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import mark_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import time
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -0,0 +1,209 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import re
import time
import threading
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
# Use commandBuffer like other commands
if 'progressMonitoring' not in self.env['commandBuffer']:
# Check if progress monitoring should be enabled by default from settings
try:
defaultEnabled = self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'progressMonitoring')
except:
# If setting doesn't exist, default to False
defaultEnabled = False
self.env['commandBuffer']['progressMonitoring'] = defaultEnabled
self.env['commandBuffer']['lastProgressTime'] = 0
self.env['commandBuffer']['lastProgressValue'] = -1
def shutdown(self):
self.stopProgressMonitoring()
def getDescription(self):
return _('Toggle progress bar monitoring with ascending tones')
def run(self):
# Check if commandBuffer exists
if 'progressMonitoring' not in self.env['commandBuffer']:
self.env['commandBuffer']['progressMonitoring'] = False
self.env['commandBuffer']['lastProgressTime'] = 0
self.env['commandBuffer']['lastProgressValue'] = -1
if self.env['commandBuffer']['progressMonitoring']:
self.stopProgressMonitoring()
self.env['runtime']['outputManager'].presentText(_("Progress monitoring disabled"), interrupt=True)
else:
self.startProgressMonitoring()
self.env['runtime']['outputManager'].presentText(_("Progress monitoring enabled"), interrupt=True)
def startProgressMonitoring(self):
self.env['commandBuffer']['progressMonitoring'] = True
self.env['commandBuffer']['lastProgressTime'] = time.time()
self.env['commandBuffer']['lastProgressValue'] = -1
# Don't control speech - let user decide with silence_until_prompt
def stopProgressMonitoring(self):
self.env['commandBuffer']['progressMonitoring'] = False
# Don't control speech - progress monitor is beep-only
def detectProgress(self, text):
if not self.env['commandBuffer']['progressMonitoring']:
return
# Skip progress detection if current screen looks like a prompt
if self.isCurrentLinePrompt():
return
currentTime = time.time()
# Pattern 1: Percentage (50%, 25.5%, etc.)
percentMatch = re.search(r'(\d+(?:\.\d+)?)\s*%', text)
if percentMatch:
percentage = float(percentMatch.group(1))
if percentage != self.env['commandBuffer']['lastProgressValue']:
self.playProgressTone(percentage)
self.env['commandBuffer']['lastProgressValue'] = percentage
self.env['commandBuffer']['lastProgressTime'] = currentTime
return
# Pattern 2: Fraction (15/100, 3 of 10, etc.)
fractionMatch = re.search(r'(\d+)\s*(?:of|/)\s*(\d+)', text)
if fractionMatch:
current = int(fractionMatch.group(1))
total = int(fractionMatch.group(2))
if total > 0:
percentage = (current / total) * 100
if percentage != self.env['commandBuffer']['lastProgressValue']:
self.playProgressTone(percentage)
self.env['commandBuffer']['lastProgressValue'] = percentage
self.env['commandBuffer']['lastProgressTime'] = currentTime
return
# Pattern 3: Progress bars ([#### ], [====> ], etc.)
# Improved pattern to avoid matching IRC channels like [#channel]
barMatch = re.search(r'\[([#=\-\*]+)([\s\.]*)\]', text)
if barMatch:
filled = len(barMatch.group(1))
unfilled = len(barMatch.group(2))
total = filled + unfilled
# Require at least 2 progress chars total and unfilled portion must be spaces/dots
if total >= 2 and (not barMatch.group(2) or re.match(r'^[\s\.]*$', barMatch.group(2))):
percentage = (filled / total) * 100
if percentage != self.env['commandBuffer']['lastProgressValue']:
self.playProgressTone(percentage)
self.env['commandBuffer']['lastProgressValue'] = percentage
self.env['commandBuffer']['lastProgressTime'] = currentTime
return
# Pattern 4: Generic activity indicators (Loading..., Working..., etc.)
activityPattern = re.search(r'(loading|processing|working|installing|downloading|compiling|building).*\.{2,}', text, re.IGNORECASE)
if activityPattern:
# Play a steady beep every 2 seconds for ongoing activity
if currentTime - self.env['commandBuffer']['lastProgressTime'] >= 2.0:
self.playActivityBeep()
self.env['commandBuffer']['lastProgressTime'] = currentTime
def playProgressTone(self, percentage):
# Map 0-100% to 400-1200Hz frequency range
frequency = 400 + (percentage * 8)
frequency = max(400, min(1200, frequency)) # Clamp to safe range
self.env['runtime']['outputManager'].playFrequence(frequency, 0.15, interrupt=False)
def playActivityBeep(self):
# Single tone for generic activity
self.env['runtime']['outputManager'].playFrequence(800, 0.1, interrupt=False)
def isCurrentLinePrompt(self):
"""Check if the current line looks like a standalone prompt (not command with progress)"""
import re
try:
# Get the current screen content
if not self.env['screen']['newContentText']:
return False
lines = self.env['screen']['newContentText'].split('\n')
if not lines:
return False
# Check the last line (most common) and current cursor line for prompt patterns
linesToCheck = []
# Add last line (most common for prompts)
if lines:
linesToCheck.append(lines[-1])
# Add current cursor line if different from last line
if (self.env['screen']['newCursor']['y'] < len(lines) and
self.env['screen']['newCursor']['y'] != len(lines) - 1):
linesToCheck.append(lines[self.env['screen']['newCursor']['y']])
# Standalone prompt patterns (no commands mixed in)
standalonePromptPatterns = [
r'^\s*\$\s*$', # Just $ (with whitespace)
r'^\s*#\s*$', # Just # (with whitespace)
r'^\s*>\s*$', # Just > (with whitespace)
r'^\[.*\]\s*[\\\$#>]\s*$', # [path]$ without commands
r'^[a-zA-Z0-9._-]+[\\\$#>]\s*$', # bash-5.1$ without commands
# Interactive prompt patterns (these ARE standalone)
r'.*\?\s*\[[YyNn]/[YyNn]\]\s*$', # ? [Y/n] or ? [y/N] style
r'.*\?\s*\[[Yy]es/[Nn]o\]\s*$', # ? [Yes/No] style
r'.*continue\?\s*\[[YyNn]/[YyNn]\].*$', # "continue? [Y/n]" style
r'^::.*\?\s*\[[YyNn]/[YyNn]\].*$', # pacman style prompts
# Authentication prompts (these ARE standalone)
r'^\[[Ss]udo\]\s*[Pp]assword\s*for\s+.*:\s*$', # [sudo] password
r'^[Pp]assword\s*:\s*$', # Password:
r'.*[Pp]assword\s*:\s*$', # general password prompts
# Continuation prompts (these ARE standalone)
r'^[Pp]ress\s+any\s+key\s+to\s+continue.*$', # Press any key
r'^[Aa]re\s+you\s+sure\?\s*.*$', # Are you sure?
]
for line in linesToCheck:
line = line.strip()
if not line:
continue
# Check if this line contains both a prompt AND other content (like commands)
# If so, don't treat it as a standalone prompt
hasPromptMarker = bool(re.search(r'.*@.*[\\\$#>]', line) or re.search(r'^\[.*\]\s*[\\\$#>]', line))
if hasPromptMarker:
# If line has prompt marker but also has significant content after it,
# it's a command line, not a standalone prompt
promptEnd = max(
line.rfind('$'),
line.rfind('#'),
line.rfind('>'),
line.rfind('\\')
)
if promptEnd >= 0 and promptEnd < len(line) - 5: # More than just whitespace after prompt
continue # This is a command line, not a standalone prompt
for pattern in standalonePromptPatterns:
try:
if re.search(pattern, line):
return True
except re.error:
continue
return False
except Exception:
# If anything fails, assume it's not a prompt to be safe
return False
def setCallback(self, callback):
pass

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import word_utils
import string
initialized = False

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
class command():
def __init__(self):

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import char_utils
class command():
@@ -23,7 +22,7 @@ class command():
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
# is has attribute it enabled?
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'):
cursorPos = self.env['screen']['newCursorReview']

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import char_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import word_utils
class command():

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import word_utils
from fenrirscreenreader.utils import char_utils

View File

@@ -4,7 +4,6 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import char_utils
class command():

Some files were not shown because too many files have changed in this diff Show More