39 Commits

Author SHA1 Message Date
271c4fc18f Table mode fixes and improvements to application detection. 2025-07-08 14:41:43 -04:00
bb6dbc7186 Fixed character navigation in table mode. 2025-07-07 22:58:14 -04:00
c7cc9d039b Improved application detection, now works inside screen and tmux. Fixed incosistancies in prev/next word navigation. 2025-07-07 11:17:12 -04:00
d1a42835e4 Initial table mode added. Probably bugs. 2025-07-07 09:46:12 -04:00
3390c25dfe More pep8 fixes. A tiny bit of refactoring. 2025-07-07 00:42:23 -04:00
ea56b90b48 Oops, getting used to this pep8 thing myself. Fixed codeName to code_name. 2025-07-06 18:51:43 -04:00
1268d989b7 Merge after mostly converting to pep8 compliance. 2025-07-06 18:34:28 -04:00
d28c18faed Found and sniped a couple more pep8 migration errors. 2025-07-05 09:29:32 -04:00
c90c726899 Fixed a bug in the remote manager. 2025-07-05 09:15:40 -04:00
bab7c1a552 Removed double keybinding from laptop layout. 2025-07-03 16:11:13 -04:00
848844aae4 Oops, forgot to delete my traceback notes. 2025-07-03 13:24:23 -04:00
4c1bddbbd3 Most of the pep8 changes finished. Be careful, things may be horribly broken. 2025-07-03 13:23:25 -04:00
21bb9c6083 Most of the pep8 changes finished. Be careful, things may be horribly broken. 2025-07-03 13:22:00 -04:00
7408951152 To make Fenrir easier to approach for new developer, start code migration to be pep8 compliant. 2025-07-01 22:23:50 -04:00
23c3ad20a1 More code optmizations. Removed fenrir+pk_plus. The functionality of bringing back speech has been added to the temperary speech interruption key kp_enter. 2025-06-30 22:25:01 -04:00
4bcf82178e Updated configure_pipewire script. A bit more code refactor. Preparing to start moving everything over to pep8 compliance. 2025-06-28 22:52:21 -04:00
beae1866bb Moved restore speech on prompt to existing temp interrupt speech command, Fenrir+kp_plus unbound now. 2025-06-28 01:49:20 -04:00
8af1cca879 Latest changes and bug fixes. 2025-06-27 21:18:27 -04:00
40b88efa34 Fix up a few errors that sneaked in while updating vmenu code and a couple other things. Logs should be much nicer now. 2025-06-25 10:56:08 -04:00
b1edc53362 Added missing dependency to requirements.txt. 2025-06-20 12:43:49 -04:00
dda84b9905 Final batch of code stability updates before anouther bout of extended testing. Still plenty to go, but making progress. 2025-06-20 03:34:50 -04:00
64e79f6945 Code cleanup, make sure race conditions can't happen, at least in theory. 2025-06-20 03:10:07 -04:00
f4ed8da4c3 Forgot one in last commit. 2025-06-20 03:04:25 -04:00
a5ca1d28e8 Make sure all except statements are no longer empty, should help a lot with debugging. 2025-06-20 03:03:43 -04:00
a394ea0222 Code cleanup and bug fixes. 2025-06-20 02:19:57 -04:00
4e193f133f Fixed an error that crept into log permissions during code restructuring. 2025-06-20 02:19:07 -04:00
27dcff23bb Code optimization and bug fixes. Removed the broken, partial atspi driver implementation. 2025-06-18 15:08:36 -04:00
efb308ac72 latest testing code merged. Nothing major reported from testing branch, so if we get no reports, this will become the next stable release. I'm waiting a bit to tag because major new features introduced. 2025-06-17 00:53:28 -04:00
f6be6c54fb Bug fixes mostlry, tested and seems to be working better. 2025-06-13 23:21:46 -04:00
f18c31df6c Merge branch 'testing' bug fix for remoteDriver 2025-06-07 18:24:44 -04:00
3dca3e5b23 Merged for new release. 2025-06-07 12:23:53 -04:00
1b9a9a90b1 Fixed version conflict. 2025-06-06 20:35:07 -04:00
4c8c8d896d Fixed version conflict. 2025-06-05 16:05:11 -04:00
4672592dba Latest merge from testing. 2025-04-28 15:41:14 -04:00
7a12992b88 latest release. 2025-04-17 00:36:26 -04:00
7a87fb51bb Fixed version for master branch. 2025-04-14 20:04:14 -04:00
2cc2fda28c Actually fix the version file this time. 2025-03-02 17:59:20 -05:00
c99d0f6ee1 Fixed version.py. 2025-03-02 17:44:32 -05:00
5b642cd9e2 Fixed error in settings file. 2025-02-26 17:41:01 -05:00
354 changed files with 18640 additions and 9691 deletions

View File

@ -74,7 +74,7 @@ KEY_FENRIR,KEY_0=bookmark_10
KEY_FENRIR,KEY_KPSLASH=set_window_application KEY_FENRIR,KEY_KPSLASH=set_window_application
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application 2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
KEY_KPPLUS=progress_bar_monitor KEY_KPPLUS=progress_bar_monitor
KEY_FENRIR,KEY_KPPLUS=silence_until_prompt #KEY_FENRIR,KEY_KPPLUS=silence_until_prompt
KEY_FENRIR,KEY_F2=toggle_braille KEY_FENRIR,KEY_F2=toggle_braille
KEY_FENRIR,KEY_F3=toggle_sound KEY_FENRIR,KEY_F3=toggle_sound
KEY_FENRIR,KEY_F4=toggle_speech KEY_FENRIR,KEY_F4=toggle_speech

View File

@ -76,12 +76,11 @@ KEY_FENRIR,KEY_F3=toggle_sound
KEY_FENRIR,KEY_F4=toggle_speech KEY_FENRIR,KEY_F4=toggle_speech
KEY_FENRIR,KEY_ENTER=temp_disable_speech KEY_FENRIR,KEY_ENTER=temp_disable_speech
KEY_FENRIR,KEY_SHIFT,KEY_P=progress_bar_monitor KEY_FENRIR,KEY_SHIFT,KEY_P=progress_bar_monitor
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=silence_until_prompt KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_auto_read
KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
KEY_FENRIR,KEY_CTRL,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_SHIFT,KEY_E=toggle_emoticons
KEY_FENRIR,KEY_ENTER=toggle_auto_read
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
KEY_FENRIR,KEY_Y=toggle_highlight_tracking KEY_FENRIR,KEY_Y=toggle_highlight_tracking
#=toggle_barrier #=toggle_barrier

View File

@ -124,7 +124,9 @@ interruptOnKeyPressFilter=
doubleTapTimeout=0.2 doubleTapTimeout=0.2
[general] [general]
debugLevel=0 # Debug levels: 0=DEACTIVE, 1=ERROR, 2=WARNING, 3=INFO (most verbose)
# For production use, WARNING (2) provides good balance of useful info without spam
debugLevel=2
# debugMode sets where the debug output should send to: # debugMode sets where the debug output should send to:
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log) # debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
# debugMode=Print just prints on the screen # debugMode=Print just prints on the screen

View File

@ -1,141 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Install script for Fenrir Screen Reader #Basic install script for Fenrir.
set -e read -rp "This will install Fenrir. Press ctrl+C to cancel, or enter to continue."
# 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 # Fenrir main application
install -m755 -d /opt/fenrirscreenreader install -m755 -d /opt/fenrirscreenreader
cp -af src/* /opt/fenrirscreenreader cp -af src/* /opt/fenrirscreenreader
ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir
# tools # tools
install -m755 -d /usr/share/fenrirscreenreader/tools install -m755 -d /usr/share/fenrirscreenreader/tools
cp -af tools/* /usr/share/fenrirscreenreader/tools cp -af tools/* /usr/share/fenrirscreenreader/tools
@ -172,49 +43,24 @@ if [ -f "/etc/fenrirscreenreader/settings/settings.conf" ]; then
fi fi
else else
install -m644 -D "config/settings/settings.conf" /etc/fenrirscreenreader/settings/settings.conf 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
# Final message # end message
cat << EOF cat << EOF
Installation complete.
install path:/opt/fenrirscreenreader
settings path:/etc/fenrirscreenreader
Installation complete! To test Fenrir:
============================= sudo fenrir
Install path: /opt/fenrirscreenreader
Settings path: /etc/fenrirscreenreader
Next steps: To have Fenrir start on system boot using systemd:
1. Test Fenrir: sudo fenrir download service file: https://raw.githubusercontent.com/chrys87/fenrir/master/autostart/systemd/Arch/fenrir.service
2. Enable autostart: sudo systemctl enable fenrir move the service file to: /etc/systemd/system/fenrir.service
3. Configure audio (run both as user and root): sudo systemctl enable fenrir
- PulseAudio: /usr/share/fenrirscreenreader/tools/configure_pulse.sh
- PipeWire: /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
For help: Pulseaudio users may want to run
- Documentation: https://git.stormux.org/storm/fenrir /usr/share/fenrirscreenreader/tools/configure_pulse.sh
- Configuration: sudo fenrir --help once from their user account, then once from the root.
- Dependency check: python3 check-dependencies.py
Fenrir installation successful!
EOF EOF

View File

@ -1,16 +1,10 @@
daemonize>=2.5.0 daemonize
evdev>=1.4.0 dbus-python
dbus-python>=1.3.0 evdev
pyperclip>=1.8.0 pexpect
pyudev>=0.24.0 pyenchant
pyte>=0.8.0 pyperclip
setproctitle>=1.3.0 pyte
setuptools>=65.0.0 pyudev
pexpect>=4.8.0 pyxdg
setproctitle
# 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

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

View File

@ -4,19 +4,22 @@
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors. # By Chrys, Storm Dragon, and contributors.
import argparse
import inspect
import os import os
import sys import sys
import inspect
import argparse
from daemonize import Daemonize from daemonize import Daemonize
from fenrirscreenreader import fenrirVersion
from fenrirscreenreader.core import fenrirManager
# Get the fenrir installation path # Get the fenrir installation path
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) fenrirPath = os.path.dirname(os.path.realpath(
if not fenrirPath in sys.path: os.path.abspath(inspect.getfile(inspect.currentframe()))))
if fenrirPath not in sys.path:
sys.path.append(fenrirPath) sys.path.append(fenrirPath)
from fenrirscreenreader.core import fenrirManager
from fenrirscreenreader import fenrirVersion
def create_argument_parser(): def create_argument_parser():
"""Create and return the argument parser for Fenrir""" """Create and return the argument parser for Fenrir"""
@ -27,7 +30,7 @@ def create_argument_parser():
argumentParser.add_argument( argumentParser.add_argument(
'-v', '--version', '-v', '--version',
action='version', action='version',
version=f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}', version=f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.code_name}',
help='Show version information and exit' help='Show version information and exit'
) )
argumentParser.add_argument( argumentParser.add_argument(
@ -68,10 +71,10 @@ def create_argument_parser():
help='Use PTY emulation with evdev for input (single instance)' help='Use PTY emulation with evdev for input (single instance)'
) )
argumentParser.add_argument( argumentParser.add_argument(
'-F', '--force-all-screens', '-F',
'--force-all-screens',
action='store_true', action='store_true',
help='Force Fenrir to respond on all screens, ignoring ignoreScreen setting' help='Force Fenrir to respond on all screens, ignoring ignoreScreen setting')
)
argumentParser.add_argument( argumentParser.add_argument(
'-i', '-I', '--ignore-screen', '-i', '-I', '--ignore-screen',
metavar='SCREEN', metavar='SCREEN',
@ -80,29 +83,52 @@ def create_argument_parser():
) )
return argumentParser return argumentParser
def validate_arguments(cliArgs): def validate_arguments(cliArgs):
"""Validate command line arguments""" """Validate command line arguments"""
if cliArgs.options: if cliArgs.options:
for option in cliArgs.options.split(';'): for option in cliArgs.options.split(';'):
if option and ('#' not in option or '=' not in option): if option and ('#' not in option or '=' not in option):
return False, f"Invalid option format: {option}\nExpected format: SECTION#SETTING=VALUE" return False, f"Invalid option format: {option}\nExpected format: SECTION#SETTING=VALUE"
if cliArgs.emulated_pty and cliArgs.emulated_evdev: if cliArgs.emulated_pty and cliArgs.emulated_evdev:
return False, "Cannot use both --emulated-pty and --emulated-evdev simultaneously" return False, "Cannot use both --emulated-pty and --emulated-evdev simultaneously"
return True, None return True, None
def run_fenrir(): def run_fenrir():
"""Main function that runs Fenrir""" """Main function that runs Fenrir"""
fenrirApp = fenrirManager.fenrirManager(cliArgs) fenrirApp = None
fenrirApp.proceed() try:
del fenrirApp fenrirApp = fenrirManager.FenrirManager(cliArgs)
fenrirApp.proceed()
except Exception as e:
print(f"Error starting Fenrir: {e}", file=sys.stderr)
if fenrirApp and hasattr(fenrirApp, 'cleanup_on_error'):
try:
fenrirApp.cleanup_on_error()
except Exception as cleanup_error:
print(
f"Error during cleanup: {cleanup_error}", file=sys.stderr)
sys.exit(1)
finally:
if fenrirApp:
del fenrirApp
# Clean up PID file if it exists
pidFile = "/run/fenrir.pid"
if os.path.exists(pidFile):
try:
os.remove(pidFile)
except Exception:
pass
def main(): def main():
global cliArgs global cliArgs
argumentParser = create_argument_parser() argumentParser = create_argument_parser()
cliArgs = argumentParser.parse_args() cliArgs = argumentParser.parse_args()
# Validate arguments # Validate arguments
isValid, errorMsg = validate_arguments(cliArgs) isValid, errorMsg = validate_arguments(cliArgs)
if not isValid: if not isValid:
@ -123,5 +149,6 @@ def main():
) )
daemonProcess.start() daemonProcess.start()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -2,19 +2,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return 'No description found' def get_description(self):
return "No description found"
def run(self): def run(self):
pass pass
def setCallback(self, callback):
def set_callback(self, callback):
pass pass

View File

@ -2,24 +2,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
# this command is just to initialize stuff. # this command is just to initialize stuff.
# like init index lists in memoryManager # like init index lists in MemoryManager
# it is not useful to execute it # it is not useful to execute it
class command():
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
# clipboard # clipboard
self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards')) self.env["runtime"]["MemoryManager"].add_index_list(
"clipboardHistory",
self.env["runtime"]["SettingsManager"].get_setting_as_int(
"general", "numberOfClipboards"
),
)
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return 'No description found' def get_description(self):
return "No description found"
def run(self): def run(self):
pass pass
def setCallback(self, callback):
def set_callback(self, callback):
pass pass

View File

@ -2,52 +2,92 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.utils import word_utils
import string import string
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils
initialized = False initialized = False
try: try:
import enchant import enchant
initialized = True initialized = True
except: except Exception as e:
pass pass
class command():
class command:
def __init__(self): def __init__(self):
self.language = '' self.language = ""
self.spellChecker = None self.spellChecker = None
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
self.updateSpellLanguage() self.update_spell_language()
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('adds the current word to the exceptions dictionary') def get_description(self):
def updateSpellLanguage(self): return _("adds the current word to the exceptions dictionary")
self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage'))
self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') def update_spell_language(self):
self.spellChecker = enchant.Dict(
self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
)
self.language = self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
def run(self): def run(self):
if not initialized: if not initialized:
return return
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: if (
self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
!= self.language
):
try: try:
self.updateSpellLanguage() self.update_spell_language()
except Exception as e: except Exception as e:
return return
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
# get the word # get the word
newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] new_content = self.env["screen"]["new_content_text"].split("\n")[
x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) cursor_pos["y"]
currWord = currWord.strip(string.whitespace + r'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~') ]
x, y, curr_word, end_of_screen, line_break = (
word_utils.get_current_word(cursor_pos["x"], 0, new_content)
)
curr_word = curr_word.strip(
string.whitespace + r'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~'
)
if currWord != '': if curr_word != "":
if self.spellChecker.is_added(currWord): if self.spellChecker.is_added(curr_word):
self.env['runtime']['outputManager'].presentText(_('{0} is already in dictionary').format(currWord,), soundIcon='Cancel', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("{0} is already in dictionary").format(
curr_word,
),
sound_icon="Cancel",
interrupt=True,
)
else: else:
self.spellChecker.add(currWord) self.spellChecker.add(curr_word)
self.env['runtime']['outputManager'].presentText(_('{0} added to dictionary').format(currWord,), soundIcon='Accept', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("{0} added to dictionary").format(
curr_word,
),
sound_icon="Accept",
interrupt=True,
)
def setCallback(self, callback): def set_callback(self, callback):
pass pass

View File

@ -2,45 +2,51 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import math import math
class AdjustmentCommand(): from fenrirscreenreader.core.i18n import _
class adjustment_command:
"""Base class for speech and sound adjustment commands""" """Base class for speech and sound adjustment commands"""
def __init__(self, section, setting, direction, step=0.1): def __init__(self, section, setting, direction, step=0.1):
self.section = section # 'speech' or 'sound' self.section = section # 'speech' or 'sound'
self.setting = setting # 'rate', 'pitch', 'volume' self.setting = setting # 'rate', 'pitch', 'volume'
self.direction = direction # 'inc' or 'dec' self.direction = direction # 'inc' or 'dec'
self.step = step self.step = step
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self): def get_description(self):
action = "Increase" if self.direction == 'inc' else "Decrease" action = "Increase" if self.direction == "inc" else "Decrease"
if self.section == 'speech': if self.section == "speech":
return _(f'{action} the speech {self.setting}') return _(f"{action} the speech {self.setting}")
else: else:
return _(f'{action} the {self.section} {self.setting}') return _(f"{action} the {self.section} {self.setting}")
def run(self): def run(self):
if self.section == 'sound' and self.setting == 'volume': if self.section == "sound" and self.setting == "volume":
# Sound volume uses different method # Sound volume uses different method
self._adjust_sound_volume() self._adjust_sound_volume()
else: else:
# Speech rate, pitch, volume use standard method # Speech rate, pitch, volume use standard method
self._adjust_speech_setting() self._adjust_speech_setting()
def _adjust_speech_setting(self): def _adjust_speech_setting(self):
"""Adjust speech settings (rate, pitch, volume)""" """Adjust speech settings (rate, pitch, volume)"""
value = self.env['runtime']['settingsManager'].getSettingAsFloat(self.section, self.setting) value = self.env["runtime"]["SettingsManager"].get_setting_as_float(
self.section, self.setting
)
# Apply adjustment with rounding # Apply adjustment with rounding
if self.direction == 'inc': if self.direction == "inc":
value = round((math.ceil(10 * value) / 10) + self.step, 2) value = round((math.ceil(10 * value) / 10) + self.step, 2)
if value > 1.0: if value > 1.0:
value = 1.0 value = 1.0
@ -48,25 +54,35 @@ class AdjustmentCommand():
value = round((math.ceil(10 * value) / 10) - self.step, 2) value = round((math.ceil(10 * value) / 10) - self.step, 2)
if value < 0.0: if value < 0.0:
value = 0.0 value = 0.0
# Set the new value # Set the new value
self.env['runtime']['settingsManager'].setSetting(self.section, self.setting, str(value)) self.env["runtime"]["SettingsManager"].set_setting(
self.section, self.setting, str(value)
)
# Present feedback # Present feedback
percentage = int(value * 100) percentage = int(value * 100)
if self.section == 'speech': if self.section == "speech":
feedback = _("{0} percent speech {1}").format(percentage, self.setting) feedback = _("{0} percent speech {1}").format(
percentage, self.setting
)
else: else:
feedback = _("{0} percent {1} {2}").format(percentage, self.section, self.setting) feedback = _("{0} percent {1} {2}").format(
percentage, self.section, self.setting
self.env['runtime']['outputManager'].presentText(feedback, soundIcon='', interrupt=True) )
self.env["runtime"]["OutputManager"].present_text(
feedback, sound_icon="", interrupt=True
)
def _adjust_sound_volume(self): def _adjust_sound_volume(self):
"""Adjust sound volume using same logic as speech""" """Adjust sound volume using same logic as speech"""
value = self.env['runtime']['settingsManager'].getSettingAsFloat(self.section, self.setting) value = self.env["runtime"]["SettingsManager"].get_setting_as_float(
self.section, self.setting
)
# Sound volume uses same math as speech settings # Sound volume uses same math as speech settings
if self.direction == 'inc': if self.direction == "inc":
value = round((math.ceil(10 * value) / 10) + self.step, 2) value = round((math.ceil(10 * value) / 10) + self.step, 2)
if value > 1.0: if value > 1.0:
value = 1.0 value = 1.0
@ -74,15 +90,19 @@ class AdjustmentCommand():
value = round((math.ceil(10 * value) / 10) - self.step, 2) value = round((math.ceil(10 * value) / 10) - self.step, 2)
if value < 0.0: if value < 0.0:
value = 0.0 value = 0.0
# Set the new value # Set the new value
self.env['runtime']['settingsManager'].setSetting(self.section, self.setting, str(value)) self.env["runtime"]["SettingsManager"].set_setting(
self.section, self.setting, str(value)
)
# Present feedback with appropriate sound icon # Present feedback with appropriate sound icon
percentage = int(value * 100) percentage = int(value * 100)
sound_icon = 'SoundOn' if self.direction == 'inc' else 'SoundOff' sound_icon = "SoundOn" if self.direction == "inc" else "SoundOff"
feedback = _("{0} percent sound volume").format(percentage) feedback = _("{0} percent sound volume").format(percentage)
self.env['runtime']['outputManager'].presentText(feedback, soundIcon=sound_icon, interrupt=True) self.env["runtime"]["OutputManager"].present_text(
feedback, sound_icon=sound_icon, interrupt=True
def setCallback(self, callback): )
pass
def set_callback(self, callback):
pass

View File

@ -2,25 +2,37 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader import fenrirVersion from fenrirscreenreader import fenrirVersion
from fenrirscreenreader.core.i18n import _
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Present the version of Fenrir currrrently in use.') def get_description(self):
return _("Present the version of Fenrir currently in use.")
def run(self): def run(self):
try: try:
self.env['runtime']['outputManager'].presentText(f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
except exception as e: f"Fenrir screen reader version {
self.env['runtime']['outputManager'].presentText(_('Version information is unavailable.'), interrupt=True) fenrirVersion.version}-{
fenrirVersion.code_name}",
def setCallback(self, callback): interrupt=True,
)
except Exception as e:
self.env["runtime"]["OutputManager"].present_text(
_("Version information is unavailable."), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -1,71 +1,94 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self): def get_description(self):
return "Apply the last tested voice from safe voice browser" return "Apply the last tested voice from safe voice browser"
def run(self): def run(self):
try: try:
# Check if we have a tested voice # Check if we have a tested voice
if ('commandBuffer' not in self.env or if (
'lastTestedModule' not in self.env['commandBuffer'] or "commandBuffer" not in self.env
'lastTestedVoice' not in self.env['commandBuffer']): or "lastTestedModule" not in self.env["commandBuffer"]
self.env['runtime']['outputManager'].presentText("No voice has been tested yet", interrupt=True) or "lastTestedVoice" not in self.env["commandBuffer"]
self.env['runtime']['outputManager'].presentText("Use voice browser first", interrupt=True) ):
self.env["runtime"]["OutputManager"].present_text(
"No voice has been tested yet", interrupt=True
)
self.env["runtime"]["OutputManager"].present_text(
"Use voice browser first", interrupt=True
)
return return
module = self.env['commandBuffer']['lastTestedModule'] module = self.env["commandBuffer"]["lastTestedModule"]
voice = self.env['commandBuffer']['lastTestedVoice'] voice = self.env["commandBuffer"]["lastTestedVoice"]
self.env['runtime']['outputManager'].presentText(f"Applying {voice} from {module}", interrupt=True) self.env["runtime"]["OutputManager"].present_text(
f"Applying {voice} from {module}", interrupt=True
)
# Apply to runtime settings only (temporary until saved) # Apply to runtime settings only (temporary until saved)
settingsManager = self.env['runtime']['settingsManager'] SettingsManager = self.env["runtime"]["SettingsManager"]
# Store old values for safety # Store old values for safety
oldDriver = settingsManager.getSetting('speech', 'driver') old_driver = SettingsManager.get_setting("speech", "driver")
oldModule = settingsManager.getSetting('speech', 'module') old_module = SettingsManager.get_setting("speech", "module")
oldVoice = settingsManager.getSetting('speech', 'voice') old_voice = SettingsManager.get_setting("speech", "voice")
try: try:
# Apply new settings to runtime only (use setSetting to update settingArgDict) # Apply new settings to runtime only (use set_setting to update
settingsManager.setSetting('speech', 'driver', 'speechdDriver') # settingArgDict)
settingsManager.setSetting('speech', 'module', module) SettingsManager.set_setting(
settingsManager.setSetting('speech', 'voice', voice) "speech", "driver", "speechdDriver"
)
SettingsManager.set_setting("speech", "module", module)
SettingsManager.set_setting("speech", "voice", voice)
# Apply to speech driver instance directly # Apply to speech driver instance directly
if 'speechDriver' in self.env['runtime']: if "SpeechDriver" in self.env["runtime"]:
speechDriver = self.env['runtime']['speechDriver'] SpeechDriver = self.env["runtime"]["SpeechDriver"]
# Set the module and voice on the driver instance # Set the module and voice on the driver instance
speechDriver.setModule(module) SpeechDriver.set_module(module)
speechDriver.setVoice(voice) SpeechDriver.set_voice(voice)
self.env['runtime']['outputManager'].presentText("Voice applied successfully!", interrupt=True) self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText("Use save settings to make permanent", interrupt=True) "Voice applied successfully!", interrupt=True
self.env['runtime']['outputManager'].playSound('Accept') )
self.env["runtime"]["OutputManager"].present_text(
"Use save settings to make permanent", interrupt=True
)
self.env["runtime"]["OutputManager"].play_sound("Accept")
except Exception as e: except Exception as e:
# Revert on failure # Revert on failure
settingsManager.setSetting('speech', 'driver', oldDriver) SettingsManager.set_setting("speech", "driver", old_driver)
settingsManager.setSetting('speech', 'module', oldModule) SettingsManager.set_setting("speech", "module", old_module)
settingsManager.setSetting('speech', 'voice', oldVoice) SettingsManager.set_setting("speech", "voice", old_voice)
self.env['runtime']['outputManager'].presentText(f"Failed to apply voice, reverted: {str(e)}", interrupt=True) self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].playSound('Error') f"Failed to apply voice, reverted: {str(e)}",
interrupt=True,
)
self.env["runtime"]["OutputManager"].play_sound("Error")
except Exception as e: except Exception as e:
self.env['runtime']['outputManager'].presentText(f"Apply voice error: {str(e)}", interrupt=True) self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].playSound('Error') f"Apply voice error: {str(e)}", interrupt=True
)
def setCallback(self, callback): self.env["runtime"]["OutputManager"].play_sound("Error")
pass
def set_callback(self, callback):
pass

View File

@ -2,28 +2,45 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import screen_utils from fenrirscreenreader.utils import screen_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Reads attributes of current cursor position') def get_description(self):
return _("Reads attributes of current cursor position")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
try: try:
attributes = self.env['runtime']['attributeManager'].getAttributeByXY( cursorPos['x'], cursorPos['y']) attributes = self.env["runtime"][
"AttributeManager"
].get_attribute_by_xy(cursor_pos["x"], cursor_pos["y"])
except Exception as e: except Exception as e:
print(e) print(e)
attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString') attribute_format_string = self.env["runtime"][
attributeFormatString = self.env['runtime']['attributeManager'].formatAttributes(attributes, attributeFormatString) "SettingsManager"
].get_setting("general", "attribute_format_string")
self.env['runtime']['outputManager'].presentText(attributeFormatString, soundIcon='', interrupt=True) attribute_format_string = self.env["runtime"][
def setCallback(self, callback): "AttributeManager"
].format_attributes(attributes, attribute_format_string)
self.env["runtime"]["OutputManager"].present_text(
attribute_format_string, sound_icon="", interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(1, 'read') super().__init__(1, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(10, 'read') super().__init__(10, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(2, 'read') super().__init__(2, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(3, 'read') super().__init__(3, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(4, 'read') super().__init__(4, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(5, 'read') super().__init__(5, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(6, 'read') super().__init__(6, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(7, 'read') super().__init__(7, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(8, 'read') super().__init__(8, "read")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(9, 'read') super().__init__(9, "read")

View File

@ -2,149 +2,210 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import gettext from fenrirscreenreader.core.i18n import _
_ = gettext.gettext
from fenrirscreenreader.utils import mark_utils
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
from fenrirscreenreader.utils import mark_utils
class BookmarkCommand():
class bookmark_command:
"""Base class for bookmark operations - read, set, clear""" """Base class for bookmark operations - read, set, clear"""
def __init__(self, bookmark_id, action='read'):
def __init__(self, bookmark_id, action="read"):
self.ID = str(bookmark_id) self.ID = str(bookmark_id)
self.action = action self.action = action
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
# Always initialize bookmark structure - all commands need this # Always initialize bookmark structure - all commands need this
if self.ID not in self.env['commandBuffer']['bookMarks']: if self.ID not in self.env["commandBuffer"]["bookMarks"]:
self.env['commandBuffer']['bookMarks'][self.ID] = {} self.env["commandBuffer"]["bookMarks"][self.ID] = {}
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self): def get_description(self):
if self.action == 'read': if self.action == "read":
return _('read Bookmark {0}').format(self.ID) return _("read Bookmark {0}").format(self.ID)
elif self.action == 'set': elif self.action == "set":
return _('set Bookmark {0}').format(self.ID) return _("set Bookmark {0}").format(self.ID)
elif self.action == 'clear': elif self.action == "clear":
return _('remove Bookmark {0}').format(self.ID) return _("remove Bookmark {0}").format(self.ID)
return f'{self.action} Bookmark {self.ID}' return f"{self.action} Bookmark {self.ID}"
def run(self): def run(self):
if self.action == 'read': if self.action == "read":
self._read_bookmark() self._read_bookmark()
elif self.action == 'set': elif self.action == "set":
self._set_bookmark() self._set_bookmark()
elif self.action == 'clear': elif self.action == "clear":
self._clear_bookmark() self._clear_bookmark()
def _read_bookmark(self): def _read_bookmark(self):
currApp = self.env['runtime']['applicationManager'].getCurrentApplication() curr_app = self.env["runtime"][
"ApplicationManager"
if not self.env['commandBuffer']['bookMarks'][self.ID]: ].get_current_application()
self.env['runtime']['outputManager'].presentText('Bookmark {0} not set'.format(self.ID), interrupt=True)
if not self.env["commandBuffer"]["bookMarks"][self.ID]:
self.env["runtime"]["OutputManager"].present_text(
"Bookmark {0} not set".format(self.ID), interrupt=True
)
return return
if currApp not in self.env['commandBuffer']['bookMarks'][self.ID]: if curr_app not in self.env["commandBuffer"]["bookMarks"][self.ID]:
self.env['runtime']['outputManager'].presentText('Bookmark for application {0} not set'.format(currApp), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
"Bookmark for application {0} not set".format(curr_app),
interrupt=True,
)
return return
if not self.env['commandBuffer']['bookMarks'][self.ID][currApp].get('1'): if not self.env["commandBuffer"]["bookMarks"][self.ID][curr_app].get(
self.env['runtime']['outputManager'].presentText('Bookmark for application {0} not set'.format(currApp), interrupt=True) "1"
):
self.env["runtime"]["OutputManager"].present_text(
"Bookmark for application {0} not set".format(curr_app),
interrupt=True,
)
return return
# Get bookmarked text # Get bookmarked text
marked = '' marked = ""
startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() start_mark = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app][
"1"
if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: ].copy()
endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy()
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) if self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]["2"]:
end_mark = self.env["commandBuffer"]["bookMarks"][self.ID][
curr_app
]["2"].copy()
marked = mark_utils.get_text_between_marks(
start_mark, end_mark, self.env["screen"]["new_content_text"]
)
else: else:
x, y, marked = line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) x, y, marked = line_utils.get_current_line(
start_mark["x"],
start_mark["y"],
self.env["screen"]["new_content_text"],
)
if marked.isspace(): if marked.isspace():
self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else: else:
self.env['runtime']['outputManager'].presentText(marked, interrupt=True) self.env["runtime"]["OutputManager"].present_text(
marked, interrupt=True
)
def _set_bookmark(self): def _set_bookmark(self):
if not self.env['commandBuffer']['Marks']['1']: if not self.env["commandBuffer"]["Marks"]["1"]:
self.env['runtime']['outputManager'].presentText(_("No mark found"), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("No mark found"), interrupt=True
)
return return
currApp = self.env['runtime']['applicationManager'].getCurrentApplication() curr_app = self.env["runtime"][
self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} "ApplicationManager"
].get_current_application()
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] = {}
if self.env['commandBuffer']['Marks']['2']: bookmarks = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() bookmarks["1"] = self.env["commandBuffer"]["Marks"]["1"].copy()
if self.env["commandBuffer"]["Marks"]["2"]:
bookmarks["2"] = self.env["commandBuffer"]["Marks"]["2"].copy()
else: else:
self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None bookmarks["2"] = None
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("Bookmark {0} set for application {1}").format(
self.ID, curr_app
),
interrupt=True,
)
# Clear marks after setting bookmark # Clear marks after setting bookmark
self.env['commandBuffer']['Marks']['1'] = None self.env["commandBuffer"]["Marks"]["1"] = None
self.env['commandBuffer']['Marks']['2'] = None self.env["commandBuffer"]["Marks"]["2"] = None
def _clear_bookmark(self): def _clear_bookmark(self):
currApp = self.env['runtime']['applicationManager'].getCurrentApplication() curr_app = self.env["runtime"][
"ApplicationManager"
if self.ID in self.env['commandBuffer']['bookMarks'] and currApp in self.env['commandBuffer']['bookMarks'][self.ID]: ].get_current_application()
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) bookmarks = self.env["commandBuffer"]["bookMarks"]
if self.ID in bookmarks and curr_app in bookmarks[self.ID]:
del self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
self.env["runtime"]["OutputManager"].present_text(
_("Bookmark {0} removed for application {1}").format(
self.ID, curr_app
),
interrupt=True,
)
else: else:
self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set for application {1}').format(self.ID, currApp), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("Bookmark {0} not set for application {1}").format(
def setCallback(self, callback): self.ID, curr_app
),
interrupt=True,
)
def set_callback(self, callback):
pass pass
# Factory function to create bookmark command instances # Factory function to create bookmark command instances
def create_bookmark_commands(): def create_bookmark_commands():
"""Create all bookmark command instances""" """Create all bookmark command instances"""
commands = {} commands = {}
# Create read bookmark commands (bookmark_1 through bookmark_10) # Create read bookmark commands (bookmark_1 through bookmark_10)
for i in range(1, 11): for i in range(1, 11):
commands[f'bookmark_{i}'] = lambda i=i: BookmarkCommand(i, 'read') commands[f"bookmark_{i}"] = lambda i=i: bookmark_command(i, "read")
# Create set bookmark commands (set_bookmark_1 through set_bookmark_10) # Create set bookmark commands (set_bookmark_1 through set_bookmark_10)
for i in range(1, 11): for i in range(1, 11):
commands[f'set_bookmark_{i}'] = lambda i=i: BookmarkCommand(i, 'set') commands[f"set_bookmark_{i}"] = lambda i=i: bookmark_command(i, "set")
# Create clear bookmark commands (clear_bookmark_1 through clear_bookmark_10) # Create clear bookmark commands (clear_bookmark_1 through
# clear_bookmark_10)
for i in range(1, 11): for i in range(1, 11):
commands[f'clear_bookmark_{i}'] = lambda i=i: BookmarkCommand(i, 'clear') commands[f"clear_bookmark_{i}"] = lambda i=i: bookmark_command(
i, "clear"
)
return commands return commands
# For backwards compatibility, provide individual command classes # For backwards compatibility, provide individual command classes
# This allows the existing command loading system to work unchanged # This allows the existing command loading system to work unchanged
def _make_command_class(bookmark_id, action): def _make_command_class(bookmark_id, action):
"""Create a command class for a specific bookmark and action""" """Create a command class for a specific bookmark and action"""
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(bookmark_id, action) super().__init__(bookmark_id, action)
return command return command
# Generate individual command classes for each bookmark operation # Generate individual command classes for each bookmark operation
# These will be used by the existing command loading system # These will be used by the existing command loading system
# Read bookmarks (bookmark_1.py style) # Read bookmarks (bookmark_1.py style)
for i in range(1, 11): for i in range(1, 11):
globals()[f'bookmark_{i}_command'] = _make_command_class(i, 'read') globals()[f"bookmark_{i}_command"] = _make_command_class(i, "read")
# Set bookmarks (set_bookmark_1.py style) # Set bookmarks (set_bookmark_1.py style)
for i in range(1, 11): for i in range(1, 11):
globals()[f'set_bookmark_{i}_command'] = _make_command_class(i, 'set') globals()[f"set_bookmark_{i}_command"] = _make_command_class(i, "set")
# Clear bookmarks (clear_bookmark_1.py style) # Clear bookmarks (clear_bookmark_1.py style)
for i in range(1, 11): for i in range(1, 11):
globals()[f'clear_bookmark_{i}_command'] = _make_command_class(i, 'clear') globals()[f"clear_bookmark_{i}_command"] = _make_command_class(i, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(1, 'clear') super().__init__(1, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(10, 'clear') super().__init__(10, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(2, 'clear') super().__init__(2, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(3, 'clear') super().__init__(3, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(4, 'clear') super().__init__(4, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(5, 'clear') super().__init__(5, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(6, 'clear') super().__init__(6, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(7, 'clear') super().__init__(7, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(8, 'clear') super().__init__(8, "clear")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "bookmark_base.py")
_spec = importlib.util.spec_from_file_location("bookmark_base", _base_path) _spec = importlib.util.spec_from_file_location("bookmark_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
BookmarkCommand = _module.BookmarkCommand bookmark_command = _module.bookmark_command
class command(BookmarkCommand):
class command(bookmark_command):
def __init__(self): def __init__(self):
super().__init__(9, 'clear') super().__init__(9, "clear")

View File

@ -2,22 +2,33 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('clears the currently selected clipboard') def get_description(self):
return _("clears the currently selected clipboard")
def run(self): def run(self):
self.env['runtime']['memoryManager'].clearCurrentIndexList('clipboardHistory') self.env["runtime"]["MemoryManager"].clear_current_index_list(
self.env['runtime']['outputManager'].presentText(_('clipboard cleared'), interrupt=True) "clipboardHistory"
return )
def setCallback(self, callback): self.env["runtime"]["OutputManager"].present_text(
_("clipboard cleared"), interrupt=True
)
return
def set_callback(self, callback):
pass pass

View File

@ -2,25 +2,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Turn off window mode for application') def get_description(self):
return _("Turn off window mode for application")
def run(self):
if self.env['runtime']['cursorManager'].clearWindowForApplication(): def run(self):
currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if self.env["runtime"]["CursorManager"].clear_window_for_application():
self.env['runtime']['outputManager'].presentText(_('Window Mode off for application {0}').format(currApp,), interrupt=True) curr_app = self.env["runtime"][
else: "ApplicationManager"
self.env['runtime']['outputManager'].presentText(_("Not in window Mode"), interrupt=True) ].get_current_application()
self.env["runtime"]["OutputManager"].present_text(
def setCallback(self, callback): _("Window Mode off for application {0}").format(
curr_app,
),
interrupt=True,
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("Not in window Mode"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,26 +2,35 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils from fenrirscreenreader.utils import mark_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('copies last presented text to the clipboard')
def run(self):
lastEcho = self.env['runtime']['outputManager'].getLastEcho()
if lastEcho.rstrip() != "":
lastEcho = lastEcho.rstrip()
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', lastEcho)
self.env['runtime']['outputManager'].presentText(lastEcho, soundIcon='CopyToClipboard', interrupt=True)
def setCallback(self, callback): def shutdown(self):
pass
def get_description(self):
return _("copies last presented text to the clipboard")
def run(self):
last_echo = self.env["runtime"]["OutputManager"].get_last_echo()
if last_echo.rstrip() != "":
last_echo = last_echo.rstrip()
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
"clipboardHistory", last_echo
)
self.env["runtime"]["OutputManager"].present_text(
last_echo, sound_icon="CopyToClipboard", interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,72 +2,81 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils from fenrirscreenreader.utils import mark_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self): def get_description(self):
return _('copies marked text to the currently selected clipboard') return _("copies marked text to the currently selected clipboard")
def getTextFromScreen(self, startMark, endMark): def get_text_from_screen(self, start_mark, end_mark):
screenContent = self.env['screen']['newContentText'] screen_content = self.env["screen"]["new_content_text"]
screenLines = screenContent.split('\n') screen_lines = screen_content.split("\n")
startY = min(startMark['y'], len(screenLines) - 1) start_y = min(start_mark["y"], len(screen_lines) - 1)
endY = min(endMark['y'], len(screenLines) - 1) end_y = min(end_mark["y"], len(screen_lines) - 1)
# If marks are on the same line # If marks are on the same line
if startY == endY: if start_y == end_y:
line = screenLines[startY] line = screen_lines[start_y]
startX = min(startMark['x'], len(line)) start_x = min(start_mark["x"], len(line))
endX = min(endMark['x'], len(line)) + 1 end_x = min(end_mark["x"], len(line)) + 1
return line[startX:endX] return line[start_x:end_x]
# Handle multi-line selection # Handle multi-line selection
result = [] result = []
# First line (from start mark to end of line) # First line (from start mark to end of line)
firstLine = screenLines[startY] first_line = screen_lines[start_y]
startX = min(startMark['x'], len(firstLine)) start_x = min(start_mark["x"], len(first_line))
result.append(firstLine[startX:].rstrip()) result.append(first_line[start_x:].rstrip())
# Middle lines (complete lines) # Middle lines (complete lines)
for lineNum in range(startY + 1, endY): for lineNum in range(start_y + 1, end_y):
result.append(screenLines[lineNum].rstrip()) result.append(screen_lines[lineNum].rstrip())
# Last line (from start to end mark) # Last line (from start to end mark)
if endY > startY: if end_y > start_y:
lastLine = screenLines[endY] last_line = screen_lines[end_y]
endX = min(endMark['x'], len(lastLine)) + 1 end_x = min(end_mark["x"], len(last_line)) + 1
result.append(lastLine[:endX].rstrip()) result.append(last_line[:end_x].rstrip())
return '\n'.join(result) return "\n".join(result)
def run(self): def run(self):
if not self.env['commandBuffer']['Marks']['1']: if not self.env["commandBuffer"]["Marks"]["1"]:
self.env['runtime']['outputManager'].presentText(_("One or two marks are needed"), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("One or two marks are needed"), interrupt=True
)
return return
if not self.env['commandBuffer']['Marks']['2']: if not self.env["commandBuffer"]["Marks"]["2"]:
self.env['runtime']['cursorManager'].setMark() self.env["runtime"]["CursorManager"].set_mark()
# use the last first and the last setted mark as range # use the last first and the last setted mark as range
startMark = self.env['commandBuffer']['Marks']['1'].copy() start_mark = self.env["commandBuffer"]["Marks"]["1"].copy()
endMark = self.env['commandBuffer']['Marks']['2'].copy() end_mark = self.env["commandBuffer"]["Marks"]["2"].copy()
# Replace mark_utils.getTextBetweenMarks with our new method # Replace mark_utils.get_text_between_marks with our new method
marked = self.getTextFromScreen(startMark, endMark) marked = self.get_text_from_screen(start_mark, end_mark)
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', marked) self.env["runtime"]["MemoryManager"].add_value_to_first_index(
"clipboardHistory", marked
)
# reset marks # reset marks
self.env['runtime']['cursorManager'].clearMarks() self.env["runtime"]["CursorManager"].clear_marks()
self.env['runtime']['outputManager'].presentText(marked, soundIcon='CopyToClipboard', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
marked, sound_icon="CopyToClipboard", interrupt=True
def setCallback(self, callback): )
def set_callback(self, callback):
pass pass

View File

@ -2,25 +2,39 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('speaks the contents of the currently selected clipboard') def get_description(self):
return _("speaks the contents of the currently selected clipboard")
def run(self): def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): if self.env["runtime"]["MemoryManager"].is_index_list_empty(
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) "clipboardHistory"
return ):
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText(clipboard , interrupt=True) _("clipboard empty"), interrupt=True
)
def setCallback(self, callback): return
clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
self.env["runtime"]["OutputManager"].present_text(
clipboard, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,24 +2,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('reads the contents of the current screen') def get_description(self):
return _("reads the contents of the current screen")
def run(self): def run(self):
if self.env['screen']['newContentText'].isspace(): if self.env["screen"]["new_content_text"].isspace():
self.env['runtime']['outputManager'].presentText(_("screen is empty"), soundIcon='EmptyLine', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
else: _("screen is empty"), sound_icon="EmptyLine", interrupt=True
self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'],interrupt=True) )
else:
def setCallback(self, callback): self.env["runtime"]["OutputManager"].present_text(
self.env["screen"]["new_content_text"], interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,30 +2,43 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils from fenrirscreenreader.utils import mark_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('reads from the cursor to the bottom of the screen') def get_description(self):
return _("reads from the cursor to the bottom of the screen")
def run(self): def run(self):
# Prefer review cursor over text cursor # Prefer review cursor over text cursor
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
textAfterCursor = mark_utils.getTextAfterMark(cursorPos, self.env['screen']['newContentText']) text_after_cursor = mark_utils.get_text_after_mark(
cursor_pos, self.env["screen"]["new_content_text"]
)
if textAfterCursor.isspace(): if text_after_cursor.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else: else:
self.env['runtime']['outputManager'].presentText(textAfterCursor, interrupt=True) self.env["runtime"]["OutputManager"].present_text(
text_after_cursor, interrupt=True
)
def setCallback(self, callback): def set_callback(self, callback):
pass pass

View File

@ -2,34 +2,44 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils from fenrirscreenreader.utils import mark_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Reads from the top of the screen to the cursor position') def get_description(self):
return _("Reads from the top of the screen to the cursor position")
def run(self): def run(self):
# Prefer review cursor over text cursor # Prefer review cursor over text cursor
if self.env['screen']['newCursorReview']: if self.env["screen"]["newCursorReview"]:
cursorPos = self.env['screen']['newCursorReview'].copy() cursor_pos = self.env["screen"]["newCursorReview"].copy()
else: else:
cursorPos = self.env['screen']['newCursor'].copy() cursor_pos = self.env["screen"]["new_cursor"].copy()
textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screen']['newContentText']) text_before_cursor = mark_utils.get_text_before_mark(
cursor_pos, self.env["screen"]["new_content_text"]
)
if textBeforeCursor.isspace(): if text_before_cursor.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else: else:
self.env['runtime']['outputManager'].presentText(textBeforeCursor, interrupt=True) self.env["runtime"]["OutputManager"].present_text(
text_before_cursor, interrupt=True
def setCallback(self, callback): )
def set_callback(self, callback):
pass pass

View File

@ -2,24 +2,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get current quick menu entry') def get_description(self):
def run(self): return _("get current quick menu entry")
menu = ''
value = '' def run(self):
menu = self.env['runtime']['quickMenuManager'].getCurrentEntry() menu = ""
if menu != '': value = ""
value = self.env['runtime']['quickMenuManager'].getCurrentValue() menu = self.env["runtime"]["QuickMenuManager"].get_current_entry()
self.env['runtime']['outputManager'].presentText(menu + ' ' + value, interrupt=True) if menu != "":
def setCallback(self, callback): value = self.env["runtime"]["QuickMenuManager"].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
menu + " " + value, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,20 +2,30 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get current quick menu value') def get_description(self):
def run(self): return _("get current quick menu value")
value = self.env['runtime']['quickMenuManager'].getCurrentValue()
self.env['runtime']['outputManager'].presentText(value, interrupt=True) def run(self):
def setCallback(self, callback): value = self.env["runtime"]["QuickMenuManager"].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
value, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,23 +2,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Column number for cursor') def get_description(self):
return _("Column number for cursor")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['runtime']['outputManager'].presentText(str(cursorPos['x'] + 1) , interrupt=True) "CursorManager"
self.env['runtime']['outputManager'].announceActiveCursor() ].get_review_or_text_cursor()
self.env['runtime']['outputManager'].presentText(' column number' , interrupt=False) self.env["runtime"]["OutputManager"].present_text(
str(cursor_pos["x"] + 1), interrupt=True
def setCallback(self, callback): )
self.env["runtime"]["OutputManager"].announce_active_cursor()
self.env["runtime"]["OutputManager"].present_text(
" column number", interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,23 +2,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Line number for cursor') def get_description(self):
return _("Line number for cursor")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['runtime']['outputManager'].presentText(str(cursorPos['y'] + 1), interrupt=True) "CursorManager"
self.env['runtime']['outputManager'].announceActiveCursor() ].get_review_or_text_cursor()
self.env['runtime']['outputManager'].presentText(' line number' , interrupt=False) self.env["runtime"]["OutputManager"].present_text(
str(cursor_pos["y"] + 1), interrupt=True
def setCallback(self, callback): )
self.env["runtime"]["OutputManager"].announce_active_cursor()
self.env["runtime"]["OutputManager"].present_text(
" line number", interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,24 +2,39 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('displays the position of the review cursor') def get_description(self):
return _("displays the position of the review cursor")
def run(self): def run(self):
# Prefer review cursor over text cursor # Prefer review cursor over text cursor
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
self.env['runtime']['outputManager'].presentText(_("line {0}, column {1}, Terminal {2}").format(cursorPos['y']+1, cursorPos['x']+1, self.env['screen']['newTTY']), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("line {0}, column {1}, Terminal {2}").format(
def setCallback(self, callback): cursor_pos["y"] + 1,
cursor_pos["x"] + 1,
self.env["screen"]["newTTY"],
),
interrupt=True,
)
def set_callback(self, callback):
pass pass

View File

@ -2,31 +2,47 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('read line to cursor pos, use review cursor if you are in review mode, otherwhise use text cursor')
def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
x, y, currLine = \ def shutdown(self):
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(currLine[:cursorPos['x']], interrupt=True)
self.env['runtime']['outputManager'].announceActiveCursor()
def setCallback(self, callback):
pass pass
def get_description(self):
return _(
"read line to cursor pos, use review cursor if you are in review mode, otherwhise use text cursor"
)
def run(self):
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
x, y, curr_line = line_utils.get_current_line(
cursor_pos["x"],
cursor_pos["y"],
self.env["screen"]["new_content_text"],
)
if curr_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
curr_line[: cursor_pos["x"]], interrupt=True
)
self.env["runtime"]["OutputManager"].announce_active_cursor()
def set_callback(self, callback):
pass

View File

@ -2,31 +2,47 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('read to end of line, use review cursor if you are in review mode, otherwhise use text cursor')
def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
x, y, currLine = \ def shutdown(self):
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(currLine[cursorPos['x']:], interrupt=True)
self.env['runtime']['outputManager'].announceActiveCursor()
def setCallback(self, callback):
pass pass
def get_description(self):
return _(
"read to end of line, use review cursor if you are in review mode, otherwhise use text cursor"
)
def run(self):
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
x, y, curr_line = line_utils.get_current_line(
cursor_pos["x"],
cursor_pos["y"],
self.env["screen"]["new_content_text"],
)
if curr_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
curr_line[cursor_pos["x"] :], interrupt=True
)
self.env["runtime"]["OutputManager"].announce_active_cursor()
def set_callback(self, callback):
pass

View File

@ -2,60 +2,75 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core import debug
import os import os
class command(): from fenrirscreenreader.core import debug
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('cycles between available keyboard layouts') def get_description(self):
return _("cycles between available keyboard layouts")
def getAvailableLayouts(self):
def get_available_layouts(self):
"""Get list of available keyboard layout files""" """Get list of available keyboard layout files"""
layouts = [] layouts = []
# Check standard locations for keyboard layouts # Check standard locations for keyboard layouts
settingsRoot = '/etc/fenrirscreenreader/' settings_root = "/etc/fenrirscreenreader/"
if not os.path.exists(settingsRoot): if not os.path.exists(settings_root):
# Fallback to source directory # Fallback to source directory
import fenrirscreenreader import fenrirscreenreader
fenrirPath = os.path.dirname(fenrirscreenreader.__file__)
settingsRoot = fenrirPath + '/../../config/' fenrir_path = os.path.dirname(fenrirscreenreader.__file__)
settings_root = fenrir_path + "/../../config/"
keyboardPath = settingsRoot + 'keyboard/'
keyboard_path = settings_root + "keyboard/"
if os.path.exists(keyboardPath):
for file in os.listdir(keyboardPath): if os.path.exists(keyboard_path):
if file.endswith('.conf') and not file.startswith('__') and not file.lower().startswith('pty'): for file in os.listdir(keyboard_path):
layout_name = file.replace('.conf', '') if (
file.endswith(".conf")
and not file.startswith("__")
and not file.lower().startswith("pty")
):
layout_name = file.replace(".conf", "")
if layout_name not in layouts: if layout_name not in layouts:
layouts.append(layout_name) layouts.append(layout_name)
# Ensure we have at least basic layouts # Ensure we have at least basic layouts
if not layouts: if not layouts:
layouts = ['desktop', 'laptop'] layouts = ["desktop", "laptop"]
else: else:
layouts.sort() layouts.sort()
return layouts return layouts
def run(self): def run(self):
current_layout = self.env['runtime']['settingsManager'].getSetting('keyboard', 'keyboardLayout') current_layout = self.env["runtime"]["SettingsManager"].get_setting(
"keyboard", "keyboardLayout"
)
# Extract layout name from full path if needed # Extract layout name from full path if needed
if '/' in current_layout: if "/" in current_layout:
current_layout = os.path.basename(current_layout).replace('.conf', '') current_layout = os.path.basename(current_layout).replace(
".conf", ""
)
# Get available layouts # Get available layouts
available_layouts = self.getAvailableLayouts() available_layouts = self.get_available_layouts()
# Find next layout in cycle # Find next layout in cycle
try: try:
current_index = available_layouts.index(current_layout) current_index = available_layouts.index(current_layout)
@ -63,28 +78,28 @@ class command():
except ValueError: except ValueError:
# If current layout not found, start from beginning # If current layout not found, start from beginning
next_index = 0 next_index = 0
next_layout = available_layouts[next_index] next_layout = available_layouts[next_index]
# Update setting and reload shortcuts # Update setting and reload shortcuts
self.env['runtime']['settingsManager'].setSetting('keyboard', 'keyboardLayout', next_layout) self.env["runtime"]["SettingsManager"].set_setting(
"keyboard", "keyboardLayout", next_layout
)
# Reload shortcuts with new layout # Reload shortcuts with new layout
try: try:
self.env['runtime']['inputManager'].reloadShortcuts() self.env["runtime"]["InputManager"].reload_shortcuts()
self.env['runtime']['outputManager'].presentText( self.env["runtime"]["OutputManager"].present_text(
_('Switched to {} keyboard layout').format(next_layout), _("Switched to {} keyboard layout").format(next_layout),
interrupt=True interrupt=True,
) )
except Exception as e: except Exception as e:
self.env['runtime']['debug'].writeDebugOut( self.env["runtime"]["DebugManager"].write_debug_out(
"Error reloading shortcuts: " + str(e), "Error reloading shortcuts: " + str(e), debug.DebugLevel.ERROR
debug.debugLevel.ERROR
) )
self.env['runtime']['outputManager'].presentText( self.env["runtime"]["OutputManager"].present_text(
_('Error switching keyboard layout'), _("Error switching keyboard layout"), interrupt=True
interrupt=True
) )
def setCallback(self, callback): def set_callback(self, callback):
pass pass

View File

@ -2,28 +2,41 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import datetime import datetime
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('presents the date') def get_description(self):
return _("presents the date")
def run(self): def run(self):
dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') date_format = self.env["runtime"]["SettingsManager"].get_setting(
"general", "date_format"
)
# get the time formatted # get the time formatted
dateString = datetime.datetime.strftime(datetime.datetime.now(), dateFormat) date_string = datetime.datetime.strftime(
datetime.datetime.now(), date_format
)
# present the time via speak and braile, there is no soundicon, interrupt the current speech # present the time via speak and braile, there is no soundicon,
self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=True) # interrupt the current speech
self.env["runtime"]["OutputManager"].present_text(
date_string, sound_icon="", interrupt=True
)
def setCallback(self, callback): def set_callback(self, callback):
pass pass

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('alsa', 'volume', 'dec') super().__init__("alsa", "volume", "dec")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('sound', 'volume', 'dec') super().__init__("sound", "volume", "dec")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'pitch', 'dec') super().__init__("speech", "pitch", "dec")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'rate', 'dec') super().__init__("speech", "rate", "dec")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'volume', 'dec') super().__init__("speech", "volume", "dec")

View File

@ -2,26 +2,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('exits review mode')
def run(self):
if not self.env['runtime']['cursorManager'].isReviewMode():
self.env['runtime']['outputManager'].presentText(_("Not in Review Mode"), interrupt=True)
return
self.env['runtime']['cursorManager'].clearReviewCursor() def shutdown(self):
self.env['runtime']['outputManager'].presentText(_("Exiting Review Mode"), interrupt=True) pass
def setCallback(self, callback): def get_description(self):
return _("exits review mode")
def run(self):
if not self.env["runtime"]["CursorManager"].is_review_mode():
self.env["runtime"]["OutputManager"].present_text(
_("Not in Review Mode"), interrupt=True
)
return
self.env["runtime"]["CursorManager"].clear_review_cursor()
self.env["runtime"]["OutputManager"].present_text(
_("Exiting Review Mode"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,38 +2,66 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core import debug
import os import os
class command(): from fenrirscreenreader.core import debug
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment, scriptPath=''):
def initialize(self, environment, script_path=""):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('export the current fenrir clipboard to a file') def get_description(self):
def run(self): return _("export the current fenrir clipboard to a file")
clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath')
clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) def run(self):
clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) clipboard_file_path = self.env["runtime"][
clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) "SettingsManager"
clipboardFile = open(clipboardFilePath,'w') ].get_setting("general", "clipboardExportPath")
clipboard_file_path = clipboard_file_path.replace(
"$user", self.env["general"]["curr_user"]
)
clipboard_file_path = clipboard_file_path.replace(
"$USER", self.env["general"]["curr_user"]
)
clipboard_file_path = clipboard_file_path.replace(
"$User", self.env["general"]["curr_user"]
)
clipboard_file = open(clipboard_file_path, "w")
try: try:
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): if self.env["runtime"]["MemoryManager"].is_index_list_empty(
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) "clipboardHistory"
return ):
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
clipboardFile.write(clipboard) _("clipboard empty"), interrupt=True
clipboardFile.close() )
os.chmod(clipboardFilePath, 0o666) return
self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True) clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
clipboard_file.write(clipboard)
clipboard_file.close()
os.chmod(clipboard_file_path, 0o644)
self.env["runtime"]["OutputManager"].present_text(
_("clipboard exported to file"), interrupt=True
)
except Exception as e: except Exception as e:
self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR) self.env["runtime"]["DebugManager"].write_debug_out(
"export_clipboard_to_file:run: Filepath:"
def setCallback(self, callback): + clipboard_file
+ " trace:"
+ str(e),
debug.DebugLevel.ERROR,
)
def set_callback(self, callback):
pass pass

View File

@ -2,69 +2,95 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib
import _thread import _thread
import importlib
import os
import pyperclip import pyperclip
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment, scriptPath=''):
def initialize(self, environment, script_path=""):
self.env = environment self.env = environment
self.scriptPath = scriptPath self.script_path = script_path
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Export current fenrir clipboard to X or GUI clipboard') def get_description(self):
def run(self): return _("Export current fenrir clipboard to X or GUI clipboard")
_thread.start_new_thread(self._threadRun , ())
def _threadRun(self): def run(self):
_thread.start_new_thread(self._thread_run, ())
def _thread_run(self):
try: try:
# Check if clipboard is empty # Check if clipboard is empty
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): if self.env["runtime"]["MemoryManager"].is_index_list_empty(
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) "clipboardHistory"
):
self.env["runtime"]["OutputManager"].present_text(
_("clipboard empty"), interrupt=True
)
return return
# Get current clipboard content # Get current clipboard content
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
# Remember original display environment variable if it exists # Remember original display environment variable if it exists
originalDisplay = os.environ.get('DISPLAY', '') original_display = os.environ.get("DISPLAY", "")
success = False success = False
# Try different display options # Try different display options
for i in range(10): for i in range(10):
display = f":{i}" display = f":{i}"
try: try:
# Set display environment variable # Set display environment variable
os.environ['DISPLAY'] = display os.environ["DISPLAY"] = display
# Attempt to set clipboard content # Attempt to set clipboard content
importlib.reload(pyperclip) # Weird workaround for some distros # Weird workaround for some distros
importlib.reload(pyperclip)
pyperclip.copy(clipboard) pyperclip.copy(clipboard)
# If we get here without exception, we found a working display # If we get here without exception, we found a working
# display
success = True success = True
break break
except Exception: except Exception:
# Failed for this display, try next one # Failed for this display, try next one
continue continue
# Restore original display setting # Restore original display setting
if originalDisplay: if original_display:
os.environ['DISPLAY'] = originalDisplay os.environ["DISPLAY"] = original_display
else: else:
os.environ.pop('DISPLAY', None) os.environ.pop("DISPLAY", None)
# Notify the user of the result # Notify the user of the result
if success: if success:
self.env['runtime']['outputManager'].presentText(_('exported to the X session.'), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("exported to the X session."), interrupt=True
)
else: else:
self.env['runtime']['outputManager'].presentText(_('failed to export to X clipboard. No available display found.'), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_(
"failed to export to X clipboard. No available display found."
),
interrupt=True,
)
except Exception as e: except Exception as e:
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False) self.env["runtime"]["OutputManager"].present_text(
str(e), sound_icon="", interrupt=False
def setCallback(self, callback): )
def set_callback(self, callback):
pass pass

View File

@ -2,26 +2,42 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('selects the first clipboard') def get_description(self):
return _("selects the first clipboard")
def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): def run(self):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) if self.env["runtime"]["MemoryManager"].is_index_list_empty(
return "clipboardHistory"
self.env['runtime']['memoryManager'].setFirstIndex('clipboardHistory') ):
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True) _("clipboard empty"), interrupt=True
)
def setCallback(self, callback): return
self.env["runtime"]["MemoryManager"].set_first_index(
"clipboardHistory"
)
clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
self.env["runtime"]["OutputManager"].present_text(
clipboard, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,22 +2,30 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('sends the following keypress to the terminal or application')
def run(self):
self.env['input']['keyForeward'] = 3
self.env['runtime']['outputManager'].presentText(_('Forward next keypress'), interrupt=True)
def setCallback(self, callback): def shutdown(self):
pass
def get_description(self):
return _("sends the following keypress to the terminal or application")
def run(self):
self.env["input"]["keyForeward"] = 3
self.env["runtime"]["OutputManager"].present_text(
_("Forward next keypress"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,37 +2,58 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.utils import mark_utils
import os import os
class command(): from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('imports text from clipboard file to the clipboard') def get_description(self):
return _("imports text from clipboard file to the clipboard")
def run(self):
clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath') def run(self):
clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) clipboard_file_path = self.env["runtime"][
clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) "SettingsManager"
clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) ].get_setting("general", "clipboardExportPath")
if not os.path.exists(clipboardFilePath): clipboard_file_path = clipboard_file_path.replace(
self.env['runtime']['outputManager'].presentText(_('File does not exist'), soundIcon='', interrupt=True) "$user", self.env["general"]["curr_user"]
return )
clipboardFile = open(clipboardFilePath,'r') clipboard_file_path = clipboard_file_path.replace(
imported = clipboardFile.read() "$USER", self.env["general"]["curr_user"]
clipboardFile.close() )
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', imported) clipboard_file_path = clipboard_file_path.replace(
"$User", self.env["general"]["curr_user"]
self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True) )
self.env['runtime']['outputManager'].presentText(imported, soundIcon='', interrupt=False) if not os.path.exists(clipboard_file_path):
self.env["runtime"]["OutputManager"].present_text(
_("File does not exist"), sound_icon="", interrupt=True
def setCallback(self, callback): )
return
clipboard_file = open(clipboard_file_path, "r")
imported = clipboard_file.read()
clipboard_file.close()
self.env["runtime"]["MemoryManager"].add_value_to_first_index(
"clipboardHistory", imported
)
self.env["runtime"]["OutputManager"].present_text(
"Import to Clipboard", sound_icon="CopyToClipboard", interrupt=True
)
self.env["runtime"]["OutputManager"].present_text(
imported, sound_icon="", interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,62 +2,86 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import importlib
import _thread import _thread
import pyperclip import importlib
import os import os
class command(): import pyperclip
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment, scriptPath=''):
def initialize(self, environment, script_path=""):
self.env = environment self.env = environment
self.scriptPath = scriptPath self.script_path = script_path
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
def get_description(self):
return _("imports the graphical clipboard to Fenrir's clipboard") return _("imports the graphical clipboard to Fenrir's clipboard")
def run(self):
_thread.start_new_thread(self._threadRun , ()) def run(self):
def _threadRun(self): _thread.start_new_thread(self._thread_run, ())
def _thread_run(self):
try: try:
# Remember original display environment variable if it exists # Remember original display environment variable if it exists
originalDisplay = os.environ.get('DISPLAY', '') original_display = os.environ.get("DISPLAY", "")
clipboardContent = None clipboard_content = None
# Try different display options # Try different display options
for i in range(10): for i in range(10):
display = f":{i}" display = f":{i}"
try: try:
# Set display environment variable # Set display environment variable
os.environ['DISPLAY'] = display os.environ["DISPLAY"] = display
# Attempt to get clipboard content # Attempt to get clipboard content
importlib.reload(pyperclip) # Weird workaround for some distros # Weird workaround for some distros
clipboardContent = pyperclip.paste() importlib.reload(pyperclip)
# If we get here without exception, we found a working display clipboard_content = pyperclip.paste()
if clipboardContent: # If we get here without exception, we found a working
# display
if clipboard_content:
break break
except Exception: except Exception:
# Failed for this display, try next one # Failed for this display, try next one
continue continue
# Restore original display setting # Restore original display setting
if originalDisplay: if original_display:
os.environ['DISPLAY'] = originalDisplay os.environ["DISPLAY"] = original_display
else: else:
os.environ.pop('DISPLAY', None) os.environ.pop("DISPLAY", None)
# Process the clipboard content if we found any # Process the clipboard content if we found any
if clipboardContent and isinstance(clipboardContent, str): if clipboard_content and isinstance(clipboard_content, str):
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', clipboardContent) self.env["runtime"]["MemoryManager"].add_value_to_first_index(
self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True) "clipboardHistory", clipboard_content
self.env['runtime']['outputManager'].presentText(clipboardContent, soundIcon='', interrupt=False) )
self.env["runtime"]["OutputManager"].present_text(
"Import to Clipboard",
sound_icon="CopyToClipboard",
interrupt=True,
)
self.env["runtime"]["OutputManager"].present_text(
clipboard_content, sound_icon="", interrupt=False
)
else: else:
self.env['runtime']['outputManager'].presentText('No text found in clipboard or no accessible display', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
"No text found in clipboard or no accessible display",
interrupt=True,
)
except Exception as e: except Exception as e:
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False) self.env["runtime"]["OutputManager"].present_text(
str(e), sound_icon="", interrupt=False
def setCallback(self, callback): )
def set_callback(self, callback):
pass pass

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('alsa', 'volume', 'inc') super().__init__("alsa", "volume", "inc")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('sound', 'volume', 'inc') super().__init__("sound", "volume", "inc")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'pitch', 'inc') super().__init__("speech", "pitch", "inc")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'rate', 'inc') super().__init__("speech", "rate", "inc")

View File

@ -2,16 +2,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import os
import importlib.util import importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') import os
from fenrirscreenreader.core.i18n import _
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path) _spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
_module = importlib.util.module_from_spec(_spec) _module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module) _spec.loader.exec_module(_module)
AdjustmentCommand = _module.AdjustmentCommand adjustment_command = _module.adjustment_command
class command(AdjustmentCommand):
class command(adjustment_command):
def __init__(self): def __init__(self):
super().__init__('speech', 'volume', 'inc') super().__init__("speech", "volume", "inc")

View File

@ -2,34 +2,49 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Presents the indentation level for the current line') def get_description(self):
return _("Presents the indentation level for the current line")
def run(self): def run(self):
# Prefer review cursor over text cursor # Prefer review cursor over text cursor
if self.env['screen']['newCursorReview']: if self.env["screen"]["newCursorReview"]:
cursorPos = self.env['screen']['newCursorReview'].copy() cursor_pos = self.env["screen"]["newCursorReview"].copy()
else: else:
cursorPos = self.env['screen']['newCursor'].copy() cursor_pos = self.env["screen"]["new_cursor"].copy()
x, y, currLine = \ x, y, curr_line = line_utils.get_current_line(
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) cursor_pos["x"],
cursor_pos["y"],
if currLine.isspace(): self.env["screen"]["new_content_text"],
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) )
else:
self.env['runtime']['outputManager'].presentText(_("indent {0}").format(len(currLine) - len(currLine.lstrip())), interrupt=True)
def setCallback(self, callback): if curr_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("indent {0}").format(
len(curr_line) - len(curr_line.lstrip())
),
interrupt=True,
)
def set_callback(self, callback):
pass pass

View File

@ -2,26 +2,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('selects the last clipboard') def get_description(self):
return _("selects the last clipboard")
def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): def run(self):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) if self.env["runtime"]["MemoryManager"].is_index_list_empty(
return "clipboardHistory"
self.env['runtime']['memoryManager'].setLastIndex('clipboardHistory') ):
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True) _("clipboard empty"), interrupt=True
)
def setCallback(self, callback): return
self.env["runtime"]["MemoryManager"].set_last_index("clipboardHistory")
clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
self.env["runtime"]["OutputManager"].present_text(
clipboard, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,36 +2,53 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils from fenrirscreenreader.utils import mark_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Presents the currently selected text that will be copied to the clipboard') def get_description(self):
return _(
"Presents the currently selected text that will be copied to the clipboard"
)
def run(self): def run(self):
if not (self.env['commandBuffer']['Marks']['1'] and \ if not (
self.env['commandBuffer']['Marks']['2']): self.env["commandBuffer"]["Marks"]["1"]
self.env['runtime']['outputManager'].presentText(_("please set begin and endmark"), interrupt=True) and self.env["commandBuffer"]["Marks"]["2"]
):
self.env["runtime"]["OutputManager"].present_text(
_("please set begin and endmark"), interrupt=True
)
return return
# use the last first and the last setted mark as range # use the last first and the last setted mark as range
startMark = self.env['commandBuffer']['Marks']['1'].copy() start_mark = self.env["commandBuffer"]["Marks"]["1"].copy()
endMark = self.env['commandBuffer']['Marks']['2'].copy() end_mark = self.env["commandBuffer"]["Marks"]["2"].copy()
marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) marked = mark_utils.get_text_between_marks(
start_mark, end_mark, self.env["screen"]["new_content_text"]
)
if marked.isspace(): if marked.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else: else:
self.env['runtime']['outputManager'].presentText(marked, interrupt=True) self.env["runtime"]["OutputManager"].present_text(
marked, interrupt=True
def setCallback(self, callback): )
def set_callback(self, callback):
pass pass

View File

@ -2,34 +2,56 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('selects the next clipboard') def get_description(self):
return _("selects the next clipboard")
def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): def run(self):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) if self.env["runtime"]["MemoryManager"].is_index_list_empty(
return "clipboardHistory"
self.env['runtime']['memoryManager'].getNextIndex('clipboardHistory') ):
isFirst = self.env['runtime']['memoryManager'].isFirstIndex('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
isLast = self.env['runtime']['memoryManager'].isLastIndex('clipboardHistory') _("clipboard empty"), interrupt=True
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') )
if isFirst: return
self.env['runtime']['outputManager'].presentText(_('First clipboard '), interrupt=True) self.env["runtime"]["MemoryManager"].get_next_index("clipboardHistory")
if isLast: is_first = self.env["runtime"]["MemoryManager"].is_first_index(
self.env['runtime']['outputManager'].presentText(_('Last clipboard '), interrupt=True) "clipboardHistory"
)
speechInterrupt = not(isLast or isFirst) is_last = self.env["runtime"]["MemoryManager"].is_last_index(
self.env['runtime']['outputManager'].presentText(clipboard, interrupt = speechInterrupt) "clipboardHistory"
)
def setCallback(self, callback): clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
if is_first:
self.env["runtime"]["OutputManager"].present_text(
_("First clipboard "), interrupt=True
)
if is_last:
self.env["runtime"]["OutputManager"].present_text(
_("Last clipboard "), interrupt=True
)
speech_interrupt = not (is_last or is_first)
self.env["runtime"]["OutputManager"].present_text(
clipboard, interrupt=speech_interrupt
)
def set_callback(self, callback):
pass pass

View File

@ -2,27 +2,41 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get next quick menu entry') def get_description(self):
def run(self): return _("get next quick menu entry")
menu = ''
value = '' def run(self):
if self.env['runtime']['quickMenuManager'].nextEntry(): menu = ""
menu = self.env['runtime']['quickMenuManager'].getCurrentEntry() value = ""
if menu != '': if self.env["runtime"]["QuickMenuManager"].next_entry():
value = self.env['runtime']['quickMenuManager'].getCurrentValue() menu = self.env["runtime"]["QuickMenuManager"].get_current_entry()
self.env['runtime']['outputManager'].presentText(menu + ' ' + value, interrupt=True) if menu != "":
else: value = self.env["runtime"][
self.env['runtime']['outputManager'].presentText(_('Quick menu not available'), interrupt=True) "QuickMenuManager"
def setCallback(self, callback): ].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
menu + " " + value, interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("Quick menu not available"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,21 +2,31 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get next quick menu value') def get_description(self):
def run(self): return _("get next quick menu value")
if self.env['runtime']['quickMenuManager'].nextValue():
value = self.env['runtime']['quickMenuManager'].getCurrentValue() def run(self):
self.env['runtime']['outputManager'].presentText(value, interrupt=True) if self.env["runtime"]["QuickMenuManager"].next_value():
def setCallback(self, callback): value = self.env["runtime"]["QuickMenuManager"].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
value, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,28 +2,49 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
import time import time
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards')) self.env["runtime"]["MemoryManager"].add_index_list(
"clipboardHistory",
self.env["runtime"]["SettingsManager"].get_setting_as_int(
"general", "numberOfClipboards"
),
)
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('pastes the text from the currently selected clipboard') def get_description(self):
return _("pastes the text from the currently selected clipboard")
def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): def run(self):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) if self.env["runtime"]["MemoryManager"].is_index_list_empty(
return "clipboardHistory"
self.env['runtime']['outputManager'].presentText('paste clipboard', soundIcon='PasteClipboardOnScreen', interrupt=True) ):
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['screenManager'].injectTextToScreen(clipboard) _("clipboard empty"), interrupt=True
)
def setCallback(self, callback): return
self.env["runtime"]["OutputManager"].present_text(
"paste clipboard",
sound_icon="PasteClipboardOnScreen",
interrupt=True,
)
clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
self.env["runtime"]["ScreenManager"].inject_text_to_screen(clipboard)
def set_callback(self, callback):
pass pass

View File

@ -2,28 +2,38 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass
def getDescription(self):
return _('present first line')
def run(self):
x, y, firstLine = \
line_utils.getCurrentLine(0, 0, self.env['screen']['newContentText'])
if firstLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(firstLine, interrupt=True)
def setCallback(self, callback):
pass pass
def get_description(self):
return _("present first line")
def run(self):
x, y, first_line = line_utils.get_current_line(
0, 0, self.env["screen"]["new_content_text"]
)
if first_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
first_line, interrupt=True
)
def set_callback(self, callback):
pass

View File

@ -2,28 +2,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('current line')
def run(self):
x, y, lastLine = \
line_utils.getCurrentLine(0, self.env['screen']['lines'] -1, self.env['screen']['newContentText'])
if lastLine.isspace(): def shutdown(self):
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(lastLine, interrupt=True)
def setCallback(self, callback):
pass pass
def get_description(self):
return _("current line")
def run(self):
x, y, last_line = line_utils.get_current_line(
0,
self.env["screen"]["lines"] - 1,
self.env["screen"]["new_content_text"],
)
if last_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
last_line, interrupt=True
)
def set_callback(self, callback):
pass

View File

@ -2,33 +2,55 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('selects the previous clipboard') def get_description(self):
return _("selects the previous clipboard")
def run(self): def run(self):
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): if self.env["runtime"]["MemoryManager"].is_index_list_empty(
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) "clipboardHistory"
return ):
self.env['runtime']['memoryManager'].setPrefIndex('clipboardHistory') self.env["runtime"]["OutputManager"].present_text(
isFirst = self.env['runtime']['memoryManager'].isFirstIndex('clipboardHistory') _("clipboard empty"), interrupt=True
isLast = self.env['runtime']['memoryManager'].isLastIndex('clipboardHistory') )
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') return
if isFirst: self.env["runtime"]["MemoryManager"].set_pref_index("clipboardHistory")
self.env['runtime']['outputManager'].presentText(_('First clipboard '), interrupt=True) is_first = self.env["runtime"]["MemoryManager"].is_first_index(
if isLast: "clipboardHistory"
self.env['runtime']['outputManager'].presentText(_('Last clipboard '), interrupt=True) )
speechInterrupt = not(isLast or isFirst) is_last = self.env["runtime"]["MemoryManager"].is_last_index(
self.env['runtime']['outputManager'].presentText(clipboard, interrupt = speechInterrupt) "clipboardHistory"
)
def setCallback(self, callback): clipboard = self.env["runtime"][
"MemoryManager"
].get_index_list_element("clipboardHistory")
if is_first:
self.env["runtime"]["OutputManager"].present_text(
_("First clipboard "), interrupt=True
)
if is_last:
self.env["runtime"]["OutputManager"].present_text(
_("Last clipboard "), interrupt=True
)
speech_interrupt = not (is_last or is_first)
self.env["runtime"]["OutputManager"].present_text(
clipboard, interrupt=speech_interrupt
)
def set_callback(self, callback):
pass pass

View File

@ -2,27 +2,41 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get previous quick menu entry') def get_description(self):
def run(self): return _("get previous quick menu entry")
menu = ''
value = '' def run(self):
if self.env['runtime']['quickMenuManager'].prevEntry(): menu = ""
menu = self.env['runtime']['quickMenuManager'].getCurrentEntry() value = ""
if menu != '': if self.env["runtime"]["QuickMenuManager"].prev_entry():
value = self.env['runtime']['quickMenuManager'].getCurrentValue() menu = self.env["runtime"]["QuickMenuManager"].get_current_entry()
self.env['runtime']['outputManager'].presentText(menu + ' ' + value, interrupt=True) if menu != "":
else: value = self.env["runtime"][
self.env['runtime']['outputManager'].presentText(_('Quick menu not available'), interrupt=True) "QuickMenuManager"
def setCallback(self, callback): ].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
menu + " " + value, interrupt=True
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("Quick menu not available"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,21 +2,31 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('get previous quick menu value') def get_description(self):
def run(self): return _("get previous quick menu value")
if self.env['runtime']['quickMenuManager'].prevValue():
value = self.env['runtime']['quickMenuManager'].getCurrentValue() def run(self):
self.env['runtime']['outputManager'].presentText(value, interrupt=True) if self.env["runtime"]["QuickMenuManager"].prev_value():
def setCallback(self, callback): value = self.env["runtime"]["QuickMenuManager"].get_current_value()
self.env["runtime"]["OutputManager"].present_text(
value, interrupt=True
)
def set_callback(self, callback):
pass pass

View File

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

View File

@ -2,22 +2,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('exits Fenrir')
def run(self):
self.env['runtime']['eventManager'].stopMainEventLoop()
def setCallback(self, callback): def shutdown(self):
pass pass
def get_description(self):
return _("exits Fenrir")
def run(self):
self.env["runtime"]["EventManager"].stop_main_event_loop()
def set_callback(self, callback):
pass

View File

@ -2,22 +2,30 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('Removes marks from selected text')
def run(self):
self.env['runtime']['cursorManager'].clearMarks()
self.env['runtime']['outputManager'].presentText(_('Remove marks'), interrupt=True)
def setCallback(self, callback): def shutdown(self):
pass
def get_description(self):
return _("Removes marks from selected text")
def run(self):
self.env["runtime"]["CursorManager"].clear_marks()
self.env["runtime"]["OutputManager"].present_text(
_("Remove marks"), interrupt=True
)
def set_callback(self, callback):
pass pass

View File

@ -2,53 +2,96 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.utils import word_utils
import string import string
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils
initialized = False initialized = False
try: try:
import enchant import enchant
initialized = True initialized = True
except: except Exception as e:
pass pass
class command():
class command:
def __init__(self): def __init__(self):
self.language = '' self.language = ""
self.spellChecker = None self.spellChecker = None
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
self.updateSpellLanguage() self.update_spell_language()
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('removes the current word from the exceptions dictionary') def get_description(self):
def updateSpellLanguage(self): return _("removes the current word from the exceptions dictionary")
self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage'))
self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') def update_spell_language(self):
self.spellChecker = enchant.Dict(
self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
)
self.language = self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
def run(self): def run(self):
if not initialized: if not initialized:
self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) self.env["runtime"]["OutputManager"].present_text(
return _("pyenchant is not installed"), interrupt=True
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: )
return
if (
self.env["runtime"]["SettingsManager"].get_setting(
"general", "spellCheckLanguage"
)
!= self.language
):
try: try:
self.updateSpellLanguage() self.update_spell_language()
except: except Exception as e:
return return
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
# get the word # get the word
newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] new_content = self.env["screen"]["new_content_text"].split("\n")[
x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) cursor_pos["y"]
currWord = currWord.strip(string.whitespace + r'!"#$%&()*+,-./:;<=Â?@[\\]^_{|}~') ]
if not currWord.isspace(): x, y, curr_word, end_of_screen, line_break = (
if self.spellChecker.is_removed(currWord): word_utils.get_current_word(cursor_pos["x"], 0, new_content)
self.env['runtime']['outputManager'].presentText(_('{0} is not in the dictionary').format(currWord,), soundIcon='Cancel', interrupt=True) )
curr_word = curr_word.strip(
string.whitespace + r'!"#$%&()*+,-./:;<=Â?@[\\]^_{|}~'
)
if not curr_word.isspace():
if self.spellChecker.is_removed(curr_word):
self.env["runtime"]["OutputManager"].present_text(
_("{0} is not in the dictionary").format(
curr_word,
),
sound_icon="Cancel",
interrupt=True,
)
else: else:
self.spellChecker.remove(currWord) self.spellChecker.remove(curr_word)
self.env['runtime']['outputManager'].presentText(_('{0} removed').format(currWord,), soundIcon='Accept', interrupt=True) self.env["runtime"]["OutputManager"].present_text(
def setCallback(self, callback): _("{0} removed").format(
curr_word,
),
sound_icon="Accept",
interrupt=True,
)
def set_callback(self, callback):
pass pass

View File

@ -2,22 +2,33 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
class command(): from fenrirscreenreader.core.i18n import _
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Move review to the bottom of the screen') def get_description(self):
return _("Move review to the bottom of the screen")
def run(self): def run(self):
self.env['screen']['newCursorReview'] = { 'x': 0, 'y':self.env['screen']['lines'] -1} self.env["screen"]["newCursorReview"] = {
self.env['runtime']['outputManager'].presentText(_("Bottom"), interrupt=True, flush=False) "x": 0,
"y": self.env["screen"]["lines"] - 1,
}
self.env["runtime"]["OutputManager"].present_text(
_("Bottom"), interrupt=True, flush=False
)
def setCallback(self, callback): def set_callback(self, callback):
pass pass

View File

@ -2,34 +2,75 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('presents the current character.')
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ def shutdown(self):
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) pass
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False) def get_description(self):
# is has attribute it enabled? return _("presents the current character.")
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'):
cursorPos = self.env['screen']['newCursorReview'] def run(self):
self.env["runtime"][
if not self.env['runtime']['attributeManager'].hasAttributes(cursorPos): "CursorManager"
return ].enter_review_mode_curr_text_cursor()
self.env['runtime']['outputManager'].presentText('has attribute', soundIcon='HasAttributes', interrupt=False)
# In table mode, sync to cell start if cursor is outside current cell
def setCallback(self, callback): if self.env["runtime"]["TableManager"].is_table_mode():
table_info = self.env["runtime"]["TableManager"].get_current_table_cell_info()
if table_info:
cursor_pos = self.env["screen"]["newCursorReview"]
line_text = self.env["runtime"]["ScreenManager"].get_line_text(cursor_pos["y"])
if line_text:
column_start = self.env["runtime"]["TableManager"].get_column_start_position(line_text, table_info["column_index"])
cell_content = table_info["cell_content"]
cell_end = column_start + len(cell_content)
# If cursor is outside the current cell, move to cell start
if cursor_pos["x"] < column_start or cursor_pos["x"] >= cell_end:
self.env["screen"]["newCursorReview"]["x"] = column_start
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_char,
) = char_utils.get_current_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
char_utils.present_char_for_review(
self.env,
curr_char,
interrupt=True,
announce_capital=True,
flush=False,
)
# is has attribute it enabled?
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"general", "hasattributes"
):
cursor_pos = self.env["screen"]["newCursorReview"]
if not self.env["runtime"]["AttributeManager"].has_attributes(
cursor_pos
):
return
self.env["runtime"]["OutputManager"].present_text(
"has attribute", sound_icon="HasAttributes", interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,31 +2,49 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('set review and phonetically presents the current character')
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ def shutdown(self):
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) pass
if currChar.isspace(): def get_description(self):
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) return _("set review and phonetically presents the current character")
else:
currChar = char_utils.getPhonetic(currChar) def run(self):
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, announceCapital=True, flush=False) self.env["runtime"][
"CursorManager"
def setCallback(self, callback): ].enter_review_mode_curr_text_cursor()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_char,
) = char_utils.get_current_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
if curr_char.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
else:
curr_char = char_utils.get_phonetic(curr_char)
self.env["runtime"]["OutputManager"].present_text(
curr_char, interrupt=True, announce_capital=True, flush=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,30 +2,48 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('current line')
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currLine = \ def shutdown(self):
line_utils.getCurrentLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False)
else:
self.env['runtime']['outputManager'].presentText(currLine, interrupt=True, flush=False)
def setCallback(self, callback):
pass pass
def get_description(self):
return _("current line")
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_line,
) = line_utils.get_current_line(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
if curr_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True, flush=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
curr_line, interrupt=True, flush=False
)
def set_callback(self, callback):
pass

View File

@ -2,35 +2,95 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils from fenrirscreenreader.utils import word_utils
from fenrirscreenreader.core import debug
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('current word.') def get_description(self):
return _("current word.")
def run(self): def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ (
word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
if currWord.isspace(): curr_word,
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) end_of_screen,
line_break,
) = word_utils.get_current_word(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
# Check if we're in table mode and provide table-aware output
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
self.env["runtime"]["DebugManager"].write_debug_out(
f"review_curr_word: is_table_mode={is_table_mode}",
debug.DebugLevel.INFO
)
if is_table_mode:
# Get current cell info using internal column tracking
table_info = self.env["runtime"]["TableManager"].get_current_table_cell_info()
if table_info:
# Announce with table context - cell content first, then header
output_text = f"{table_info['cell_content']} {table_info['column_header']}"
self.env["runtime"]["OutputManager"].present_text(
output_text, interrupt=True, flush=False
)
return # Exit early for table mode
else:
# Fallback to regular word announcement
if curr_word.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
curr_word, interrupt=True, flush=False
)
else: else:
self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) # Regular word announcement
if endOfScreen: if curr_word.isspace():
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') _("blank"), interrupt=True, flush=False
if lineBreak: )
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): else:
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') self.env["runtime"]["OutputManager"].present_text(
def setCallback(self, callback): curr_word, interrupt=True, flush=False
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
if line_break:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "line_break"
):
self.env["runtime"]["OutputManager"].present_text(
_("line break"), interrupt=False, sound_icon="EndOfLine"
)
def set_callback(self, callback):
pass pass

View File

@ -2,39 +2,73 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.utils import word_utils from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
from fenrirscreenreader.utils import word_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Phonetically spells the current word') def get_description(self):
return _("Phonetically spells the current word")
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() def run(self):
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ self.env["runtime"][
word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) "CursorManager"
].enter_review_mode_curr_text_cursor()
if currWord.isspace(): (
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) self.env["screen"]["newCursorReview"]["x"],
else: self.env["screen"]["newCursorReview"]["y"],
firstSequence = True curr_word,
for c in currWord: end_of_screen,
currChar = char_utils.getPhonetic(c) line_break,
self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) ) = word_utils.get_current_word(
firstSequence = False self.env["screen"]["newCursorReview"]["x"],
if endOfScreen: self.env["screen"]["newCursorReview"]["y"],
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): self.env["screen"]["new_content_text"],
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') )
if lineBreak:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): if curr_word.isspace():
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') self.env["runtime"]["OutputManager"].present_text(
def setCallback(self, callback): _("blank"), interrupt=True, flush=False
)
else:
first_sequence = True
for c in curr_word:
curr_char = char_utils.get_phonetic(c)
self.env["runtime"]["OutputManager"].present_text(
curr_char,
interrupt=first_sequence,
announce_capital=True,
flush=False,
)
first_sequence = False
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
if line_break:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "line_break"
):
self.env["runtime"]["OutputManager"].present_text(
_("line break"), interrupt=False, sound_icon="EndOfLine"
)
def set_callback(self, callback):
pass pass

View File

@ -2,27 +2,55 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Move review to the character below the current position') def get_description(self):
return _("Move review to the character below the current position")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], downChar, endOfScreen = \ "CursorManager"
char_utils.getDownChar(self.env['screen']['newCursorReview']['x'],self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) ].get_review_or_text_cursor()
self.env['runtime']['outputManager'].presentText(downChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) (
if endOfScreen: self.env["screen"]["newCursorReview"]["x"],
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): self.env["screen"]["newCursorReview"]["y"],
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') downChar,
def setCallback(self, callback): end_of_screen,
) = char_utils.get_down_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
self.env["runtime"]["OutputManager"].present_text(
downChar,
interrupt=True,
ignore_punctuation=True,
announce_capital=True,
flush=False,
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
def set_callback(self, callback):
pass pass

View File

@ -2,31 +2,59 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('set review cursor to begin of current line and display the content') def get_description(self):
return _(
"set review cursor to begin of current line and display the content"
)
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['runtime']['cursorManager'].setReviewCursorPosition(0 ,cursorPos['y']) "CursorManager"
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ ].get_review_or_text_cursor()
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) self.env["runtime"]["CursorManager"].set_review_cursor_position(
0, cursor_pos["y"]
if currChar.isspace(): )
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) (
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_char,
) = char_utils.get_current_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
if curr_char.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
else: else:
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) self.env["runtime"]["OutputManager"].present_text(
self.env['runtime']['outputManager'].presentText(_("beginning of line"), interrupt=False) curr_char,
interrupt=True,
def setCallback(self, callback): ignore_punctuation=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("beginning of line"), interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,28 +2,54 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Move Review to the end of current line and display the content') def get_description(self):
return _(
"Move Review to the end of current line and display the content"
)
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) "CursorManager"
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ ].get_review_or_text_cursor()
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) self.env["runtime"]["CursorManager"].set_review_cursor_position(
self.env["screen"]["columns"] - 1, cursor_pos["y"]
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) )
self.env['runtime']['outputManager'].presentText(_("end of line"), interrupt=False) (
self.env["screen"]["newCursorReview"]["x"],
def setCallback(self, callback): self.env["screen"]["newCursorReview"]["y"],
curr_char,
) = char_utils.get_current_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
self.env["runtime"]["OutputManager"].present_text(
curr_char,
interrupt=True,
ignore_punctuation=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("end of line"), interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,34 +2,66 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Move Review to the first character on the line') def get_description(self):
return _("Move Review to the first character on the line")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
x, y, currLine = \ "CursorManager"
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) ].get_review_or_text_cursor()
if currLine.isspace(): x, y, curr_line = line_utils.get_current_line(
self.env['runtime']['outputManager'].presentText(_("line is empty"), interrupt=True) cursor_pos["x"],
return cursor_pos["y"],
self.env['runtime']['cursorManager'].setReviewCursorPosition((len(currLine) - len(currLine.lstrip())), cursorPos['y']) self.env["screen"]["new_content_text"],
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']) if curr_line.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("line is empty"), interrupt=True
)
return
self.env["runtime"]["CursorManager"].set_review_cursor_position(
(len(curr_line) - len(curr_line.lstrip())), cursor_pos["y"]
)
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_char,
) = char_utils.get_current_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False) char_utils.present_char_for_review(
self.env['runtime']['outputManager'].presentText(_("first character in line indent {0}").format(str(len(currLine) - len(currLine.lstrip()))), interrupt=False) self.env,
curr_char,
def setCallback(self, callback): interrupt=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("first character in line indent {0}").format(
str(len(curr_line) - len(curr_line.lstrip()))
),
interrupt=False,
)
def set_callback(self, callback):
pass pass

View File

@ -2,28 +2,51 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
pass pass
def getDescription(self):
return _('Move Review to the last character on the line') def get_description(self):
return _("Move Review to the last character on the line")
def run(self): def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() cursor_pos = self.env["runtime"][
self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) "CursorManager"
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \ ].get_review_or_text_cursor()
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) self.env["runtime"]["CursorManager"].set_review_cursor_position(
self.env["screen"]["columns"] - 1, cursor_pos["y"]
char_utils.presentCharForReview(self.env, lastChar, interrupt=True, announceCapital=True, flush=False) )
self.env['runtime']['outputManager'].presentText(_("last character in line"), interrupt=False) (
self.env["screen"]["newCursorReview"]["x"],
def setCallback(self, callback): self.env["screen"]["newCursorReview"]["y"],
lastChar,
) = char_utils.get_last_char_in_line(
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
char_utils.present_char_for_review(
self.env,
lastChar,
interrupt=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("last character in line"), interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,38 +2,126 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('Moves review to the next character ')
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \
char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
char_utils.presentCharForReview(self.env, nextChar, interrupt=True, announceCapital=True, flush=False) def shutdown(self):
if endOfScreen: pass
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') def get_description(self):
if lineBreak: return _("Moves review to the next character")
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'):
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def run(self):
# is has attribute it enabled? self.env["runtime"][
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'): "CursorManager"
cursorPos = self.env['screen']['newCursorReview'] ].enter_review_mode_curr_text_cursor()
if not self.env['runtime']['attributeManager'].hasAttributes(cursorPos): # Check if we're in table mode for bounded navigation
return if self.env["runtime"]["TableManager"].is_table_mode():
self.env['runtime']['outputManager'].presentText('has attribute', soundIcon='HasAttributes', interrupt=False) table_info = self.env["runtime"]["TableManager"].get_current_table_cell_info()
def setCallback(self, callback): if table_info:
cursor_pos = self.env["screen"]["newCursorReview"]
line_text = self.env["runtime"]["ScreenManager"].get_line_text(cursor_pos["y"])
if line_text:
column_start = self.env["runtime"]["TableManager"].get_column_start_position(line_text, table_info["column_index"])
cell_content = table_info["cell_content"]
cell_end = column_start + len(cell_content)
# Check if we're already at the end of the cell
if cursor_pos["x"] >= cell_end - 1:
# At cell boundary - announce end and don't move
char_utils.present_char_for_review(
self.env,
cell_content[-1] if cell_content else "",
interrupt=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("end of cell"), interrupt=False, sound_icon="EndOfLine"
)
return
# Move within cell bounds
relative_pos = cursor_pos["x"] - column_start
if relative_pos < len(cell_content) - 1:
new_relative_pos = relative_pos + 1
self.env["screen"]["newCursorReview"]["x"] = column_start + new_relative_pos
# Get character at new position
if new_relative_pos < len(cell_content):
next_char = cell_content[new_relative_pos]
else:
next_char = ""
char_utils.present_char_for_review(
self.env,
next_char,
interrupt=True,
announce_capital=True,
flush=False,
)
return
# Regular navigation for non-table mode
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
next_char,
end_of_screen,
line_break,
) = char_utils.get_next_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
char_utils.present_char_for_review(
self.env,
next_char,
interrupt=True,
announce_capital=True,
flush=False,
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
if line_break:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "line_break"
):
self.env["runtime"]["OutputManager"].present_text(
_("line break"), interrupt=False, sound_icon="EndOfLine"
)
# is has attribute it enabled?
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"general", "hasattributes"
):
cursor_pos = self.env["screen"]["newCursorReview"]
if not self.env["runtime"]["AttributeManager"].has_attributes(
cursor_pos
):
return
self.env["runtime"]["OutputManager"].present_text(
"has attribute", sound_icon="HasAttributes", interrupt=False
)
def set_callback(self, callback):
pass pass

View File

@ -2,33 +2,64 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import char_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('phonetically presents the next character and set review to it')
def run(self):
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ def shutdown(self):
char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) pass
nextChar = char_utils.getPhonetic(nextChar) def get_description(self):
self.env['runtime']['outputManager'].presentText(nextChar ,interrupt=True, announceCapital=True, flush=False) return _(
if endOfScreen: "phonetically presents the next character and set review to it"
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): )
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
if lineBreak: def run(self):
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): self.env["runtime"][
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') "CursorManager"
def setCallback(self, callback): ].enter_review_mode_curr_text_cursor()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
next_char,
end_of_screen,
line_break,
) = char_utils.get_next_char(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
next_char = char_utils.get_phonetic(next_char)
self.env["runtime"]["OutputManager"].present_text(
next_char, interrupt=True, announce_capital=True, flush=False
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
if line_break:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "line_break"
):
self.env["runtime"]["OutputManager"].present_text(
_("line break"), interrupt=False, sound_icon="EndOfLine"
)
def set_callback(self, callback):
pass pass

View File

@ -2,34 +2,62 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import line_utils
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('moves review to the next line ')
def run(self):
self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview']
if not self.env['screen']['newCursorReview']:
self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextLine, endOfScreen = \ def shutdown(self):
line_utils.getNextLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) pass
if nextLine.isspace(): def get_description(self):
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) return _("moves review to the next line ")
else:
self.env['runtime']['outputManager'].presentText(nextLine, interrupt=True, flush=False) def run(self):
if endOfScreen: self.env["screen"]["oldCursorReview"] = self.env["screen"][
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): "newCursorReview"
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') ]
def setCallback(self, callback): if not self.env["screen"]["newCursorReview"]:
self.env["screen"]["newCursorReview"] = self.env["screen"][
"new_cursor"
].copy()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
nextLine,
end_of_screen,
) = line_utils.get_next_line(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
if nextLine.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), sound_icon="EmptyLine", interrupt=True, flush=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
nextLine, interrupt=True, flush=False
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
def set_callback(self, callback):
pass pass

View File

@ -2,37 +2,102 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributors.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils from fenrirscreenreader.utils import word_utils
from fenrirscreenreader.core import debug
class command():
class command:
def __init__(self): def __init__(self):
pass pass
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('moves review to the next word ')
def run(self):
self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview']
if self.env['screen']['newCursorReview'] == None:
self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy()
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ def shutdown(self):
word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) pass
if nextWord.isspace(): def get_description(self):
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) return _("moves review to the next word ")
else:
self.env['runtime']['outputManager'].presentText(nextWord, interrupt=True, flush=False) def run(self):
if endOfScreen: # Check if we're in table mode FIRST - before any word navigation
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') self.env["runtime"]["DebugManager"].write_debug_out(
if lineBreak: f"review_next_word: is_table_mode={is_table_mode}",
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): debug.DebugLevel.INFO
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') )
def setCallback(self, callback): if is_table_mode:
table_info = self.env["runtime"]["TableManager"].move_to_next_column()
if table_info and table_info.get("at_end"):
# Stay on current cell and play end of line sound
current_info = table_info["current_info"]
if current_info:
output_text = f"{current_info['cell_content']}"
self.env["runtime"]["OutputManager"].present_text(
output_text, interrupt=True, flush=False
)
# Play end of line sound
self.env["runtime"]["OutputManager"].present_text(
_("end of line"), interrupt=False, sound_icon="EndOfLine"
)
elif table_info:
# Normal column navigation - announce cell content with column info
output_text = f"{table_info['cell_content']} {table_info['column_header']}"
self.env["runtime"]["OutputManager"].present_text(
output_text, interrupt=True, flush=False
)
else:
# No table info available, but still in table mode
self.env["runtime"]["OutputManager"].present_text(
_("no table data"), interrupt=True, flush=False
)
return # ALWAYS return in table mode to prevent regular word navigation
# Regular word navigation (only when NOT in table mode)
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
next_word,
end_of_screen,
line_break,
) = word_utils.get_next_word(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
self.env["screen"]["new_content_text"],
)
# Regular word announcement
if next_word.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
next_word, interrupt=True, flush=False
)
if end_of_screen:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "end_of_screen"
):
self.env["runtime"]["OutputManager"].present_text(
_("end of screen"),
interrupt=True,
sound_icon="EndOfScreen",
)
if line_break:
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"review", "line_break"
):
self.env["runtime"]["OutputManager"].present_text(
_("line break"), interrupt=False, sound_icon="EndOfLine"
)
def set_callback(self, callback):
pass pass

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