1 Commits

354 changed files with 9504 additions and 19088 deletions

View File

@ -74,7 +74,7 @@ KEY_FENRIR,KEY_0=bookmark_10
KEY_FENRIR,KEY_KPSLASH=set_window_application
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
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_F3=toggle_sound
KEY_FENRIR,KEY_F4=toggle_speech

View File

@ -76,11 +76,12 @@ KEY_FENRIR,KEY_F3=toggle_sound
KEY_FENRIR,KEY_F4=toggle_speech
KEY_FENRIR,KEY_ENTER=temp_disable_speech
KEY_FENRIR,KEY_SHIFT,KEY_P=progress_bar_monitor
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_auto_read
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=silence_until_prompt
KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_ENTER=toggle_output
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
KEY_FENRIR,KEY_ENTER=toggle_auto_read
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
#=toggle_barrier

View File

@ -124,9 +124,7 @@ interruptOnKeyPressFilter=
doubleTapTimeout=0.2
[general]
# 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
debugLevel=0
# debugMode sets where the debug output should send to:
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
# debugMode=Print just prints on the screen
@ -135,9 +133,6 @@ debugFile=
punctuationProfile=default
punctuationLevel=some
respectPunctuationPause=True
# Replace undefined punctuation with spaces instead of removing them
# This improves readability of text with punctuation like [X]mute, IP addresses, etc.
replaceUndefinedPunctuationWithSpace=True
newLinePause=True
numberOfClipboards=50
# used path for "export_clipboard_to_file"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,38 +2,24 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
# 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
from fenrirscreenreader.core.i18n import _
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
# clipboard
self.env["runtime"]["MemoryManager"].add_index_list(
"clipboardHistory",
self.env["runtime"]["SettingsManager"].get_setting_as_int(
"general", "numberOfClipboards"
),
)
self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards'))
def shutdown(self):
pass
def get_description(self):
return "No description found"
def getDescription(self):
return 'No description found'
def run(self):
pass
def set_callback(self, callback):
def setCallback(self, callback):
pass

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,35 +2,26 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import mark_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("copies last presented text to the clipboard")
pass
def getDescription(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
)
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 set_callback(self, callback):
def setCallback(self, callback):
pass

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,38 +2,28 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("present first line")
pass
def getDescription(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
)
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"].present_text(
first_line, interrupt=True
)
def set_callback(self, callback):
self.env['runtime']['outputManager'].presentText(firstLine, interrupt=True)
def setCallback(self, callback):
pass

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,82 +2,34 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("presents the current character.")
pass
def getDescription(self):
return _('presents the current character.')
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
# In table mode, sync to cell start if cursor is outside current cell
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
):
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'])
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
# is has attribute it enabled?
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'):
cursorPos = self.env['screen']['newCursorReview']
if not self.env['runtime']['attributeManager'].hasAttributes(cursorPos):
return
self.env["runtime"]["OutputManager"].present_text(
"has attribute", sound_icon="HasAttributes", interrupt=False
)
def set_callback(self, callback):
self.env['runtime']['outputManager'].presentText('has attribute', soundIcon='HasAttributes', interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,49 +2,31 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("set review and phonetically presents the current character")
pass
def getDescription(self):
return _('set review and phonetically presents the current character')
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
(
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
)
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 currChar.isspace():
self.env['runtime']['outputManager'].presentText(_("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):
currChar = char_utils.getPhonetic(currChar)
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, announceCapital=True, flush=False)
def setCallback(self, callback):
pass

View File

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

View File

@ -2,99 +2,35 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils
from fenrirscreenreader.core import debug
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("current word.")
pass
def getDescription(self):
return _('current word.')
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
(
self.env["screen"]["newCursorReview"]["x"],
self.env["screen"]["newCursorReview"]["y"],
curr_word,
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
)
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'])
if currWord.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False)
else:
# 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
)
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):
self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False)
if endOfScreen:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
if lineBreak:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'):
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine')
def setCallback(self, callback):
pass

View File

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

View File

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

View File

@ -2,80 +2,31 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _(
"set review cursor to begin of current line and display the content"
)
pass
def getDescription(self):
return _('set review cursor to begin of current line and display the content')
def run(self):
# Check if we're in table mode first
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
if is_table_mode:
table_info = self.env["runtime"]["TableManager"].move_to_first_cell()
if table_info:
output_text = (
f"{table_info['cell_content']} {table_info['column_header']}"
)
self.env["runtime"]["OutputManager"].present_text(
output_text, interrupt=True, flush=False
)
self.env["runtime"]["OutputManager"].present_text(
_("first cell"), interrupt=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("no table data"), interrupt=True, flush=False
)
return
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
self.env['runtime']['cursorManager'].setReviewCursorPosition(0 ,cursorPos['y'])
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'])
# Regular line begin navigation (when not in table mode)
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
self.env["runtime"]["CursorManager"].set_review_cursor_position(
0, 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"],
)
if curr_char.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
if currChar.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False)
else:
self.env["runtime"]["OutputManager"].present_text(
curr_char,
interrupt=True,
ignore_punctuation=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("beginning of line"), interrupt=False
)
def set_callback(self, callback):
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("beginning of line"), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,75 +2,28 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _(
"Move Review to the end of current line and display the content"
)
pass
def getDescription(self):
return _('Move Review to the end of current line and display the content')
def run(self):
# Check if we're in table mode first
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
if is_table_mode:
table_info = self.env["runtime"]["TableManager"].move_to_last_cell()
if table_info:
output_text = (
f"{table_info['cell_content']} {table_info['column_header']}"
)
self.env["runtime"]["OutputManager"].present_text(
output_text, interrupt=True, flush=False
)
self.env["runtime"]["OutputManager"].present_text(
_("last cell"), interrupt=False
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("no table data"), interrupt=True, flush=False
)
return
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y'])
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'])
# Regular line end navigation (when not in table mode)
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
self.env["runtime"]["CursorManager"].set_review_cursor_position(
self.env["screen"]["columns"] - 1, 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"],
)
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):
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("end of line"), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,89 +2,34 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
from fenrirscreenreader.utils import line_utils
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("Move Review to the first character on the line")
pass
def getDescription(self):
return _('Move Review to the first character on the line')
def run(self):
# Check if we're in table mode first
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
if is_table_mode:
table_info = self.env["runtime"]["TableManager"].move_to_first_char_in_cell()
if table_info:
char_utils.present_char_for_review(
self.env,
table_info['character'],
interrupt=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("first character in cell {0}").format(table_info['column_header']),
interrupt=False,
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("no table data"), interrupt=True, flush=False
)
return
# Regular line first character navigation (when not in table mode)
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(
_("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"],
)
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
x, y, currLine = \
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("line is empty"), interrupt=True)
return
self.env['runtime']['cursorManager'].setReviewCursorPosition((len(currLine) - len(currLine.lstrip())), cursorPos['y'])
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'])
char_utils.present_char_for_review(
self.env,
curr_char,
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):
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("first character in line indent {0}").format(str(len(currLine) - len(currLine.lstrip()))), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,74 +2,28 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("Move Review to the last character on the line")
pass
def getDescription(self):
return _('Move Review to the last character on the line')
def run(self):
# Check if we're in table mode first
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
if is_table_mode:
table_info = self.env["runtime"]["TableManager"].move_to_last_char_in_cell()
if table_info:
char_utils.present_char_for_review(
self.env,
table_info['character'],
interrupt=True,
announce_capital=True,
flush=False,
)
self.env["runtime"]["OutputManager"].present_text(
_("last character in cell {0}").format(table_info['column_header']),
interrupt=False,
)
else:
self.env["runtime"]["OutputManager"].present_text(
_("no table data"), interrupt=True, flush=False
)
return
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y'])
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
# Regular line last character navigation (when not in table mode)
cursor_pos = self.env["runtime"][
"CursorManager"
].get_review_or_text_cursor()
self.env["runtime"]["CursorManager"].set_review_cursor_position(
self.env["screen"]["columns"] - 1, cursor_pos["y"]
)
(
self.env["screen"]["newCursorReview"]["x"],
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):
char_utils.presentCharForReview(self.env, lastChar, interrupt=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("last character in line"), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,134 +2,38 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("Moves review to the next character")
pass
def getDescription(self):
return _('Moves review to the next character ')
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
# Check if we're in table mode for bounded navigation
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)
# 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
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'])
# 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
):
char_utils.presentCharForReview(self.env, nextChar, interrupt=True, announceCapital=True, flush=False)
if endOfScreen:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
if lineBreak:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'):
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine')
# is has attribute it enabled?
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'):
cursorPos = self.env['screen']['newCursorReview']
if not self.env['runtime']['attributeManager'].hasAttributes(cursorPos):
return
self.env["runtime"]["OutputManager"].present_text(
"has attribute", sound_icon="HasAttributes", interrupt=False
)
def set_callback(self, callback):
self.env['runtime']['outputManager'].presentText('has attribute', soundIcon='HasAttributes', interrupt=False)
def setCallback(self, callback):
pass

View File

@ -2,64 +2,33 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import char_utils
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _(
"phonetically presents the next character and set review to it"
)
pass
def getDescription(self):
return _('phonetically presents the next character and set review to it')
def run(self):
self.env["runtime"][
"CursorManager"
].enter_review_mode_curr_text_cursor()
self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor()
(
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):
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'])
nextChar = char_utils.getPhonetic(nextChar)
self.env['runtime']['outputManager'].presentText(nextChar ,interrupt=True, announceCapital=True, flush=False)
if endOfScreen:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
if lineBreak:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'):
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine')
def setCallback(self, callback):
pass

View File

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

View File

@ -2,108 +2,37 @@
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import word_utils
from fenrirscreenreader.core import debug
class command:
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("moves review to the next word ")
pass
def getDescription(self):
return _('moves review to the next word ')
def run(self):
# Check if we're in table mode FIRST - before any word navigation
is_table_mode = self.env["runtime"]["TableManager"].is_table_mode()
self.env["runtime"]["DebugManager"].write_debug_out(
f"review_next_word: is_table_mode={is_table_mode}",
debug.DebugLevel.INFO
)
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
self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview']
if self.env['screen']['newCursorReview'] == None:
self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy()
# 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"],
)
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \
word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
# Regular word announcement
if next_word.isspace():
self.env["runtime"]["OutputManager"].present_text(
_("blank"), interrupt=True, flush=False
)
if nextWord.isspace():
self.env['runtime']['outputManager'].presentText(_("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):
self.env['runtime']['outputManager'].presentText(nextWord, interrupt=True, flush=False)
if endOfScreen:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
if lineBreak:
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'):
self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine')
def setCallback(self, callback):
pass

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