diff --git a/src/fenrir b/src/fenrir index 11f332fd..fd771695 100755 --- a/src/fenrir +++ b/src/fenrir @@ -4,19 +4,22 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. +import argparse +import inspect import os import sys -import inspect -import argparse + from daemonize import Daemonize +from fenrirscreenreader import fenrirVersion +from fenrirscreenreader.core import fenrirManager + # Get the fenrir installation path -fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) -if not fenrirPath in sys.path: +fenrirPath = os.path.dirname(os.path.realpath( + os.path.abspath(inspect.getfile(inspect.currentframe())))) +if fenrirPath not in sys.path: sys.path.append(fenrirPath) -from fenrirscreenreader.core import fenrirManager -from fenrirscreenreader import fenrirVersion def create_argument_parser(): """Create and return the argument parser for Fenrir""" @@ -68,10 +71,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', @@ -80,25 +83,38 @@ 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 = fenrirManager.FenrirManager(cliArgs) + 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: - del fenrirApp + if fenrirApp: + del fenrirApp # Clean up PID file if it exists pidFile = "/run/fenrir.pid" if os.path.exists(pidFile): @@ -107,11 +123,12 @@ def run_fenrir(): except Exception: pass + def main(): global cliArgs argumentParser = create_argument_parser() cliArgs = argumentParser.parse_args() - + # Validate arguments isValid, errorMsg = validate_arguments(cliArgs) if not isValid: @@ -132,5 +149,6 @@ def main(): ) daemonProcess.start() + if __name__ == "__main__": main() diff --git a/src/fenrirscreenreader/commands/command_template.py b/src/fenrirscreenreader/commands/command_template.py index 10da3943..d96dbdb8 100644 --- a/src/fenrirscreenreader/commands/command_template.py +++ b/src/fenrirscreenreader/commands/command_template.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,7 +19,7 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): pass diff --git a/src/fenrirscreenreader/commands/commands/00_init_commands.py b/src/fenrirscreenreader/commands/commands/00_init_commands.py index 6ec89477..bce779d5 100644 --- a/src/fenrirscreenreader/commands/commands/00_init_commands.py +++ b/src/fenrirscreenreader/commands/commands/00_init_commands.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # this command is just to initialize stuff. @@ -12,22 +12,25 @@ 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"].add_index_list( + "clipboardHistory", + self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "numberOfClipboards" + ), + ) def shutdown(self): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): pass diff --git a/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py b/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py index 5055d5af..6f83c64f 100644 --- a/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py +++ b/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py @@ -2,23 +2,25 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +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: pass -class command(): +class command: def __init__(self): - self.language = '' + self.language = "" self.spellChecker = None def initialize(self, environment): @@ -29,44 +31,63 @@ class command(): pass def get_description(self): - return _('adds the current word to the exceptions dictionary') + 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') + self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) + ) + self.language = self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) def run(self): if not initialized: return - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') != self.language: + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "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() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() # 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) + 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'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~') + string.whitespace + r'!"#$%&\()*+,-./:;<=Â?@[\\]^_{|}~' + ) - if curr_word != '': + 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) + self.env["runtime"]["OutputManager"].present_text( + _("{0} is already in dictionary").format( + curr_word, + ), + sound_icon="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.env["runtime"]["OutputManager"].present_text( + _("{0} added to dictionary").format( + curr_word, + ), + sound_icon="Accept", + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/adjustment_base.py b/src/fenrirscreenreader/commands/commands/adjustment_base.py index 1ac77df4..599498a1 100644 --- a/src/fenrirscreenreader/commands/commands/adjustment_base.py +++ b/src/fenrirscreenreader/commands/commands/adjustment_base.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import math +from fenrirscreenreader.core.i18n import _ -class adjustment_command(): + +class adjustment_command: """Base class for speech and sound adjustment commands""" def __init__(self, section, setting, direction, step=0.1): @@ -25,14 +25,14 @@ class adjustment_command(): pass def get_description(self): - action = "Increase" if self.direction == 'inc' else "Decrease" - if self.section == 'speech': - return _(f'{action} the speech {self.setting}') + 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: @@ -41,11 +41,12 @@ class adjustment_command(): 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"].get_setting_as_float( + 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 @@ -55,28 +56,33 @@ class adjustment_command(): value = 0.0 # Set the new value - self.env['runtime']['SettingsManager'].set_setting( - self.section, self.setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + self.section, self.setting, str(value) + ) # Present feedback percentage = int(value * 100) - if self.section == 'speech': + if self.section == "speech": feedback = _("{0} percent speech {1}").format( - percentage, self.setting) + percentage, self.setting + ) else: feedback = _("{0} percent {1} {2}").format( - percentage, self.section, self.setting) + percentage, self.section, self.setting + ) - self.env['runtime']['OutputManager'].present_text( - feedback, sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + feedback, sound_icon="", interrupt=True + ) def _adjust_sound_volume(self): """Adjust sound volume using same logic as speech""" - value = self.env['runtime']['SettingsManager'].get_setting_as_float( - self.section, self.setting) + value = self.env["runtime"]["SettingsManager"].get_setting_as_float( + self.section, self.setting + ) # Sound volume uses same math as speech settings - if self.direction == 'inc': + if self.direction == "inc": value = round((math.ceil(10 * value) / 10) + self.step, 2) if value > 1.0: value = 1.0 @@ -86,15 +92,17 @@ class adjustment_command(): value = 0.0 # Set the new value - self.env['runtime']['SettingsManager'].set_setting( - self.section, self.setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + self.section, self.setting, str(value) + ) # Present feedback with appropriate sound icon percentage = int(value * 100) - sound_icon = 'SoundOn' if self.direction == 'inc' else 'SoundOff' + 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) + self.env["runtime"]["OutputManager"].present_text( + feedback, sound_icon=sound_icon, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/announce_fenrir_version.py b/src/fenrirscreenreader/commands/commands/announce_fenrir_version.py index 8d3f4e19..a6247084 100644 --- a/src/fenrirscreenreader/commands/commands/announce_fenrir_version.py +++ b/src/fenrirscreenreader/commands/commands/announce_fenrir_version.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader import fenrirVersion +from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,17 +19,20 @@ class command(): pass def get_description(self): - return _('Present the version of Fenrir currently in use.') + return _("Present the version of Fenrir currently in use.") def run(self): try: - self.env['runtime']['OutputManager'].present_text( - f'Fenrir screen reader version { + self.env["runtime"]["OutputManager"].present_text( + f"Fenrir screen reader version { fenrirVersion.version}-{ - fenrirVersion.code_name}', interrupt=True) + fenrirVersion.code_name}", + interrupt=True, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - _('Version information is unavailable.'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Version information is unavailable."), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/apply_tested_voice.py b/src/fenrirscreenreader/commands/commands/apply_tested_voice.py index 2834ab35..a1fe209b 100644 --- a/src/fenrirscreenreader/commands/commands/apply_tested_voice.py +++ b/src/fenrirscreenreader/commands/commands/apply_tested_voice.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,64 +19,76 @@ class command(): 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"].present_text( + "No voice has been tested yet", interrupt=True + ) + self.env["runtime"]["OutputManager"].present_text( + "Use voice browser first", interrupt=True + ) return - module = self.env['commandBuffer']['lastTestedModule'] - voice = self.env['commandBuffer']['lastTestedVoice'] + module = self.env["commandBuffer"]["lastTestedModule"] + voice = self.env["commandBuffer"]["lastTestedVoice"] - self.env['runtime']['OutputManager'].present_text( - f"Applying {voice} from {module}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Applying {voice} from {module}", interrupt=True + ) # Apply to runtime settings only (temporary until saved) - 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') + old_driver = SettingsManager.get_setting("speech", "driver") + old_module = SettingsManager.get_setting("speech", "module") + old_voice = SettingsManager.get_setting("speech", "voice") try: # Apply new settings to runtime only (use set_setting to update # settingArgDict) - SettingsManager.set_setting('speech', 'driver', 'speechdDriver') - SettingsManager.set_setting('speech', 'module', module) - SettingsManager.set_setting('speech', 'voice', voice) + SettingsManager.set_setting( + "speech", "driver", "speechdDriver" + ) + SettingsManager.set_setting("speech", "module", module) + SettingsManager.set_setting("speech", "voice", voice) # Apply to speech driver instance directly - if 'SpeechDriver' in self.env['runtime']: - SpeechDriver = self.env['runtime']['SpeechDriver'] + 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') + self.env["runtime"]["OutputManager"].present_text( + "Voice applied successfully!", interrupt=True + ) + self.env["runtime"]["OutputManager"].present_text( + "Use save settings to make permanent", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Accept") except Exception as e: # Revert on failure - SettingsManager.set_setting('speech', 'driver', old_driver) - SettingsManager.set_setting('speech', 'module', old_module) - SettingsManager.set_setting('speech', 'voice', old_voice) + 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') + self.env["runtime"]["OutputManager"].present_text( + f"Failed to apply voice, reverted: {str(e)}", + interrupt=True, + ) + self.env["runtime"]["OutputManager"].play_sound("Error") except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Apply voice error: {str(e)}", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Error') + 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 diff --git a/src/fenrirscreenreader/commands/commands/attribute_cursor.py b/src/fenrirscreenreader/commands/commands/attribute_cursor.py index ddfba9ad..298eb326 100644 --- a/src/fenrirscreenreader/commands/commands/attribute_cursor.py +++ b/src/fenrirscreenreader/commands/commands/attribute_cursor.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import screen_utils -class command(): +class command: def __init__(self): pass @@ -20,22 +19,28 @@ class command(): pass def get_description(self): - return _('Reads attributes of current cursor position') + return _("Reads attributes of current cursor position") def run(self): - cursor_pos = self.env['runtime']['CursorManager'].get_review_or_text_cursor() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() try: - attributes = self.env['runtime']['AttributeManager'].get_attribute_by_xy( - cursor_pos['x'], cursor_pos['y']) + attributes = self.env["runtime"][ + "AttributeManager" + ].get_attribute_by_xy(cursor_pos["x"], cursor_pos["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) + 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) + self.env["runtime"]["OutputManager"].present_text( + attribute_format_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_1.py b/src/fenrirscreenreader/commands/commands/bookmark_1.py index 85bf1d1e..ac1113d9 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_1.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_1.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(1, 'read') + super().__init__(1, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_10.py b/src/fenrirscreenreader/commands/commands/bookmark_10.py index 30e7c8db..dee21e88 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_10.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_10.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(10, 'read') + super().__init__(10, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_2.py b/src/fenrirscreenreader/commands/commands/bookmark_2.py index 7afb55d2..e747516c 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_2.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_2.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(2, 'read') + super().__init__(2, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_3.py b/src/fenrirscreenreader/commands/commands/bookmark_3.py index 990521c2..56fbe47a 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_3.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_3.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(3, 'read') + super().__init__(3, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_4.py b/src/fenrirscreenreader/commands/commands/bookmark_4.py index 41326199..f7931aa2 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_4.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_4.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(4, 'read') + super().__init__(4, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_5.py b/src/fenrirscreenreader/commands/commands/bookmark_5.py index 09916f97..3e4f7e7e 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_5.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_5.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(5, 'read') + super().__init__(5, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_6.py b/src/fenrirscreenreader/commands/commands/bookmark_6.py index 287b267c..2e0fd983 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_6.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_6.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(6, 'read') + super().__init__(6, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_7.py b/src/fenrirscreenreader/commands/commands/bookmark_7.py index be3a06b8..04c4ce35 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_7.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_7.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(7, 'read') + super().__init__(7, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_8.py b/src/fenrirscreenreader/commands/commands/bookmark_8.py index 0f5ca2f6..fc28647d 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_8.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_8.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(8, 'read') + super().__init__(8, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_9.py b/src/fenrirscreenreader/commands/commands/bookmark_9.py index fae812c7..ac1a83f5 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_9.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_9.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(9, 'read') + super().__init__(9, "read") diff --git a/src/fenrirscreenreader/commands/commands/bookmark_base.py b/src/fenrirscreenreader/commands/commands/bookmark_base.py index b9a77e6a..a46234fe 100644 --- a/src/fenrirscreenreader/commands/commands/bookmark_base.py +++ b/src/fenrirscreenreader/commands/commands/bookmark_base.py @@ -2,129 +2,159 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. +from fenrirscreenreader.core.i18n import _ from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import mark_utils -from fenrirscreenreader.core.i18n import _ - -import gettext -_ = gettext.gettext -class bookmark_command(): +class bookmark_command: """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}' + 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() + 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) + if not self.env["commandBuffer"]["bookMarks"][self.ID]: + self.env["runtime"]["OutputManager"].present_text( + "Bookmark {0} not set".format(self.ID), interrupt=True + ) return - if curr_app not in self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['OutputManager'].present_text( - 'Bookmark for application {0} not set'.format(curr_app), interrupt=True) + if curr_app not in self.env["commandBuffer"]["bookMarks"][self.ID]: + self.env["runtime"]["OutputManager"].present_text( + "Bookmark for application {0} not set".format(curr_app), + interrupt=True, + ) return - if not self.env['commandBuffer']['bookMarks'][self.ID][curr_app].get( - '1'): - self.env['runtime']['OutputManager'].present_text( - 'Bookmark for application {0} not set'.format(curr_app), interrupt=True) + if not self.env["commandBuffer"]["bookMarks"][self.ID][curr_app].get( + "1" + ): + self.env["runtime"]["OutputManager"].present_text( + "Bookmark for application {0} not set".format(curr_app), + interrupt=True, + ) return # Get bookmarked text - marked = '' - start_mark = self.env['commandBuffer']['bookMarks'][self.ID][curr_app]['1'].copy( - ) + 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( - ) + 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']) + start_mark, end_mark, self.env["screen"]["new_content_text"] + ) else: x, y, marked = line_utils.get_current_line( - start_mark['x'], start_mark['y'], self.env['screen']['new_content_text']) + start_mark["x"], + start_mark["y"], + self.env["screen"]["new_content_text"], + ) if marked.isspace(): - self.env['runtime']['OutputManager'].present_text( - _('blank'), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - marked, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + marked, interrupt=True + ) def _set_bookmark(self): - if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['OutputManager'].present_text( - _("No mark found"), interrupt=True) + if not self.env["commandBuffer"]["Marks"]["1"]: + self.env["runtime"]["OutputManager"].present_text( + _("No mark found"), interrupt=True + ) return - curr_app = self.env['runtime']['ApplicationManager'].get_current_application() - self.env['commandBuffer']['bookMarks'][self.ID][curr_app] = {} + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() + self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] = {} - self.env['commandBuffer']['bookMarks'][self.ID][curr_app]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + bookmarks = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] + bookmarks["1"] = self.env["commandBuffer"]["Marks"]["1"].copy() - if self.env['commandBuffer']['Marks']['2']: - self.env['commandBuffer']['bookMarks'][self.ID][curr_app]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + if self.env["commandBuffer"]["Marks"]["2"]: + bookmarks["2"] = self.env["commandBuffer"]["Marks"]["2"].copy() else: - self.env['commandBuffer']['bookMarks'][self.ID][curr_app]['2'] = None + bookmarks["2"] = None - self.env['runtime']['OutputManager'].present_text( - _('Bookmark {0} set for application {1}').format( - self.ID, curr_app), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Bookmark {0} set for application {1}").format( + self.ID, curr_app + ), + interrupt=True, + ) # Clear marks after setting bookmark - 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() + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() - if self.ID in self.env['commandBuffer']['bookMarks'] and curr_app in self.env['commandBuffer']['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) + bookmarks = self.env["commandBuffer"]["bookMarks"] + if self.ID in bookmarks and curr_app in bookmarks[self.ID]: + del self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] + self.env["runtime"]["OutputManager"].present_text( + _("Bookmark {0} removed for application {1}").format( + self.ID, curr_app + ), + interrupt=True, + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Bookmark {0} not set for application {1}').format( - self.ID, curr_app), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Bookmark {0} not set for application {1}").format( + self.ID, curr_app + ), + interrupt=True, + ) def set_callback(self, callback): pass + # Factory function to create bookmark command instances @@ -134,43 +164,48 @@ def create_bookmark_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: bookmark_command(i, "read") # Create set bookmark commands (set_bookmark_1 through set_bookmark_10) for i in range(1, 11): - commands[f'set_bookmark_{i}'] = lambda i=i: bookmark_command(i, 'set') + commands[f"set_bookmark_{i}"] = lambda i=i: bookmark_command(i, "set") # Create clear bookmark commands (clear_bookmark_1 through # clear_bookmark_10) for i in range(1, 11): - commands[f'clear_bookmark_{i}'] = lambda i=i: bookmark_command( - i, 'clear') + commands[f"clear_bookmark_{i}"] = lambda i=i: bookmark_command( + i, "clear" + ) return commands + # For backwards compatibility, provide individual command classes # This allows the existing command loading system to work unchanged def _make_command_class(bookmark_id, action): """Create a command class for a specific bookmark and action""" + class command(bookmark_command): def __init__(self): super().__init__(bookmark_id, action) + return command + # Generate individual command classes for each bookmark operation # These will be used by the existing command loading system # Read bookmarks (bookmark_1.py style) for i in range(1, 11): - globals()[f'bookmark_{i}_command'] = _make_command_class(i, 'read') + globals()[f"bookmark_{i}_command"] = _make_command_class(i, "read") # Set bookmarks (set_bookmark_1.py style) for i in range(1, 11): - globals()[f'set_bookmark_{i}_command'] = _make_command_class(i, 'set') + 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") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py index 6084acf2..2b618d07 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(1, 'clear') + super().__init__(1, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py index a0413ce7..ee4ecbd7 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(10, 'clear') + super().__init__(10, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py index cce212bb..9b0daf79 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(2, 'clear') + super().__init__(2, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py index 1930aa0b..902c2b79 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(3, 'clear') + super().__init__(3, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py index 6819c6e6..b7320b0a 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(4, 'clear') + super().__init__(4, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py index 09adb82e..4bd4c68c 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(5, 'clear') + super().__init__(5, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py index a474ea8e..8866a407 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(6, 'clear') + super().__init__(6, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py index 63362bf5..27e365b6 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(7, 'clear') + super().__init__(7, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py index 258d762e..36de85b0 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(8, 'clear') + super().__init__(8, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py index 88ef6f49..b7162589 100644 --- a/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(9, 'clear') + super().__init__(9, "clear") diff --git a/src/fenrirscreenreader/commands/commands/clear_clipboard.py b/src/fenrirscreenreader/commands/commands/clear_clipboard.py index 60d475db..04767a34 100644 --- a/src/fenrirscreenreader/commands/commands/clear_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/clear_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,15 @@ class command(): pass def get_description(self): - return _('clears the currently selected clipboard') + 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) + 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): diff --git a/src/fenrirscreenreader/commands/commands/clear_window_application.py b/src/fenrirscreenreader/commands/commands/clear_window_application.py index 4ab4f2ab..e36f4052 100644 --- a/src/fenrirscreenreader/commands/commands/clear_window_application.py +++ b/src/fenrirscreenreader/commands/commands/clear_window_application.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,23 @@ class command(): pass def get_description(self): - return _('Turn off window mode for application') + 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( + 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, ) - self.env['runtime']['OutputManager'].present_text( - _('Window Mode off for application {0}').format( - curr_app,), interrupt=True) else: - self.env['runtime']['OutputManager'].present_text( - _("Not in window Mode"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Not in window Mode"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py b/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py index d582a7dc..f148e827 100644 --- a/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import mark_utils -class command(): +class command: def __init__(self): pass @@ -20,16 +19,18 @@ class command(): pass def get_description(self): - return _('copies last presented text to the clipboard') + return _("copies last presented text to the clipboard") def run(self): - last_echo = self.env['runtime']['OutputManager'].get_last_echo() + 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) + self.env["runtime"]["MemoryManager"].add_value_to_first_index( + "clipboardHistory", last_echo + ) + self.env["runtime"]["OutputManager"].present_text( + last_echo, sound_icon="CopyToClipboard", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py b/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py index 6dd5f648..26040c9f 100644 --- a/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py @@ -3,11 +3,10 @@ from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import mark_utils -class command(): +class command: def __init__(self): pass @@ -18,20 +17,20 @@ class command(): pass def get_description(self): - return _('copies marked text to the currently selected clipboard') + 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') + 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) + start_y = min(start_mark["y"], len(screen_lines) - 1) + end_y = min(end_mark["y"], len(screen_lines) - 1) # If marks are on the same line if 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 + start_x = min(start_mark["x"], len(line)) + end_x = min(end_mark["x"], len(line)) + 1 return line[start_x:end_x] # Handle multi-line selection @@ -39,7 +38,7 @@ class command(): # First line (from start mark to end of line) first_line = screen_lines[start_y] - start_x = min(start_mark['x'], len(first_line)) + start_x = min(start_mark["x"], len(first_line)) result.append(first_line[start_x:].rstrip()) # Middle lines (complete lines) @@ -49,32 +48,35 @@ class command(): # 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 + end_x = min(end_mark["x"], len(last_line)) + 1 result.append(last_line[:end_x].rstrip()) - return '\n'.join(result) + 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"].present_text( + _("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"].set_mark() # 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() + 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) + self.env["runtime"]["MemoryManager"].add_value_to_first_index( + "clipboardHistory", marked + ) # reset marks - self.env['runtime']['CursorManager'].clear_marks() - self.env['runtime']['OutputManager'].present_text( - marked, sound_icon ='CopyToClipboard', interrupt=True) + self.env["runtime"]["CursorManager"].clear_marks() + self.env["runtime"]["OutputManager"].present_text( + marked, sound_icon="CopyToClipboard", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/curr_clipboard.py b/src/fenrirscreenreader/commands/commands/curr_clipboard.py index 2a68c51c..2925f6b7 100644 --- a/src/fenrirscreenreader/commands/commands/curr_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/curr_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,22 @@ class command(): pass def get_description(self): - return _('speaks the contents of the currently selected clipboard') + 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) + 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) + clipboard = self.env["runtime"][ + "MemoryManager" + ].get_index_list_element("clipboardHistory") + self.env["runtime"]["OutputManager"].present_text( + clipboard, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen.py b/src/fenrirscreenreader/commands/commands/curr_screen.py index fa223ec1..8a4f4223 100644 --- a/src/fenrirscreenreader/commands/commands/curr_screen.py +++ b/src/fenrirscreenreader/commands/commands/curr_screen.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,15 +19,17 @@ class command(): pass def get_description(self): - return _('reads the contents of the current screen') + 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) + 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) + self.env["runtime"]["OutputManager"].present_text( + self.env["screen"]["new_content_text"], interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py b/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py index b570e188..e2fb7ca0 100644 --- a/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py +++ b/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import mark_utils -class command(): +class command: def __init__(self): pass @@ -20,21 +19,26 @@ class command(): pass def get_description(self): - return _('reads from the cursor to the bottom of the screen') + 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() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() text_after_cursor = mark_utils.get_text_after_mark( - cursor_pos, self.env['screen']['new_content_text']) + cursor_pos, self.env["screen"]["new_content_text"] + ) if text_after_cursor.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - text_after_cursor, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + text_after_cursor, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py b/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py index de16fa4d..d6ab716e 100644 --- a/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py +++ b/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import mark_utils -class command(): +class command: def __init__(self): pass @@ -20,24 +19,27 @@ class command(): pass def get_description(self): - return _('Reads from the top of the screen to the cursor position') + 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"]: + cursor_pos = self.env["screen"]["newCursorReview"].copy() else: - cursor_pos = self.env['screen']['new_cursor'].copy() + cursor_pos = self.env["screen"]["new_cursor"].copy() text_before_cursor = mark_utils.get_text_before_mark( - cursor_pos, self.env['screen']['new_content_text']) + cursor_pos, self.env["screen"]["new_content_text"] + ) if text_before_cursor.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - text_before_cursor, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + text_before_cursor, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/current_quick_menu_entry.py b/src/fenrirscreenreader/commands/commands/current_quick_menu_entry.py index 960f3026..82880896 100644 --- a/src/fenrirscreenreader/commands/commands/current_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/commands/current_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,16 +19,17 @@ class command(): pass def get_description(self): - return _('get current quick menu entry') + 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) + menu = "" + value = "" + menu = self.env["runtime"]["QuickMenuManager"].get_current_entry() + if menu != "": + value = self.env["runtime"]["QuickMenuManager"].get_current_value() + self.env["runtime"]["OutputManager"].present_text( + menu + " " + value, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/current_quick_menu_value.py b/src/fenrirscreenreader/commands/commands/current_quick_menu_value.py index fc693ca5..11acac5e 100644 --- a/src/fenrirscreenreader/commands/commands/current_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/commands/current_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,13 @@ class command(): pass def get_description(self): - return _('get current quick menu value') + 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) + value = self.env["runtime"]["QuickMenuManager"].get_current_value() + self.env["runtime"]["OutputManager"].present_text( + value, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_column.py b/src/fenrirscreenreader/commands/commands/cursor_column.py index 862464c6..60d77388 100644 --- a/src/fenrirscreenreader/commands/commands/cursor_column.py +++ b/src/fenrirscreenreader/commands/commands/cursor_column.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,15 +19,19 @@ class command(): pass def get_description(self): - return _('Column number for cursor') + 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) + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() + self.env["runtime"]["OutputManager"].present_text( + str(cursor_pos["x"] + 1), interrupt=True + ) + self.env["runtime"]["OutputManager"].announce_active_cursor() + self.env["runtime"]["OutputManager"].present_text( + " column number", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_lineno.py b/src/fenrirscreenreader/commands/commands/cursor_lineno.py index b921a531..04762a0c 100644 --- a/src/fenrirscreenreader/commands/commands/cursor_lineno.py +++ b/src/fenrirscreenreader/commands/commands/cursor_lineno.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,15 +19,19 @@ class command(): pass def get_description(self): - return _('Line number for cursor') + 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) + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() + self.env["runtime"]["OutputManager"].present_text( + str(cursor_pos["y"] + 1), interrupt=True + ) + self.env["runtime"]["OutputManager"].announce_active_cursor() + self.env["runtime"]["OutputManager"].present_text( + " line number", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_position.py b/src/fenrirscreenreader/commands/commands/cursor_position.py index c0e5a59d..bd491838 100644 --- a/src/fenrirscreenreader/commands/commands/cursor_position.py +++ b/src/fenrirscreenreader/commands/commands/cursor_position.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,22 @@ class command(): pass def get_description(self): - return _('displays the position of the review cursor') + 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() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() - self.env['runtime']['OutputManager'].present_text( + 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) + cursor_pos["y"] + 1, + cursor_pos["x"] + 1, + self.env["screen"]["newTTY"], + ), + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_read_line_to_cursor.py b/src/fenrirscreenreader/commands/commands/cursor_read_line_to_cursor.py index 9c9961a2..0547fedd 100644 --- a/src/fenrirscreenreader/commands/commands/cursor_read_line_to_cursor.py +++ b/src/fenrirscreenreader/commands/commands/cursor_read_line_to_cursor.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -21,21 +20,29 @@ class command(): def get_description(self): return _( - 'read line to cursor pos, use review cursor if you are in review mode, otherwhise use text cursor') + "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() + 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']) + 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) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - curr_line[:cursor_pos['x']], interrupt=True) - self.env['runtime']['OutputManager'].announce_active_cursor() + self.env["runtime"]["OutputManager"].present_text( + curr_line[: cursor_pos["x"]], interrupt=True + ) + self.env["runtime"]["OutputManager"].announce_active_cursor() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py b/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py index fb124a37..a4bfc08d 100644 --- a/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py +++ b/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -21,21 +20,29 @@ class command(): def get_description(self): return _( - 'read to end of line, use review cursor if you are in review mode, otherwhise use text cursor') + "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() + 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']) + 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) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - curr_line[cursor_pos['x']:], interrupt=True) - self.env['runtime']['OutputManager'].announce_active_cursor() + self.env["runtime"]["OutputManager"].present_text( + curr_line[cursor_pos["x"] :], interrupt=True + ) + self.env["runtime"]["OutputManager"].announce_active_cursor() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/cycle_keyboard_layout.py b/src/fenrirscreenreader/commands/commands/cycle_keyboard_layout.py index 49871b43..5a4bd709 100644 --- a/src/fenrirscreenreader/commands/commands/cycle_keyboard_layout.py +++ b/src/fenrirscreenreader/commands/commands/cycle_keyboard_layout.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.core import debug import os +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -21,46 +21,52 @@ class command(): pass def get_description(self): - return _('cycles between available keyboard layouts') + return _("cycles between available keyboard layouts") def get_available_layouts(self): """Get list of available keyboard layout files""" layouts = [] # Check standard locations for keyboard layouts - settings_root = '/etc/fenrirscreenreader/' + settings_root = "/etc/fenrirscreenreader/" if not os.path.exists(settings_root): # Fallback to source directory import fenrirscreenreader - fenrir_path = os.path.dirname(fenrirscreenreader.__file__) - settings_root = fenrir_path + '/../../config/' - keyboard_path = settings_root + 'keyboard/' + fenrir_path = os.path.dirname(fenrirscreenreader.__file__) + settings_root = fenrir_path + "/../../config/" + + keyboard_path = settings_root + "keyboard/" if os.path.exists(keyboard_path): for file in os.listdir(keyboard_path): - if file.endswith('.conf') and not file.startswith( - '__') and not file.lower().startswith('pty'): - layout_name = file.replace('.conf', '') + if ( + 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"].get_setting( + "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() @@ -76,24 +82,23 @@ class command(): 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"].set_setting( + "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"].reload_shortcuts() + self.env["runtime"]["OutputManager"].present_text( + _("Switched to {} keyboard layout").format(next_layout), + interrupt=True, ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Error reloading shortcuts: " + str(e), - debug.DebugLevel.ERROR + self.env["runtime"]["DebugManager"].write_debug_out( + "Error reloading shortcuts: " + str(e), debug.DebugLevel.ERROR ) - self.env['runtime']['OutputManager'].present_text( - _('Error switching keyboard layout'), - interrupt=True + self.env["runtime"]["OutputManager"].present_text( + _("Error switching keyboard layout"), interrupt=True ) def set_callback(self, callback): diff --git a/src/fenrirscreenreader/commands/commands/date.py b/src/fenrirscreenreader/commands/commands/date.py index 8e4ff2a1..3b7ae543 100644 --- a/src/fenrirscreenreader/commands/commands/date.py +++ b/src/fenrirscreenreader/commands/commands/date.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the date') + return _("presents the date") def run(self): - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) # get the time formatted date_string = datetime.datetime.strftime( - datetime.datetime.now(), date_format) + datetime.datetime.now(), date_format + ) # 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) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py b/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py index 39be219d..a309e7ec 100644 --- a/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py +++ b/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('alsa', 'volume', 'dec') + super().__init__("alsa", "volume", "dec") diff --git a/src/fenrirscreenreader/commands/commands/dec_sound_volume.py b/src/fenrirscreenreader/commands/commands/dec_sound_volume.py index 26d89beb..593a5c8d 100644 --- a/src/fenrirscreenreader/commands/commands/dec_sound_volume.py +++ b/src/fenrirscreenreader/commands/commands/dec_sound_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('sound', 'volume', 'dec') + super().__init__("sound", "volume", "dec") diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py b/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py index 72715954..edc8adf6 100644 --- a/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py +++ b/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'pitch', 'dec') + super().__init__("speech", "pitch", "dec") diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_rate.py b/src/fenrirscreenreader/commands/commands/dec_speech_rate.py index 6f3578d0..c043d7be 100644 --- a/src/fenrirscreenreader/commands/commands/dec_speech_rate.py +++ b/src/fenrirscreenreader/commands/commands/dec_speech_rate.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'rate', 'dec') + super().__init__("speech", "rate", "dec") diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_volume.py b/src/fenrirscreenreader/commands/commands/dec_speech_volume.py index 32eec03d..95646767 100644 --- a/src/fenrirscreenreader/commands/commands/dec_speech_volume.py +++ b/src/fenrirscreenreader/commands/commands/dec_speech_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'volume', 'dec') + super().__init__("speech", "volume", "dec") diff --git a/src/fenrirscreenreader/commands/commands/exit_review.py b/src/fenrirscreenreader/commands/commands/exit_review.py index 3ff1b751..0a9f06a3 100644 --- a/src/fenrirscreenreader/commands/commands/exit_review.py +++ b/src/fenrirscreenreader/commands/commands/exit_review.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,19 @@ class command(): pass def get_description(self): - return _('exits review mode') + 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) + if not self.env["runtime"]["CursorManager"].is_review_mode(): + self.env["runtime"]["OutputManager"].present_text( + _("Not in Review Mode"), interrupt=True + ) return - self.env['runtime']['CursorManager'].clear_review_cursor() - self.env['runtime']['OutputManager'].present_text( - _("Exiting Review Mode"), interrupt=True) + self.env["runtime"]["CursorManager"].clear_review_cursor() + self.env["runtime"]["OutputManager"].present_text( + _("Exiting Review Mode"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py b/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py index 90223f60..fd3f8e33 100644 --- a/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py +++ b/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py @@ -2,57 +2,66 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.core import debug import os +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass - def initialize(self, environment, script_path=''): + def initialize(self, environment, script_path=""): self.env = environment def shutdown(self): pass def get_description(self): - return _('export the current fenrir clipboard to a file') + 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 = self.env["runtime"][ + "SettingsManager" + ].get_setting("general", "clipboardExportPath") clipboard_file_path = clipboard_file_path.replace( - '$user', self.env['general']['curr_user']) + "$user", self.env["general"]["curr_user"] + ) clipboard_file_path = clipboard_file_path.replace( - '$USER', self.env['general']['curr_user']) + "$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') + "$User", self.env["general"]["curr_user"] + ) + clipboard_file = open(clipboard_file_path, "w") try: - 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"].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 = 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) + self.env["runtime"]["OutputManager"].present_text( + _("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) + self.env["runtime"]["DebugManager"].write_debug_out( + "export_clipboard_to_file:run: Filepath:" + + clipboard_file + + " trace:" + + str(e), + debug.DebugLevel.ERROR, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py b/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py index b10b0405..e86d9e83 100644 --- a/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py +++ b/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py @@ -2,21 +2,22 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import _thread +import importlib +import os + +import pyperclip from fenrirscreenreader.core.i18n import _ -import os -import importlib -import _thread -import pyperclip - -class command(): +class command: def __init__(self): pass - def initialize(self, environment, script_path=''): + def initialize(self, environment, script_path=""): self.env = environment self.script_path = script_path @@ -24,7 +25,7 @@ class command(): pass def get_description(self): - return _('Export current fenrir clipboard to X or GUI clipboard') + return _("Export current fenrir clipboard to X or GUI clipboard") def run(self): _thread.start_new_thread(self._thread_run, ()) @@ -32,18 +33,21 @@ class command(): def _thread_run(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"].is_index_list_empty( + "clipboardHistory" + ): + self.env["runtime"]["OutputManager"].present_text( + _("clipboard empty"), interrupt=True + ) return # Get current clipboard content - clipboard = self.env['runtime']['MemoryManager'].get_index_list_element( - 'clipboardHistory') + clipboard = self.env["runtime"][ + "MemoryManager" + ].get_index_list_element("clipboardHistory") # Remember original display environment variable if it exists - original_display = os.environ.get('DISPLAY', '') + original_display = os.environ.get("DISPLAY", "") success = False # Try different display options @@ -51,7 +55,7 @@ class command(): 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) @@ -66,21 +70,27 @@ class command(): # Restore original display setting if original_display: - os.environ['DISPLAY'] = original_display + os.environ["DISPLAY"] = original_display else: - os.environ.pop('DISPLAY', None) + os.environ.pop("DISPLAY", None) # Notify the user of the result if success: - self.env['runtime']['OutputManager'].present_text( - _('exported to the X session.'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("exported to the X session."), interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('failed to export to X clipboard. No available display found.'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _( + "failed to export to X clipboard. No available display found." + ), + interrupt=True, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - str(e), sound_icon ='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + str(e), sound_icon="", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/first_clipboard.py b/src/fenrirscreenreader/commands/commands/first_clipboard.py index edb6307c..749d9eb3 100644 --- a/src/fenrirscreenreader/commands/commands/first_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/first_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,19 +19,25 @@ class command(): pass def get_description(self): - return _('selects the first clipboard') + 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"].is_index_list_empty( + "clipboardHistory" + ): + self.env["runtime"]["OutputManager"].present_text( + _("clipboard empty"), interrupt=True + ) return - self.env['runtime']['MemoryManager'].set_first_index('clipboardHistory') - clipboard = self.env['runtime']['MemoryManager'].get_index_list_element( - 'clipboardHistory') - self.env['runtime']['OutputManager'].present_text( - clipboard, interrupt=True) + self.env["runtime"]["MemoryManager"].set_first_index( + "clipboardHistory" + ) + clipboard = self.env["runtime"][ + "MemoryManager" + ].get_index_list_element("clipboardHistory") + self.env["runtime"]["OutputManager"].present_text( + clipboard, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/forward_keypress.py b/src/fenrirscreenreader/commands/commands/forward_keypress.py index 253f1868..754fc3b9 100644 --- a/src/fenrirscreenreader/commands/commands/forward_keypress.py +++ b/src/fenrirscreenreader/commands/commands/forward_keypress.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,13 @@ class command(): pass def get_description(self): - return _('sends the following keypress to the terminal or application') + 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"].present_text( + _("Forward next keypress"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py b/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py index 72dceee0..0a19bb16 100644 --- a/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py +++ b/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import mark_utils import os +from fenrirscreenreader.core.i18n import _ +from fenrirscreenreader.utils import mark_utils -class command(): + +class command: def __init__(self): pass @@ -21,31 +21,39 @@ class command(): pass def get_description(self): - return _('imports text from clipboard file to the clipboard') + 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 = self.env["runtime"][ + "SettingsManager" + ].get_setting("general", "clipboardExportPath") clipboard_file_path = clipboard_file_path.replace( - '$user', self.env['general']['curr_user']) + "$user", self.env["general"]["curr_user"] + ) clipboard_file_path = clipboard_file_path.replace( - '$USER', self.env['general']['curr_user']) + "$USER", self.env["general"]["curr_user"] + ) clipboard_file_path = clipboard_file_path.replace( - '$User', self.env['general']['curr_user']) + "$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) + self.env["runtime"]["OutputManager"].present_text( + _("File does not exist"), sound_icon="", interrupt=True + ) return - clipboard_file = open(clipboard_file_path, 'r') + clipboard_file = open(clipboard_file_path, "r") imported = clipboard_file.read() clipboard_file.close() - self.env['runtime']['MemoryManager'].add_value_to_first_index( - 'clipboardHistory', imported) + self.env["runtime"]["MemoryManager"].add_value_to_first_index( + "clipboardHistory", imported + ) - self.env['runtime']['OutputManager'].present_text( - 'Import to Clipboard', sound_icon ='CopyToClipboard', interrupt=True) - self.env['runtime']['OutputManager'].present_text( - imported, sound_icon ='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "Import to Clipboard", sound_icon="CopyToClipboard", interrupt=True + ) + self.env["runtime"]["OutputManager"].present_text( + imported, sound_icon="", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/import_clipboard_from_x.py b/src/fenrirscreenreader/commands/commands/import_clipboard_from_x.py index 5a9ad4bb..76641af3 100644 --- a/src/fenrirscreenreader/commands/commands/import_clipboard_from_x.py +++ b/src/fenrirscreenreader/commands/commands/import_clipboard_from_x.py @@ -2,21 +2,22 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import _thread +import importlib +import os + +import pyperclip from fenrirscreenreader.core.i18n import _ -import importlib -import _thread -import pyperclip -import os - -class command(): +class command: def __init__(self): pass - def initialize(self, environment, script_path=''): + def initialize(self, environment, script_path=""): self.env = environment self.script_path = script_path @@ -32,7 +33,7 @@ class command(): def _thread_run(self): try: # Remember original display environment variable if it exists - original_display = os.environ.get('DISPLAY', '') + original_display = os.environ.get("DISPLAY", "") clipboard_content = None # Try different display options @@ -40,7 +41,7 @@ class command(): 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) @@ -55,24 +56,32 @@ class command(): # Restore original display setting if original_display: - os.environ['DISPLAY'] = original_display + os.environ["DISPLAY"] = original_display else: - os.environ.pop('DISPLAY', None) + os.environ.pop("DISPLAY", None) # Process the clipboard content if we found any if 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) + self.env["runtime"]["MemoryManager"].add_value_to_first_index( + "clipboardHistory", clipboard_content + ) + self.env["runtime"]["OutputManager"].present_text( + "Import to Clipboard", + sound_icon="CopyToClipboard", + interrupt=True, + ) + self.env["runtime"]["OutputManager"].present_text( + clipboard_content, sound_icon="", interrupt=False + ) else: - self.env['runtime']['OutputManager'].present_text( - 'No text found in clipboard or no accessible display', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "No text found in clipboard or no accessible display", + interrupt=True, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - str(e), sound_icon ='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + str(e), sound_icon="", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py b/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py index fdf7d8ef..d52fe9a3 100644 --- a/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py +++ b/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('alsa', 'volume', 'inc') + super().__init__("alsa", "volume", "inc") diff --git a/src/fenrirscreenreader/commands/commands/inc_sound_volume.py b/src/fenrirscreenreader/commands/commands/inc_sound_volume.py index 73df4092..7c7599dc 100644 --- a/src/fenrirscreenreader/commands/commands/inc_sound_volume.py +++ b/src/fenrirscreenreader/commands/commands/inc_sound_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('sound', 'volume', 'inc') + super().__init__("sound", "volume", "inc") diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py b/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py index 9d766041..f59f63c5 100644 --- a/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py +++ b/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'pitch', 'inc') + super().__init__("speech", "pitch", "inc") diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_rate.py b/src/fenrirscreenreader/commands/commands/inc_speech_rate.py index 841bcffb..074c3ba9 100644 --- a/src/fenrirscreenreader/commands/commands/inc_speech_rate.py +++ b/src/fenrirscreenreader/commands/commands/inc_speech_rate.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'rate', 'inc') + super().__init__("speech", "rate", "inc") diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_volume.py b/src/fenrirscreenreader/commands/commands/inc_speech_volume.py index aaaef24b..484fadd1 100644 --- a/src/fenrirscreenreader/commands/commands/inc_speech_volume.py +++ b/src/fenrirscreenreader/commands/commands/inc_speech_volume.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'adjustment_base.py') +_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) @@ -17,4 +18,4 @@ adjustment_command = _module.adjustment_command class command(adjustment_command): def __init__(self): - super().__init__('speech', 'volume', 'inc') + super().__init__("speech", "volume", "inc") diff --git a/src/fenrirscreenreader/commands/commands/indent_curr_line.py b/src/fenrirscreenreader/commands/commands/indent_curr_line.py index 663e5778..fb64887c 100644 --- a/src/fenrirscreenreader/commands/commands/indent_curr_line.py +++ b/src/fenrirscreenreader/commands/commands/indent_curr_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,24 +19,32 @@ class command(): pass def get_description(self): - return _('Presents the indentation level for the current line') + 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"]: + cursor_pos = self.env["screen"]["newCursorReview"].copy() else: - cursor_pos = self.env['screen']['new_cursor'].copy() + 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']) + 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) + 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) + self.env["runtime"]["OutputManager"].present_text( + _("indent {0}").format( + len(curr_line) - len(curr_line.lstrip()) + ), + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/last_clipboard.py b/src/fenrirscreenreader/commands/commands/last_clipboard.py index 0821c52a..1e7aa6a0 100644 --- a/src/fenrirscreenreader/commands/commands/last_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/last_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,19 +19,23 @@ class command(): pass def get_description(self): - return _('selects the last clipboard') + 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"].is_index_list_empty( + "clipboardHistory" + ): + self.env["runtime"]["OutputManager"].present_text( + _("clipboard empty"), interrupt=True + ) return - self.env['runtime']['MemoryManager'].set_last_index('clipboardHistory') - clipboard = self.env['runtime']['MemoryManager'].get_index_list_element( - 'clipboardHistory') - self.env['runtime']['OutputManager'].present_text( - clipboard, interrupt=True) + self.env["runtime"]["MemoryManager"].set_last_index("clipboardHistory") + clipboard = self.env["runtime"][ + "MemoryManager" + ].get_index_list_element("clipboardHistory") + self.env["runtime"]["OutputManager"].present_text( + clipboard, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/marked_text.py b/src/fenrirscreenreader/commands/commands/marked_text.py index 678e7a58..eb63b8ea 100644 --- a/src/fenrirscreenreader/commands/commands/marked_text.py +++ b/src/fenrirscreenreader/commands/commands/marked_text.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import mark_utils -class command(): +class command: def __init__(self): pass @@ -21,28 +20,35 @@ class command(): def get_description(self): return _( - 'Presents the currently selected text that will be copied to the clipboard') + "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"].present_text( + _("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() + start_mark = self.env["commandBuffer"]["Marks"]["1"].copy() + end_mark = self.env["commandBuffer"]["Marks"]["2"].copy() marked = mark_utils.get_text_between_marks( - start_mark, end_mark, self.env['screen']['new_content_text']) + start_mark, end_mark, self.env["screen"]["new_content_text"] + ) if marked.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - marked, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + marked, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/next_clipboard.py b/src/fenrirscreenreader/commands/commands/next_clipboard.py index 8257bcea..31d6f9c3 100644 --- a/src/fenrirscreenreader/commands/commands/next_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/next_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,31 +19,39 @@ class command(): pass def get_description(self): - return _('selects the next clipboard') + 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) + 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') + 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) + self.env["runtime"]["OutputManager"].present_text( + _("First clipboard "), interrupt=True + ) if is_last: - self.env['runtime']['OutputManager'].present_text( - _('Last clipboard '), interrupt=True) + 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) + self.env["runtime"]["OutputManager"].present_text( + clipboard, interrupt=speech_interrupt + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/next_quick_menu_entry.py b/src/fenrirscreenreader/commands/commands/next_quick_menu_entry.py index c99fd2a7..0a66a36e 100644 --- a/src/fenrirscreenreader/commands/commands/next_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/commands/next_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,24 @@ class command(): pass def get_description(self): - return _('get next quick menu entry') + 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"].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 + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Quick menu not available'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Quick menu not available"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/next_quick_menu_value.py b/src/fenrirscreenreader/commands/commands/next_quick_menu_value.py index 11b4f312..1ce866cf 100644 --- a/src/fenrirscreenreader/commands/commands/next_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/commands/next_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,14 @@ class command(): pass def get_description(self): - return _('get next quick menu value') + 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) + 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): pass diff --git a/src/fenrirscreenreader/commands/commands/paste_clipboard.py b/src/fenrirscreenreader/commands/commands/paste_clipboard.py index 9a5b28f9..f47da69e 100644 --- a/src/fenrirscreenreader/commands/commands/paste_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/paste_clipboard.py @@ -2,40 +2,49 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. 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"].add_index_list( + "clipboardHistory", + self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "numberOfClipboards" + ), + ) def shutdown(self): pass def get_description(self): - return _('pastes the text from the currently selected clipboard') + 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) + 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) + 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 diff --git a/src/fenrirscreenreader/commands/commands/present_first_line.py b/src/fenrirscreenreader/commands/commands/present_first_line.py index 4bb2f3b1..9eb3d3ea 100644 --- a/src/fenrirscreenreader/commands/commands/present_first_line.py +++ b/src/fenrirscreenreader/commands/commands/present_first_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,18 +19,21 @@ class command(): pass def get_description(self): - return _('present first line') + return _("present first line") def run(self): x, y, first_line = line_utils.get_current_line( - 0, 0, self.env['screen']['new_content_text']) + 0, 0, self.env["screen"]["new_content_text"] + ) if first_line.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - first_line, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + first_line, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/present_last_line.py b/src/fenrirscreenreader/commands/commands/present_last_line.py index 0cccd403..228879c6 100644 --- a/src/fenrirscreenreader/commands/commands/present_last_line.py +++ b/src/fenrirscreenreader/commands/commands/present_last_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,18 +19,23 @@ class command(): pass def get_description(self): - return _('current line') + 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']) + 0, + self.env["screen"]["lines"] - 1, + self.env["screen"]["new_content_text"], + ) if last_line.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - last_line, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + last_line, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/prev_clipboard.py b/src/fenrirscreenreader/commands/commands/prev_clipboard.py index 3f03f3ea..6fd54902 100644 --- a/src/fenrirscreenreader/commands/commands/prev_clipboard.py +++ b/src/fenrirscreenreader/commands/commands/prev_clipboard.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,30 +19,38 @@ class command(): pass def get_description(self): - return _('selects the previous clipboard') + 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) + 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') + 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) + self.env["runtime"]["OutputManager"].present_text( + _("First clipboard "), interrupt=True + ) if is_last: - self.env['runtime']['OutputManager'].present_text( - _('Last clipboard '), interrupt=True) + 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) + self.env["runtime"]["OutputManager"].present_text( + clipboard, interrupt=speech_interrupt + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/prev_quick_menu_entry.py b/src/fenrirscreenreader/commands/commands/prev_quick_menu_entry.py index 160f0de2..0a288416 100644 --- a/src/fenrirscreenreader/commands/commands/prev_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/commands/prev_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,24 @@ class command(): pass def get_description(self): - return _('get previous quick menu entry') + 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"].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 + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Quick menu not available'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Quick menu not available"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/prev_quick_menu_value.py b/src/fenrirscreenreader/commands/commands/prev_quick_menu_value.py index 99b2dbfe..aa28e124 100644 --- a/src/fenrirscreenreader/commands/commands/prev_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/commands/prev_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,14 @@ class command(): pass def get_description(self): - return _('get previous quick menu value') + 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) + 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): pass diff --git a/src/fenrirscreenreader/commands/commands/progress_bar_monitor.py b/src/fenrirscreenreader/commands/commands/progress_bar_monitor.py index 35ba95f9..ecde4e58 100644 --- a/src/fenrirscreenreader/commands/commands/progress_bar_monitor.py +++ b/src/fenrirscreenreader/commands/commands/progress_bar_monitor.py @@ -2,69 +2,72 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import re +import threading +import time from fenrirscreenreader.core.i18n import _ -import re -import time -import threading - -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']: + 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') + default_enabled = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_bool("sound", "progressMonitoring") except Exception as e: # 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 + self.env["commandBuffer"]["progressMonitoring"] = default_enabled + 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') + 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 "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']: + if self.env["commandBuffer"]["progressMonitoring"]: self.stop_progress_monitoring() - self.env['runtime']['OutputManager'].present_text( - _("Progress monitoring disabled"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Progress monitoring disabled"), interrupt=True + ) else: self.start_progress_monitoring() - self.env['runtime']['OutputManager'].present_text( - _("Progress monitoring enabled"), interrupt=True) + 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.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 + 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']: + if not self.env["commandBuffer"]["progressMonitoring"]: return # Skip progress detection if current screen looks like a prompt @@ -74,31 +77,36 @@ class command(): current_time = time.time() # Pattern 1: Percentage (50%, 25.5%, etc.) - percent_match = re.search(r'(\d+(?:\.\d+)?)\s*%', text) + percent_match = re.search(r"(\d+(?:\.\d+)?)\s*%", text) if percent_match: percentage = float(percent_match.group(1)) - if percentage != self.env['commandBuffer']['lastProgressValue']: + if percentage != self.env["commandBuffer"]["lastProgressValue"]: self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressValue"] = percentage + self.env["commandBuffer"]["lastProgressTime"] = current_time return # Pattern 2: Fraction (15/100, 3 of 10, etc.) - fraction_match = re.search(r'(\d+)\s*(?:of|/)\s*(\d+)', text) + 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)) if total > 0: percentage = (current / total) * 100 - if percentage != self.env['commandBuffer']['lastProgressValue']: + if ( + percentage + != self.env["commandBuffer"]["lastProgressValue"] + ): self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressValue"] = percentage + self.env["commandBuffer"][ + "lastProgressTime" + ] = current_time return # Pattern 3: Progress bars ([#### ], [====> ], etc.) # Improved pattern to avoid matching IRC channels like [#channel] - bar_match = re.search(r'\[([#=\-\*]+)([\s\.]*)\]', text) + bar_match = re.search(r"\[([#=\-\*]+)([\s\.]*)\]", text) if bar_match: filled = len(bar_match.group(1)) unfilled = len(bar_match.group(2)) @@ -106,39 +114,49 @@ class command(): # 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))): + not bar_match.group(2) + or re.match(r"^[\s\.]*$", bar_match.group(2)) + ): percentage = (filled / total) * 100 - if percentage != self.env['commandBuffer']['lastProgressValue']: + if ( + percentage + != self.env["commandBuffer"]["lastProgressValue"] + ): self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressValue"] = percentage + self.env["commandBuffer"][ + "lastProgressTime" + ] = current_time return # Pattern 4: Generic activity indicators (Loading..., Working..., etc.) activity_pattern = re.search( - r'(loading|processing|working|installing|downloading|compiling|building).*\.{2,}', + r"(loading|processing|working|installing|downloading|compiling|building).*\.{2,}", text, - re.IGNORECASE) + re.IGNORECASE, + ) if activity_pattern: # Play a steady beep every 2 seconds for ongoing activity - if current_time - \ - self.env['commandBuffer']['lastProgressTime'] >= 2.0: + if ( + current_time - self.env["commandBuffer"]["lastProgressTime"] + >= 2.0 + ): self.play_activity_beep() - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressTime"] = current_time def play_progress_tone(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) + self.env["runtime"]["OutputManager"].play_frequence( + frequency, 0.15, interrupt=False + ) def play_activity_beep(self): # Single tone for generic activity - self.env['runtime']['OutputManager'].play_frequence( - 800, 0.1, interrupt=False) + self.env["runtime"]["OutputManager"].play_frequence( + 800, 0.1, interrupt=False + ) def is_current_line_prompt(self): """Check if the current line looks like a standalone prompt (not command with progress)""" @@ -146,10 +164,10 @@ class command(): try: # Get the current screen content - if not self.env['screen']['new_content_text']: + if not self.env["screen"]["new_content_text"]: return False - lines = self.env['screen']['new_content_text'].split('\n') + lines = self.env["screen"]["new_content_text"].split("\n") if not lines: return False @@ -162,34 +180,34 @@ class command(): lines_to_check.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): + 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']]) + lines[self.env["screen"]["new_cursor"]["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 - + r"^\s*\$\s*$", # Just $ (with whitespace) + r"^\s*#\s*$", # Just # (with whitespace) + r"^\s*>\s*$", # Just > (with whitespace) + r"^\[.*\]\s*[\\\$#>]\s*$", # [path]$ without commands + r"^[a-zA-Z0-9._-]+[\\\$#>]\s*$", # bash-5.1$ without commands # Interactive prompt patterns (these ARE standalone) - r'.*\?\s*\[[YyNn]/[YyNn]\]\s*$', # ? [Y/n] or ? [y/N] style - r'.*\?\s*\[[Yy]es/[Nn]o\]\s*$', # ? [Yes/No] style + r".*\?\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".*continue\?\s*\[[YyNn]/[YyNn]\].*$", + 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: @@ -200,22 +218,21 @@ class command(): # 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)) + 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, # it's a command line, not a standalone prompt prompt_end = max( - line.rfind('$'), - line.rfind('#'), - line.rfind('>'), - line.rfind('\\') + 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 ( + prompt_end >= 0 and prompt_end < len(line) - 5 + ): # More than just whitespace after prompt continue # This is a command line, not a standalone prompt for pattern in standalone_prompt_patterns: diff --git a/src/fenrirscreenreader/commands/commands/quit_fenrir.py b/src/fenrirscreenreader/commands/commands/quit_fenrir.py index af047e12..d103bf77 100644 --- a/src/fenrirscreenreader/commands/commands/quit_fenrir.py +++ b/src/fenrirscreenreader/commands/commands/quit_fenrir.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +19,10 @@ class command(): pass def get_description(self): - return _('exits Fenrir') + return _("exits Fenrir") def run(self): - self.env['runtime']['EventManager'].stop_main_event_loop() + self.env["runtime"]["EventManager"].stop_main_event_loop() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/remove_marks.py b/src/fenrirscreenreader/commands/commands/remove_marks.py index 1cccc40c..cde557a6 100644 --- a/src/fenrirscreenreader/commands/commands/remove_marks.py +++ b/src/fenrirscreenreader/commands/commands/remove_marks.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,13 @@ class command(): pass def get_description(self): - return _('Removes marks from selected text') + 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"].clear_marks() + self.env["runtime"]["OutputManager"].present_text( + _("Remove marks"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py b/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py index 0bd4c041..9b2361c4 100644 --- a/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py +++ b/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py @@ -2,23 +2,25 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +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: pass -class command(): +class command: def __init__(self): - self.language = '' + self.language = "" self.spellChecker = None def initialize(self, environment): @@ -29,46 +31,67 @@ class command(): pass def get_description(self): - return _('removes the current word from the exceptions dictionary') + 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') + self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) + ) + self.language = self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) def run(self): if not initialized: - self.env['runtime']['OutputManager'].present_text( - _('pyenchant is not installed'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("pyenchant is not installed"), interrupt=True + ) return - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') != self.language: + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "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() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() # 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) + 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'!"#$%&()*+,-./:;<=Â?@[\\]^_{|}~') + 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) + self.env["runtime"]["OutputManager"].present_text( + _("{0} is not in the dictionary").format( + curr_word, + ), + sound_icon="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) + self.env["runtime"]["OutputManager"].present_text( + _("{0} removed").format( + curr_word, + ), + sound_icon="Accept", + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_bottom.py b/src/fenrirscreenreader/commands/commands/review_bottom.py index 66d9b55a..5c19d2ad 100644 --- a/src/fenrirscreenreader/commands/commands/review_bottom.py +++ b/src/fenrirscreenreader/commands/commands/review_bottom.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,16 @@ class command(): pass def get_description(self): - return _('Move review to the bottom of the screen') + 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"].present_text( + _("Bottom"), interrupt=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_char.py b/src/fenrirscreenreader/commands/commands/review_curr_char.py index 62203cb9..637b6982 100644 --- a/src/fenrirscreenreader/commands/commands/review_curr_char.py +++ b/src/fenrirscreenreader/commands/commands/review_curr_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,30 +19,43 @@ class command(): pass def get_description(self): - return _('presents the current character.') + return _("presents the current character.") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], curr_char = char_utils.get_current_char( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + ( + 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) + 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 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): + if not self.env["runtime"]["AttributeManager"].has_attributes( + cursor_pos + ): return - self.env['runtime']['OutputManager'].present_text( - 'has attribute', sound_icon ='HasAttributes', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "has attribute", sound_icon="HasAttributes", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py index 51e375a2..153d51b7 100644 --- a/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,21 +19,32 @@ class command(): pass def get_description(self): - return _('set review and phonetically presents the current character') + 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" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], curr_char = char_utils.get_current_char( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + ( + 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["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: curr_char = char_utils.get_phonetic(curr_char) - self.env['runtime']['OutputManager'].present_text( - curr_char, interrupt=True, announce_capital=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + curr_char, interrupt=True, announce_capital=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_line.py b/src/fenrirscreenreader/commands/commands/review_curr_line.py index 647524f3..8ab1f96c 100644 --- a/src/fenrirscreenreader/commands/commands/review_curr_line.py +++ b/src/fenrirscreenreader/commands/commands/review_curr_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,20 +19,31 @@ class command(): pass def get_description(self): - return _('current line') + return _("current line") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], curr_line = line_utils.get_current_line( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + ( + 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["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - curr_line, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + curr_line, interrupt=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_word.py b/src/fenrirscreenreader/commands/commands/review_curr_word.py index b5118d6b..71c053f2 100644 --- a/src/fenrirscreenreader/commands/commands/review_curr_word.py +++ b/src/fenrirscreenreader/commands/commands/review_curr_word.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -20,30 +19,49 @@ class command(): pass def get_description(self): - return _('current word.') + return _("current word.") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + 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']) + ( + 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"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - curr_word, interrupt=True, flush=False) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py index 98b98bc1..0dac32ef 100644 --- a/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils from fenrirscreenreader.utils import char_utils +from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -21,33 +20,55 @@ class command(): pass def get_description(self): - return _('Phonetically spells the current word') + 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']) + 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"]["OutputManager"].present_text( + _("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) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_down.py b/src/fenrirscreenreader/commands/commands/review_down.py index 5984fec9..25a7d3f0 100644 --- a/src/fenrirscreenreader/commands/commands/review_down.py +++ b/src/fenrirscreenreader/commands/commands/review_down.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,23 +19,38 @@ class command(): pass def get_description(self): - return _('Move review to the character below the current position') + 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( + 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) + 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 self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "end_of_screen" + ): + self.env["runtime"]["OutputManager"].present_text( + _("end of screen"), + interrupt=True, + sound_icon="EndOfScreen", + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_begin.py b/src/fenrirscreenreader/commands/commands/review_line_begin.py index 5968dd40..3850ff74 100644 --- a/src/fenrirscreenreader/commands/commands/review_line_begin.py +++ b/src/fenrirscreenreader/commands/commands/review_line_begin.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,27 +19,42 @@ class command(): pass def get_description(self): - return _('set review cursor to begin of current line and display the content') + return _( + "set review cursor to begin of current line and display the content" + ) def run(self): - 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']) + 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) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_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( - _("beginning of line"), interrupt=False) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("beginning of line"), interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_end.py b/src/fenrirscreenreader/commands/commands/review_line_end.py index 22edc411..4118af91 100644 --- a/src/fenrirscreenreader/commands/commands/review_line_end.py +++ b/src/fenrirscreenreader/commands/commands/review_line_end.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,23 +19,37 @@ class command(): pass def get_description(self): - return _('Move Review to the end of current line and display the content') + return _( + "Move Review to the end of current line and display the content" + ) def run(self): - 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']) + 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( + 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) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("end of line"), interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_first_char.py b/src/fenrirscreenreader/commands/commands/review_line_first_char.py index 2898a0ff..703821a3 100644 --- a/src/fenrirscreenreader/commands/commands/review_line_first_char.py +++ b/src/fenrirscreenreader/commands/commands/review_line_first_char.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import char_utils +from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -21,29 +20,48 @@ class command(): pass def get_description(self): - return _('Move Review to the first character on the line') + return _("Move Review to the first character on the line") def run(self): - cursor_pos = self.env['runtime']['CursorManager'].get_review_or_text_cursor() + 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']) + 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) + 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']) + self.env["runtime"]["CursorManager"].set_review_cursor_position( + (len(curr_line) - len(curr_line.lstrip())), cursor_pos["y"] + ) + ( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + curr_char, + ) = char_utils.get_current_char( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) char_utils.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) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("first character in line indent {0}").format( + str(len(curr_line) - len(curr_line.lstrip())) + ), + interrupt=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_last_char.py b/src/fenrirscreenreader/commands/commands/review_line_last_char.py index 7e9ef046..28da01e5 100644 --- a/src/fenrirscreenreader/commands/commands/review_line_last_char.py +++ b/src/fenrirscreenreader/commands/commands/review_line_last_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,23 +19,34 @@ class command(): pass def get_description(self): - return _('Move Review to the last character on the line') + return _("Move Review to the last character on the line") def run(self): - 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']) + 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) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("last character in line"), interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_char.py b/src/fenrirscreenreader/commands/commands/review_next_char.py index 685efa28..b576f65f 100644 --- a/src/fenrirscreenreader/commands/commands/review_next_char.py +++ b/src/fenrirscreenreader/commands/commands/review_next_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,39 +19,60 @@ class command(): pass def get_description(self): - return _('Moves review to the next character ') + return _("Moves review to the next character") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], next_char, end_of_screen, line_break = char_utils.get_next_char( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() + ( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + next_char, + end_of_screen, + line_break, + ) = char_utils.get_next_char( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) char_utils.present_char_for_review( self.env, next_char, interrupt=True, announce_capital=True, - flush=False) + 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 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') + 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 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): + if not self.env["runtime"]["AttributeManager"].has_attributes( + cursor_pos + ): return - self.env['runtime']['OutputManager'].present_text( - 'has attribute', sound_icon ='HasAttributes', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "has attribute", sound_icon="HasAttributes", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py index e9cb8277..c3029864 100644 --- a/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,27 +19,47 @@ class command(): pass def get_description(self): - return _('phonetically presents the next character and set review to it') + 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" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], next_char, end_of_screen, line_break = char_utils.get_next_char( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + ( + 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) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_line.py b/src/fenrirscreenreader/commands/commands/review_next_line.py index 10bc0a14..7ee8fb43 100644 --- a/src/fenrirscreenreader/commands/commands/review_next_line.py +++ b/src/fenrirscreenreader/commands/commands/review_next_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,27 +19,45 @@ class command(): pass def get_description(self): - return _('moves review to the next line ') + 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"]["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"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + nextLine, + end_of_screen, + ) = line_utils.get_next_line( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) if nextLine.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - nextLine, interrupt=True, flush=False) + 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "end_of_screen" + ): + self.env["runtime"]["OutputManager"].present_text( + _("end of screen"), + interrupt=True, + sound_icon="EndOfScreen", + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_word.py b/src/fenrirscreenreader/commands/commands/review_next_word.py index 17c9151b..debb5a3f 100644 --- a/src/fenrirscreenreader/commands/commands/review_next_word.py +++ b/src/fenrirscreenreader/commands/commands/review_next_word.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -20,32 +19,53 @@ class command(): pass def get_description(self): - return _('moves review to the next word ') + return _("moves review to the next word ") def run(self): - self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] - if self.env['screen']['newCursorReview'] is None: - self.env['screen']['newCursorReview'] = self.env['screen']['new_cursor'].copy() + self.env["screen"]["oldCursorReview"] = self.env["screen"][ + "newCursorReview" + ] + if self.env["screen"]["newCursorReview"] is None: + self.env["screen"]["newCursorReview"] = self.env["screen"][ + "new_cursor" + ].copy() - 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"], + 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"], + ) if next_word.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - next_word, interrupt=True, flush=False) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py index e32346f3..45b7cb90 100644 --- a/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils from fenrirscreenreader.utils import char_utils +from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -21,33 +20,55 @@ class command(): pass def get_description(self): - return _('Phonetically spells the next word and moves review to it') + return _("Phonetically spells the next word and moves review to it") def run(self): - 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["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"], + ) if next_word.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: first_sequence = True for c in next_word: curr_char = char_utils.get_phonetic(c) - self.env['runtime']['OutputManager'].present_text( - curr_char, interrupt=first_sequence, announce_capital=True, flush=False) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_char.py b/src/fenrirscreenreader/commands/commands/review_prev_char.py index 2cc2ca79..4c8c159e 100644 --- a/src/fenrirscreenreader/commands/commands/review_prev_char.py +++ b/src/fenrirscreenreader/commands/commands/review_prev_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,42 +19,65 @@ class command(): pass def get_description(self): - return _('moves review to the previous character ') + return _("moves review to the previous character") 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"]["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'], prev_char, end_of_screen, line_break = char_utils.get_prev_char( - 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"], + prev_char, + end_of_screen, + line_break, + ) = char_utils.get_prev_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, prev_char, interrupt=True, announce_capital=True, - flush=False) + 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 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') + 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 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): + if not self.env["runtime"]["AttributeManager"].has_attributes( + cursor_pos + ): return - self.env['runtime']['OutputManager'].present_text( - 'has attribute', sound_icon ='HasAttributes', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "has attribute", sound_icon="HasAttributes", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py index 5958d224..295ebc19 100644 --- a/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,27 +19,47 @@ class command(): pass def get_description(self): - return _('phonetically presents the previous character and set review to it') + return _( + "phonetically presents the previous character and set review to it" + ) def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prev_char, end_of_screen, line_break = char_utils.get_prev_char( - 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"], + prev_char, + end_of_screen, + line_break, + ) = char_utils.get_prev_char( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) prev_char = char_utils.get_phonetic(prev_char) - self.env['runtime']['OutputManager'].present_text( - prev_char, interrupt=True, announce_capital=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + prev_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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_line.py b/src/fenrirscreenreader/commands/commands/review_prev_line.py index f71bd993..87d5fda9 100644 --- a/src/fenrirscreenreader/commands/commands/review_prev_line.py +++ b/src/fenrirscreenreader/commands/commands/review_prev_line.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils -class command(): +class command: def __init__(self): pass @@ -20,25 +19,41 @@ class command(): pass def get_description(self): - return _('moves review to the previous line ') + return _("moves review to the previous line ") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prev_line, end_of_screen = line_utils.get_prev_line( - 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"], + prev_line, + end_of_screen, + ) = line_utils.get_prev_line( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) if prev_line.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - prev_line, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + prev_line, 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 self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "end_of_screen" + ): + self.env["runtime"]["OutputManager"].present_text( + _("end of screen"), + interrupt=True, + sound_icon="EndOfScreen", + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_word.py b/src/fenrirscreenreader/commands/commands/review_prev_word.py index e94d2ba0..19268abe 100644 --- a/src/fenrirscreenreader/commands/commands/review_prev_word.py +++ b/src/fenrirscreenreader/commands/commands/review_prev_word.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -20,30 +19,49 @@ class command(): pass def get_description(self): - return _('moves review focus to the previous word ') + return _("moves review focus to the previous word ") def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prev_word, end_of_screen, line_break = word_utils.get_prev_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"], + prev_word, + end_of_screen, + line_break, + ) = word_utils.get_prev_word( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) if prev_word.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - prev_word, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + prev_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=False, sound_icon ='EndOfScreen') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "end_of_screen" + ): + self.env["runtime"]["OutputManager"].present_text( + _("end of screen"), + interrupt=False, + 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py index ebdea968..eadca6da 100644 --- a/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py +++ b/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils from fenrirscreenreader.utils import char_utils +from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -21,33 +20,57 @@ class command(): pass def get_description(self): - return _('Phonetically spells the previous word and moves review to it') + return _( + "Phonetically spells the previous word and moves review to it" + ) def run(self): - self.env['runtime']['CursorManager'].enter_review_mode_curr_text_cursor() - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prev_word, end_of_screen, line_break = word_utils.get_prev_word( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + self.env["runtime"][ + "CursorManager" + ].enter_review_mode_curr_text_cursor() + ( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + prev_word, + end_of_screen, + line_break, + ) = word_utils.get_prev_word( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) if prev_word.isspace(): - self.env['runtime']['OutputManager'].present_text( - _("blank"), interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), interrupt=True, flush=False + ) else: first_sequence = True for c in prev_word: curr_char = char_utils.get_phonetic(c) - self.env['runtime']['OutputManager'].present_text( - curr_char, interrupt=first_sequence, announce_capital=True, flush=False) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_screen_first_char.py b/src/fenrirscreenreader/commands/commands/review_screen_first_char.py index 349fba8f..ebd63160 100644 --- a/src/fenrirscreenreader/commands/commands/review_screen_first_char.py +++ b/src/fenrirscreenreader/commands/commands/review_screen_first_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,22 +19,32 @@ class command(): pass def get_description(self): - return _('Move Review to the first character on the screen (left top)') + return _("Move Review to the first character on the screen (left top)") def run(self): - cursor_pos = self.env['runtime']['CursorManager'].get_review_or_text_cursor() - self.env['runtime']['CursorManager'].set_review_cursor_position(0, 0) - 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']) + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() + self.env["runtime"]["CursorManager"].set_review_cursor_position(0, 0) + ( + 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( - _("first character in screen"), interrupt=False) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("first character in screen"), interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_screen_last_char.py b/src/fenrirscreenreader/commands/commands/review_screen_last_char.py index a1258493..af5b0cc3 100644 --- a/src/fenrirscreenreader/commands/commands/review_screen_last_char.py +++ b/src/fenrirscreenreader/commands/commands/review_screen_last_char.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,23 +19,36 @@ class command(): pass def get_description(self): - return _('Move Review to the last character on the screen (right bottom)') + return _( + "Move Review to the last character on the screen (right bottom)" + ) def run(self): - cursor_pos = self.env['runtime']['CursorManager'].get_review_or_text_cursor() - self.env['runtime']['CursorManager'].set_review_cursor_position( - self.env['screen']['columns'] - 1, self.env['screen']['lines'] - 1) - 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']) + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() + self.env["runtime"]["CursorManager"].set_review_cursor_position( + self.env["screen"]["columns"] - 1, self.env["screen"]["lines"] - 1 + ) + ( + 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 screen"), interrupt=False) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + _("last character in screen"), interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_top.py b/src/fenrirscreenreader/commands/commands/review_top.py index a5e2e032..8767810e 100644 --- a/src/fenrirscreenreader/commands/commands/review_top.py +++ b/src/fenrirscreenreader/commands/commands/review_top.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -20,12 +19,13 @@ class command(): pass def get_description(self): - return _('move review to top of screen') + return _("move review to top of screen") def run(self): - self.env['screen']['newCursorReview'] = {'x': 0, 'y': 0} - self.env['runtime']['OutputManager'].present_text( - _("Top"), interrupt=True, flush=False) + self.env["screen"]["newCursorReview"] = {"x": 0, "y": 0} + self.env["runtime"]["OutputManager"].present_text( + _("Top"), interrupt=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/review_up.py b/src/fenrirscreenreader/commands/commands/review_up.py index 63145c68..d538ea75 100644 --- a/src/fenrirscreenreader/commands/commands/review_up.py +++ b/src/fenrirscreenreader/commands/commands/review_up.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils -class command(): +class command: def __init__(self): pass @@ -21,29 +20,47 @@ class command(): def get_description(self): return _( - 'Move review to the character in the line above the current position') + "Move review to the character in the line above 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'], upChar, end_of_screen = char_utils.get_up_char( - self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['new_content_text']) + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() + ( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + upChar, + end_of_screen, + ) = char_utils.get_up_char( + self.env["screen"]["newCursorReview"]["x"], + self.env["screen"]["newCursorReview"]["y"], + self.env["screen"]["new_content_text"], + ) line_break = False - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( upChar, interrupt=True, ignore_punctuation=True, announce_capital=True, - flush=False) + 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 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') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "line_break" + ): + self.env["runtime"]["OutputManager"].present_text( + _("line break"), interrupt=False, sound_icon="EndOfLine" + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/save_settings.py b/src/fenrirscreenreader/commands/commands/save_settings.py index bfce0276..f34efad8 100644 --- a/src/fenrirscreenreader/commands/commands/save_settings.py +++ b/src/fenrirscreenreader/commands/commands/save_settings.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import settingsManager +from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,13 +19,16 @@ class command(): pass def get_description(self): - return _('Saves your current Fenrir settings so they are the default.') + return _("Saves your current Fenrir settings so they are the default.") def run(self): - settings_file = self.env['runtime']['SettingsManager'].get_settings_file() - self.env['runtime']['SettingsManager'].save_settings(settings_file) - self.env['runtime']['OutputManager'].present_text( - _("Settings saved."), interrupt=True) + settings_file = self.env["runtime"][ + "SettingsManager" + ].get_settings_file() + self.env["runtime"]["SettingsManager"].save_settings(settings_file) + self.env["runtime"]["OutputManager"].present_text( + _("Settings saved."), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_1.py b/src/fenrirscreenreader/commands/commands/set_bookmark_1.py index 888331e3..bb98e1cb 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_1.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_1.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(1, 'set') + super().__init__(1, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_10.py b/src/fenrirscreenreader/commands/commands/set_bookmark_10.py index fb4d3288..824862d8 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_10.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_10.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(10, 'set') + super().__init__(10, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_2.py b/src/fenrirscreenreader/commands/commands/set_bookmark_2.py index 0b78549d..6874c3ac 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_2.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_2.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(2, 'set') + super().__init__(2, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_3.py b/src/fenrirscreenreader/commands/commands/set_bookmark_3.py index c9e5dfc4..a6628608 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_3.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_3.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(3, 'set') + super().__init__(3, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_4.py b/src/fenrirscreenreader/commands/commands/set_bookmark_4.py index fee7efe2..47206450 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_4.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_4.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(4, 'set') + super().__init__(4, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_5.py b/src/fenrirscreenreader/commands/commands/set_bookmark_5.py index e2f29134..7bc36180 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_5.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_5.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(5, 'set') + super().__init__(5, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_6.py b/src/fenrirscreenreader/commands/commands/set_bookmark_6.py index 1584c176..e0499ecd 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_6.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_6.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(6, 'set') + super().__init__(6, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_7.py b/src/fenrirscreenreader/commands/commands/set_bookmark_7.py index 86ad3ddb..4092610e 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_7.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_7.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(7, 'set') + super().__init__(7, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_8.py b/src/fenrirscreenreader/commands/commands/set_bookmark_8.py index 1f1cd1ad..585959ca 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_8.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_8.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(8, 'set') + super().__init__(8, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_9.py b/src/fenrirscreenreader/commands/commands/set_bookmark_9.py index 2996f53c..a765117c 100644 --- a/src/fenrirscreenreader/commands/commands/set_bookmark_9.py +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_9.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import importlib.util +import os from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -_base_path = os.path.join(os.path.dirname(__file__), 'bookmark_base.py') +_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) @@ -17,4 +18,4 @@ bookmark_command = _module.bookmark_command class command(bookmark_command): def __init__(self): - super().__init__(9, 'set') + super().__init__(9, "set") diff --git a/src/fenrirscreenreader/commands/commands/set_mark.py b/src/fenrirscreenreader/commands/commands/set_mark.py index 675a59e1..e9056af0 100644 --- a/src/fenrirscreenreader/commands/commands/set_mark.py +++ b/src/fenrirscreenreader/commands/commands/set_mark.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,21 +19,24 @@ class command(): pass def get_description(self): - return _('places marks to select text to copy to the clipboard') + return _("places marks to select text to copy to the clipboard") def run(self): - if not self.env['runtime']['CursorManager'].is_review_mode(): - self.env['runtime']['OutputManager'].present_text( - _('no review cursor'), interrupt=True) + if not self.env["runtime"]["CursorManager"].is_review_mode(): + self.env["runtime"]["OutputManager"].present_text( + _("no review cursor"), interrupt=True + ) return - curr_mark = self.env['runtime']['CursorManager'].set_mark() + curr_mark = self.env["runtime"]["CursorManager"].set_mark() if curr_mark == 1: - self.env['runtime']['OutputManager'].present_text( - _('set mark'), sound_icon ='PlaceStartMark', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("set mark"), sound_icon="PlaceStartMark", interrupt=True + ) elif curr_mark == 2: - self.env['runtime']['OutputManager'].present_text( - _('set mark'), sound_icon ='PlaceEndMark', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("set mark"), sound_icon="PlaceEndMark", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/set_window_application.py b/src/fenrirscreenreader/commands/commands/set_window_application.py index 71f87338..5e8c63ea 100644 --- a/src/fenrirscreenreader/commands/commands/set_window_application.py +++ b/src/fenrirscreenreader/commands/commands/set_window_application.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,22 @@ class command(): pass def get_description(self): - return _('set Window Mode, needs 2 marks ') + return _("set Window Mode, needs 2 marks ") def run(self): - if self.env['runtime']['CursorManager'].set_window_for_application(): - curr_app = self.env['runtime']['ApplicationManager'].get_current_application( + if self.env["runtime"]["CursorManager"].set_window_for_application(): + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() + self.env["runtime"]["OutputManager"].present_text( + _("Window Mode on for application {0}").format(curr_app), + interrupt=True, ) - self.env['runtime']['OutputManager'].present_text( - _('Window Mode on for application {0}').format(curr_app), interrupt=True) - self.env['runtime']['CursorManager'].clear_marks() + self.env["runtime"]["CursorManager"].clear_marks() else: - self.env['runtime']['OutputManager'].present_text( - _("Set window begin and end marks"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Set window begin and end marks"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/shut_up.py b/src/fenrirscreenreader/commands/commands/shut_up.py index 931926d8..7c830e40 100644 --- a/src/fenrirscreenreader/commands/commands/shut_up.py +++ b/src/fenrirscreenreader/commands/commands/shut_up.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,14 +19,14 @@ class command(): pass def get_description(self): - return _('Interrupts the current presentation') + return _("Interrupts the current presentation") def run(self): - if len( - self.env['input']['prevDeepestInput']) > len( - self.env['input']['currInput']): + if len(self.env["input"]["prevDeepestInput"]) > len( + self.env["input"]["currInput"] + ): return - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/silence_until_prompt.py b/src/fenrirscreenreader/commands/commands/silence_until_prompt.py index ba95d278..366692ab 100644 --- a/src/fenrirscreenreader/commands/commands/silence_until_prompt.py +++ b/src/fenrirscreenreader/commands/commands/silence_until_prompt.py @@ -2,72 +2,82 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.core import debug import re +from fenrirscreenreader.core import debug +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 'silenceUntilPrompt' not in self.env['commandBuffer']: - self.env['commandBuffer']['silenceUntilPrompt'] = False + if "silenceUntilPrompt" not in self.env["commandBuffer"]: + self.env["commandBuffer"]["silenceUntilPrompt"] = False def shutdown(self): pass def get_description(self): - return _('Toggle speech silence until shell prompt returns') + return _("Toggle speech silence until shell prompt returns") def run(self): - if self.env['commandBuffer']['silenceUntilPrompt']: + if self.env["commandBuffer"]["silenceUntilPrompt"]: self.disable_silence() else: self.enable_silence() def enable_silence(self): - self.env['commandBuffer']['silenceUntilPrompt'] = True - self.env['runtime']['OutputManager'].present_text( + self.env["commandBuffer"]["silenceUntilPrompt"] = True + self.env["runtime"]["OutputManager"].present_text( _("Speech silenced until prompt returns"), - sound_icon ='SpeechOff', - interrupt=True) + sound_icon="SpeechOff", + interrupt=True, + ) # Disable speech but don't use the normal temp disable that reactivates # on keypress - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', 'False') + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "enabled", "False" + ) def disable_silence(self): - self.env['commandBuffer']['silenceUntilPrompt'] = False + self.env["commandBuffer"]["silenceUntilPrompt"] = False # Re-enable speech - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', 'True') - self.env['runtime']['OutputManager'].present_text( - _("Speech restored"), sound_icon ='SpeechOn', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "enabled", "True" + ) + self.env["runtime"]["OutputManager"].present_text( + _("Speech restored"), sound_icon="SpeechOn", interrupt=True + ) def check_for_prompt(self, text): """Check if the current line contains a shell prompt pattern""" - if not self.env['commandBuffer']['silenceUntilPrompt']: + if not self.env["commandBuffer"]["silenceUntilPrompt"]: return False # First check for exact matches from settings (with backward # compatibility) try: - exact_matches = self.env['runtime']['SettingsManager'].get_setting( - 'prompt', 'exact_matches') + exact_matches = self.env["runtime"]["SettingsManager"].get_setting( + "prompt", "exact_matches" + ) if exact_matches: - exact_list = [match.strip() - for match in exact_matches.split(',') if match.strip()] + exact_list = [ + match.strip() + for match in exact_matches.split(",") + if match.strip() + ] for exactMatch in exact_list: if text.strip() == exactMatch: - self.env['runtime']['DebugManager'].write_debug_out( - "found exact prompt match: " + exactMatch, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "found exact prompt match: " + exactMatch, + debug.DebugLevel.INFO, + ) self.disable_silence() return True except Exception as e: @@ -78,70 +88,76 @@ class command(): # Get custom patterns from settings (with backward compatibility) prompt_patterns = [] try: - custom_patterns = self.env['runtime']['SettingsManager'].get_setting( - 'prompt', 'custom_patterns') + custom_patterns = self.env["runtime"][ + "SettingsManager" + ].get_setting("prompt", "custom_patterns") # Add custom patterns from settings if they exist if custom_patterns: custom_list = [ - pattern.strip() for pattern in custom_patterns.split(',') if pattern.strip()] + pattern.strip() + for pattern in custom_patterns.split(",") + if pattern.strip() + ] prompt_patterns.extend(custom_list) except Exception as e: # Prompt section doesn't exist in settings, skip custom patterns pass # Add default shell prompt patterns - prompt_patterns.extend([ - r'^\s*\$\s*$', # Just $ (with whitespace) - r'^\s*#\s*$', # Just # (with whitespace) - r'^\s*>\s*$', # Just > (with whitespace) - r'.*@.*[\\\$#>]\s*$', - # Contains @ and ends with prompt char (user@host style) - r'^\[.*\]\s*[\\\$#>]\s*$', # [anything]$ style prompts - # Simple shell names like bash-5.1$ - r'^[a-zA-Z0-9._-]+[\\\$#>]\s*$', - - # Interactive prompt patterns - # Package manager confirmation prompts - r'.*\?\s*\[[YyNn]/[YyNn]\]\s*$', # ? [Y/n] or ? [y/N] style - r'.*\?\s*\[[Yy]es/[Nn]o\]\s*$', # ? [Yes/No] style - 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'.*ok\s*\[[YyNn]/[YyNn]\].*$', # "Is this ok [y/N]:" style - # pacman ":: Proceed? [Y/n]" style - r'^::.*\?\s*\[[YyNn]/[YyNn]\].*$', - - # Authentication prompts - # [sudo] password for user: - r'^\[[Ss]udo\]\s*[Pp]assword\s*for\s+.*:\s*$', - r'^[Pp]assword\s*:\s*$', # Password: - r'.*[Pp]assword\s*:\s*$', # general password prompts - r".*'s\s*[Pp]assword\s*:\s*$", # user's password: - r'^[Ee]nter\s+[Pp]assphrase.*:\s*$', # Enter passphrase: - # Please enter passphrase: - r'^[Pp]lease\s+enter\s+[Pp]assphrase.*:\s*$', - - # General confirmation and continuation prompts - # Press any key to continue - r'^[Pp]ress\s+any\s+key\s+to\s+continue.*$', - r'^[Aa]re\s+you\s+sure\?\s*.*$', # Are you sure? - r'^[Pp]lease\s+confirm.*$', # Please confirm - r'.*confirm.*\([YyNn]/[YyNn]\).*$', # confirm (y/n) - r'.*\([Yy]/[Nn]\)\s*$', # ends with (Y/n) or (y/N) - ]) + prompt_patterns.extend( + [ + r"^\s*\$\s*$", # Just $ (with whitespace) + r"^\s*#\s*$", # Just # (with whitespace) + r"^\s*>\s*$", # Just > (with whitespace) + r".*@.*[\\\$#>]\s*$", + # Contains @ and ends with prompt char (user@host style) + r"^\[.*\]\s*[\\\$#>]\s*$", # [anything]$ style prompts + # Simple shell names like bash-5.1$ + r"^[a-zA-Z0-9._-]+[\\\$#>]\s*$", + # Interactive prompt patterns + # Package manager confirmation prompts + r".*\?\s*\[[YyNn]/[YyNn]\]\s*$", # ? [Y/n] or ? [y/N] style + r".*\?\s*\[[Yy]es/[Nn]o\]\s*$", # ? [Yes/No] style + 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".*ok\s*\[[YyNn]/[YyNn]\].*$", # "Is this ok [y/N]:" style + # pacman ":: Proceed? [Y/n]" style + r"^::.*\?\s*\[[YyNn]/[YyNn]\].*$", + # Authentication prompts + # [sudo] password for user: + r"^\[[Ss]udo\]\s*[Pp]assword\s*for\s+.*:\s*$", + r"^[Pp]assword\s*:\s*$", # Password: + r".*[Pp]assword\s*:\s*$", # general password prompts + r".*'s\s*[Pp]assword\s*:\s*$", # user's password: + r"^[Ee]nter\s+[Pp]assphrase.*:\s*$", # Enter passphrase: + # Please enter passphrase: + r"^[Pp]lease\s+enter\s+[Pp]assphrase.*:\s*$", + # General confirmation and continuation prompts + # Press any key to continue + r"^[Pp]ress\s+any\s+key\s+to\s+continue.*$", + r"^[Aa]re\s+you\s+sure\?\s*.*$", # Are you sure? + r"^[Pp]lease\s+confirm.*$", # Please confirm + r".*confirm.*\([YyNn]/[YyNn]\).*$", # confirm (y/n) + r".*\([Yy]/[Nn]\)\s*$", # ends with (Y/n) or (y/N) + ] + ) for pattern in prompt_patterns: try: if re.search(pattern, text.strip()): - self.env['runtime']['DebugManager'].write_debug_out( - "found prompt pattern: " + pattern, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "found prompt pattern: " + pattern, + debug.DebugLevel.INFO, + ) self.disable_silence() return True except re.error as e: # Invalid regex pattern, skip it and log the error - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "Invalid prompt pattern: " + pattern + " Error: " + str(e), - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) continue return False diff --git a/src/fenrirscreenreader/commands/commands/spell_check.py b/src/fenrirscreenreader/commands/commands/spell_check.py index 9aaa9306..c9638f1b 100644 --- a/src/fenrirscreenreader/commands/commands/spell_check.py +++ b/src/fenrirscreenreader/commands/commands/spell_check.py @@ -2,22 +2,23 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import word_utils + initialized = False try: import enchant + initialized = True except Exception as e: pass -class command(): +class command: def __init__(self): - self.language = '' + self.language = "" self.spellChecker = None def initialize(self, environment): @@ -28,44 +29,58 @@ class command(): pass def get_description(self): - return _('checks the spelling of the current word') + return _("checks the spelling of the current word") def update_spell_language(self): if not initialized: return self.spellChecker = enchant.Dict( - self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage')) - self.language = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') + self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) + ) + self.language = self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) def run(self): if not initialized: - self.env['runtime']['OutputManager'].present_text( - _('pyenchant is not installed'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("pyenchant is not installed"), interrupt=True + ) return - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') != self.language: + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "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() + cursor_pos = self.env["runtime"][ + "CursorManager" + ].get_review_or_text_cursor() # 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) + 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) + ) if not curr_word.isspace(): if not self.spellChecker.check(curr_word): - self.env['runtime']['OutputManager'].present_text( - _('misspelled'), sound_icon ='mispell', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("misspelled"), sound_icon="mispell", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('correct'), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("correct"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/subprocess.py b/src/fenrirscreenreader/commands/commands/subprocess.py index f38f3d46..3c9ab294 100644 --- a/src/fenrirscreenreader/commands/commands/subprocess.py +++ b/src/fenrirscreenreader/commands/commands/subprocess.py @@ -2,21 +2,22 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import _thread +import os +import subprocess +from subprocess import PIPE +from subprocess import Popen from fenrirscreenreader.core.i18n import _ -import subprocess -import os -from subprocess import Popen, PIPE -import _thread - -class command(): +class command: def __init__(self): pass - def initialize(self, environment, script_path=''): + def initialize(self, environment, script_path=""): self.env = environment self.script_path = script_path @@ -24,42 +25,54 @@ class command(): pass def get_description(self): - return _('script: {0} fullpath: {1}').format( - os.path.basename(self.script_path), self.script_path) + return _("script: {0} fullpath: {1}").format( + os.path.basename(self.script_path), self.script_path + ) def run(self): if not os.path.exists(self.script_path): - self.env['runtime']['OutputManager'].present_text( - _('Script file not found'), sound_icon='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + _("Script file not found"), sound_icon="", interrupt=False + ) return if not os.path.isfile(self.script_path): - self.env['runtime']['OutputManager'].present_text( - _('Script source is not a valid file'), sound_icon='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + _("Script source is not a valid file"), + sound_icon="", + interrupt=False, + ) return if not os.access(self.script_path, os.X_OK): - self.env['runtime']['OutputManager'].present_text( - _('Script file is not executable'), sound_icon='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + _("Script file is not executable"), + sound_icon="", + interrupt=False, + ) return _thread.start_new_thread(self._thread_run, ()) def _thread_run(self): try: - callstring = self.script_path + ' ' + \ - self.env['general']['curr_user'] + callstring = ( + self.script_path + " " + self.env["general"]["curr_user"] + ) p = Popen(callstring, stdout=PIPE, stderr=PIPE, shell=True) stdout, stderr = p.communicate() - stdout = stdout.decode('utf-8') - stderr = stderr.decode('utf-8') - self.env['runtime']['OutputManager'].interrupt_output() - if stderr != '': - self.env['runtime']['OutputManager'].present_text( - str(stderr), sound_icon='', interrupt=False) - if stdout != '': - self.env['runtime']['OutputManager'].present_text( - str(stdout), sound_icon='', interrupt=False) + stdout = stdout.decode("utf-8") + stderr = stderr.decode("utf-8") + self.env["runtime"]["OutputManager"].interrupt_output() + if stderr != "": + self.env["runtime"]["OutputManager"].present_text( + str(stderr), sound_icon="", interrupt=False + ) + if stdout != "": + self.env["runtime"]["OutputManager"].present_text( + str(stdout), sound_icon="", interrupt=False + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - str(e), sound_icon='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + str(e), sound_icon="", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/temp_disable_speech.py b/src/fenrirscreenreader/commands/commands/temp_disable_speech.py index 94653246..0dcb25b8 100644 --- a/src/fenrirscreenreader/commands/commands/temp_disable_speech.py +++ b/src/fenrirscreenreader/commands/commands/temp_disable_speech.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +19,10 @@ class command(): pass def get_description(self): - return _('disables speech until next keypress') + return _("disables speech until next keypress") def run(self): - self.env['runtime']['OutputManager'].temp_disable_speech() + self.env["runtime"]["OutputManager"].temp_disable_speech() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/time.py b/src/fenrirscreenreader/commands/commands/time.py index ee5f398d..698af3c8 100644 --- a/src/fenrirscreenreader/commands/commands/time.py +++ b/src/fenrirscreenreader/commands/commands/time.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the time') + return _("presents the time") def run(self): - time_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'time_format') + time_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "time_format" + ) # get the time formatted time_string = datetime.datetime.strftime( - datetime.datetime.now(), time_format) + datetime.datetime.now(), time_format + ) # present the time via speak and braile, there is no soundicon, # interrupt the current speech - self.env['runtime']['OutputManager'].present_text( - time_string, sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + time_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_indent.py b/src/fenrirscreenreader/commands/commands/toggle_auto_indent.py index 04c46cb6..f32d815e 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_auto_indent.py +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_indent.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,20 +18,30 @@ class command(): pass def get_description(self): - return _('enables or disables automatic reading of indentation level changes') + return _( + "enables or disables automatic reading of indentation level changes" + ) def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'general', 'autoPresentIndent', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoPresentIndent'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoPresentIndent'): - self.env['runtime']['OutputManager'].present_text( - _("autoindent enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "general", + "autoPresentIndent", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoPresentIndent" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoPresentIndent" + ): + self.env["runtime"]["OutputManager"].present_text( + _("autoindent enabled"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("autoindent disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("autoindent disabled"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_read.py b/src/fenrirscreenreader/commands/commands/toggle_auto_read.py index 042384ae..2b140199 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_auto_read.py +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_read.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,20 +18,30 @@ class command(): pass def get_description(self): - return _('enables or disables automatic reading of new text as it appears') + return _( + "enables or disables automatic reading of new text as it appears" + ) def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'autoReadIncoming', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'autoReadIncoming'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'autoReadIncoming'): - self.env['runtime']['OutputManager'].present_text( - _("autoread enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", + "autoReadIncoming", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "autoReadIncoming" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "autoReadIncoming" + ): + self.env["runtime"]["OutputManager"].present_text( + _("autoread enabled"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("autoread disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("autoread disabled"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py b/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py index eea34bb7..39a8bb2f 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,28 @@ class command(): pass def get_description(self): - return _('enables or disables automatic spell checking') + return _("enables or disables automatic spell checking") def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'general', 'autoSpellCheck', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoSpellCheck'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoSpellCheck'): - self.env['runtime']['OutputManager'].present_text( - _("auto spellcheck enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "general", + "autoSpellCheck", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoSpellCheck" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoSpellCheck" + ): + self.env["runtime"]["OutputManager"].present_text( + _("auto spellcheck enabled"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("auto spellcheck disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("auto spellcheck disabled"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_time.py b/src/fenrirscreenreader/commands/commands/toggle_auto_time.py index d87be58d..f2832470 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_auto_time.py +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_time.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,33 @@ class command(): def get_description(self): return _( - 'Enables or disables automatic reading of time after specified intervals') + "Enables or disables automatic reading of time after specified intervals" + ) def run(self): - self.env['runtime']['SettingsManager'].set_setting('time', 'enabled', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool('time', 'enabled'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _("Automatic time announcement enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "time", + "enabled", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "enabled" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("Automatic time announcement enabled"), + sound_icon="", + interrupt=True, + ) else: - self.env['runtime']['OutputManager'].present_text( - _("Automatic time announcement disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Automatic time announcement disabled"), + sound_icon="", + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_barrier.py b/src/fenrirscreenreader/commands/commands/toggle_barrier.py index ceef6c97..e72beea5 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_barrier.py +++ b/src/fenrirscreenreader/commands/commands/toggle_barrier.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,20 +18,28 @@ class command(): pass def get_description(self): - return _('enables or disables the barrier mode') + return _("enables or disables the barrier mode") def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'barrier', 'enabled', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _("barrier mode enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "barrier", + "enabled", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("barrier mode enabled"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("barrier mode disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("barrier mode disabled"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_emoticons.py b/src/fenrirscreenreader/commands/commands/toggle_emoticons.py index a4223ca8..b05c1340 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_emoticons.py +++ b/src/fenrirscreenreader/commands/commands/toggle_emoticons.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,20 +18,30 @@ class command(): pass def get_description(self): - return _('enables or disables announcement of emoticons instead of chars') + return _( + "enables or disables announcement of emoticons instead of chars" + ) def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'general', 'emoticons', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'emoticons'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'emoticons'): - self.env['runtime']['OutputManager'].present_text( - _('emoticons enabled'), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "general", + "emoticons", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "emoticons" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "emoticons" + ): + self.env["runtime"]["OutputManager"].present_text( + _("emoticons enabled"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('emoticons disabled'), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("emoticons disabled"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_has_attribute.py b/src/fenrirscreenreader/commands/commands/toggle_has_attribute.py index 04534e81..001c81c9 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_has_attribute.py +++ b/src/fenrirscreenreader/commands/commands/toggle_has_attribute.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,20 +18,32 @@ class command(): pass def get_description(self): - return _('enables or disables the announcement of attributes') + return _("enables or disables the announcement of attributes") def run(self): - self.env['runtime']['SettingsManager'].set_setting( - 'general', 'hasattributes', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'hasattributes'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'hasattributes'): - self.env['runtime']['OutputManager'].present_text( - _("announcement of attributes enabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "general", + "hasattributes", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "hasattributes" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "hasattributes" + ): + self.env["runtime"]["OutputManager"].present_text( + _("announcement of attributes enabled"), + sound_icon="", + interrupt=True, + ) else: - self.env['runtime']['OutputManager'].present_text( - _("announcement of attributes disabled"), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("announcement of attributes disabled"), + sound_icon="", + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py b/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py index f0cc2701..d7a1eeb3 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py +++ b/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,23 +18,29 @@ class command(): pass def get_description(self): - return _('enables or disables tracking of highlighted text') + return _("enables or disables tracking of highlighted text") def run(self): - curr_mode = self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'highlight') + curr_mode = self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "highlight" + ) - self.env['runtime']['SettingsManager'].set_setting( - 'focus', 'highlight', str(not curr_mode)) - self.env['runtime']['SettingsManager'].set_setting( - 'focus', 'cursor', str(curr_mode)) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'highlight'): - self.env['runtime']['OutputManager'].present_text( - _('highlight tracking'), sound_icon ='', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "focus", "highlight", str(not curr_mode) + ) + self.env["runtime"]["SettingsManager"].set_setting( + "focus", "cursor", str(curr_mode) + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "highlight" + ): + self.env["runtime"]["OutputManager"].present_text( + _("highlight tracking"), sound_icon="", interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('cursor tracking'), sound_icon ='', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("cursor tracking"), sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_output.py b/src/fenrirscreenreader/commands/commands/toggle_output.py index bd5237a1..86548336 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_output.py +++ b/src/fenrirscreenreader/commands/commands/toggle_output.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,27 +19,33 @@ class command(): pass def get_description(self): - return _('toggles all output settings') + return _("toggles all output settings") def run(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', - 'enabled') or self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', - 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _('Fenrir muted'), sound_icon ='Accept', interrupt=True) - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', 'False') - self.env['runtime']['SettingsManager'].set_setting( - 'sound', 'enabled', 'False') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ) or self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("Fenrir muted"), sound_icon="Accept", interrupt=True + ) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "enabled", "False" + ) + self.env["runtime"]["SettingsManager"].set_setting( + "sound", "enabled", "False" + ) else: - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', 'True') - self.env['runtime']['SettingsManager'].set_setting( - 'sound', 'enabled', 'True') - self.env['runtime']['OutputManager'].present_text( - _('Fenrir unmuted'), sound_icon ='Cancel', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "enabled", "True" + ) + self.env["runtime"]["SettingsManager"].set_setting( + "sound", "enabled", "True" + ) + self.env["runtime"]["OutputManager"].present_text( + _("Fenrir unmuted"), sound_icon="Cancel", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py b/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py index 970696c9..f419e453 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py +++ b/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,16 +19,23 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if self.env['runtime']['PunctuationManager'].cycle_punctuation(): - self.env['runtime']['OutputManager'].present_text( - self.env['runtime']['SettingsManager'].get_setting( - 'general', 'punctuationLevel'), interrupt=True, ignore_punctuation=True) + if self.env["runtime"]["PunctuationManager"].cycle_punctuation(): + self.env["runtime"]["OutputManager"].present_text( + self.env["runtime"]["SettingsManager"].get_setting( + "general", "punctuationLevel" + ), + interrupt=True, + ignore_punctuation=True, + ) else: - self.env['runtime']['OutputManager'].present_text( - _('No punctuation found.'), interrupt=True, ignore_punctuation=True) + self.env["runtime"]["OutputManager"].present_text( + _("No punctuation found."), + interrupt=True, + ignore_punctuation=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_sound.py b/src/fenrirscreenreader/commands/commands/toggle_sound.py index 71eb1352..e5ca2b82 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_sound.py +++ b/src/fenrirscreenreader/commands/commands/toggle_sound.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,21 +18,30 @@ class command(): pass def get_description(self): - return _('enables or disables sound') + return _("enables or disables sound") def run(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _('sound disabled'), sound_icon ='SoundOff', interrupt=True) - self.env['runtime']['SettingsManager'].set_setting( - 'sound', 'enabled', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _('sound enabled'), sound_icon ='SoundOn', interrupt=True) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("sound disabled"), sound_icon="SoundOff", interrupt=True + ) + self.env["runtime"]["SettingsManager"].set_setting( + "sound", + "enabled", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("sound enabled"), sound_icon="SoundOn", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_speech.py b/src/fenrirscreenreader/commands/commands/toggle_speech.py index 16aa98ae..8d2786cf 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_speech.py +++ b/src/fenrirscreenreader/commands/commands/toggle_speech.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,22 +19,31 @@ class command(): pass def get_description(self): - return _('enables or disables speech') + return _("enables or disables speech") def run(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'): - self.env['runtime']['OutputManager'].interrupt_output() - self.env['runtime']['OutputManager'].present_text( - _('speech disabled'), sound_icon ='SpeechOff', interrupt=True) - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'))) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'): - self.env['runtime']['OutputManager'].present_text( - _('speech enabled'), sound_icon ='SpeechOn', interrupt=True) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ): + self.env["runtime"]["OutputManager"].interrupt_output() + self.env["runtime"]["OutputManager"].present_text( + _("speech disabled"), sound_icon="SpeechOff", interrupt=True + ) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", + "enabled", + str( + not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ) + ), + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ): + self.env["runtime"]["OutputManager"].present_text( + _("speech enabled"), sound_icon="SpeechOn", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py b/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py index e57be4ec..2584a6f0 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py +++ b/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,16 +19,20 @@ class command(): pass def get_description(self): - self.env['runtime']['HelpManager'].toggle_tutorial_mode() + self.env["runtime"]["HelpManager"].toggle_tutorial_mode() return _( - 'Exiting tutorial mode. To enter tutorial mode again press Fenrir+f1') + "Exiting tutorial mode. To enter tutorial mode again press Fenrir+f1" + ) def run(self): - self.env['runtime']['HelpManager'].toggle_tutorial_mode() - if self.env['runtime']['HelpManager'].is_tutorial_mode(): - self.env['runtime']['OutputManager'].present_text( - _('Entering tutorial mode. In this mode commands are described but not executed. You can move through the list of commands with the up and down arrow keys. To Exit tutorial mode press Fenrir+f1.'), - interrupt=True) + self.env["runtime"]["HelpManager"].toggle_tutorial_mode() + if self.env["runtime"]["HelpManager"].is_tutorial_mode(): + self.env["runtime"]["OutputManager"].present_text( + _( + "Entering tutorial mode. In this mode commands are described but not executed. You can move through the list of commands with the up and down arrow keys. To Exit tutorial mode press Fenrir+f1." + ), + interrupt=True, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_vmenu_mode.py b/src/fenrirscreenreader/commands/commands/toggle_vmenu_mode.py index 6093efab..4560d54f 100644 --- a/src/fenrirscreenreader/commands/commands/toggle_vmenu_mode.py +++ b/src/fenrirscreenreader/commands/commands/toggle_vmenu_mode.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,19 @@ class command(): pass def get_description(self): - self.env['runtime']['VmenuManager'].toggle_vmenu_mode() - return _('Entering or Leaving v menu mode.') + self.env["runtime"]["VmenuManager"].toggle_vmenu_mode() + return _("Entering or Leaving v menu mode.") def run(self): - self.env['runtime']['VmenuManager'].toggle_vmenu_mode() - if self.env['runtime']['VmenuManager'].get_active(): - self.env['runtime']['OutputManager'].present_text( - _('Entering v menu.'), interrupt=True) + self.env["runtime"]["VmenuManager"].toggle_vmenu_mode() + if self.env["runtime"]["VmenuManager"].get_active(): + self.env["runtime"]["OutputManager"].present_text( + _("Entering v menu."), interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Leaving v menu.'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Leaving v menu."), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser.py b/src/fenrirscreenreader/commands/commands/voice_browser.py index fb387f8a..b12ed037 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -from fenrirscreenreader.core.i18n import _ - import subprocess import time +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -32,20 +32,23 @@ class command(): self.exit_voice_browser() return - self.env['runtime']['OutputManager'].present_text( - "Starting voice browser", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Starting voice browser", interrupt=True + ) # Load modules self.modules = self.get_speechd_modules() if not self.modules: - self.env['runtime']['OutputManager'].present_text( - "No speech modules found", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Error') + self.env["runtime"]["OutputManager"].present_text( + "No speech modules found", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Error") return # Set current module - current_module = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'module') + current_module = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "module" + ) if current_module and current_module in self.modules: self.module_index = self.modules.index(current_module) @@ -53,8 +56,9 @@ class command(): self.load_voices_for_current_module() # Set current voice - current_voice = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'voice') + current_voice = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "voice" + ) if current_voice and current_voice in self.voices: self.voice_index = self.voices.index(current_voice) @@ -67,39 +71,44 @@ class command(): self.browserActive = True # Store original bindings - self.originalBindings = self.env['bindings'].copy() + self.originalBindings = self.env["bindings"].copy() # Override navigation keys for voice browsing # Use lambda to capture self and create bound methods - self.env['bindings'][str([1, ['KEY_UP']])] = 'VOICE_BROWSER_PREV_VOICE' - self.env['bindings'][str([1, ['KEY_DOWN']]) - ] = 'VOICE_BROWSER_NEXT_VOICE' - self.env['bindings'][str([1, ['KEY_LEFT']]) - ] = 'VOICE_BROWSER_PREV_MODULE' - self.env['bindings'][str([1, ['KEY_RIGHT']]) - ] = 'VOICE_BROWSER_NEXT_MODULE' - self.env['bindings'][str([1, ['KEY_ENTER']])] = 'VOICE_BROWSER_TEST' - self.env['bindings'][str([1, ['KEY_SPACE']])] = 'VOICE_BROWSER_APPLY' - self.env['bindings'][str([1, ['KEY_ESC']])] = 'VOICE_BROWSER_EXIT' + self.env["bindings"][str([1, ["KEY_UP"]])] = "VOICE_BROWSER_PREV_VOICE" + self.env["bindings"][ + str([1, ["KEY_DOWN"]]) + ] = "VOICE_BROWSER_NEXT_VOICE" + self.env["bindings"][ + str([1, ["KEY_LEFT"]]) + ] = "VOICE_BROWSER_PREV_MODULE" + self.env["bindings"][ + str([1, ["KEY_RIGHT"]]) + ] = "VOICE_BROWSER_NEXT_MODULE" + self.env["bindings"][str([1, ["KEY_ENTER"]])] = "VOICE_BROWSER_TEST" + self.env["bindings"][str([1, ["KEY_SPACE"]])] = "VOICE_BROWSER_APPLY" + self.env["bindings"][str([1, ["KEY_ESC"]])] = "VOICE_BROWSER_EXIT" # Register browser commands self.register_browser_commands() - self.env['runtime']['OutputManager'].present_text( - "Voice browser active", interrupt=True) - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( + "Voice browser active", interrupt=True + ) + self.env["runtime"]["OutputManager"].present_text( "Up/Down=voices, Left/Right=modules, Enter=test, Space=apply, Esc=exit", - interrupt=True) + interrupt=True, + ) def register_browser_commands(self): """Register voice browser commands with the command manager""" # Create command objects for voice browser actions - CommandManager = self.env['runtime']['CommandManager'] + CommandManager = self.env["runtime"]["CommandManager"] # This is a hack - we'll store references to our methods in the environment # so the key handlers can call them - if 'voiceBrowserInstance' not in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'] = self + if "voiceBrowserInstance" not in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"] = self def exit_voice_browser(self): """Exit voice browser and restore normal key bindings""" @@ -109,14 +118,15 @@ class command(): self.browserActive = False # Restore original bindings - self.env['bindings'] = self.originalBindings + self.env["bindings"] = self.originalBindings # Clean up - if 'voiceBrowserInstance' in self.env['runtime']: - del self.env['runtime']['voiceBrowserInstance'] + if "voiceBrowserInstance" in self.env["runtime"]: + del self.env["runtime"]["voiceBrowserInstance"] - self.env['runtime']['OutputManager'].present_text( - "Voice browser exited", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Voice browser exited", interrupt=True + ) def load_voices_for_current_module(self): """Load voices for current module""" @@ -139,12 +149,14 @@ class command(): module = self.modules[self.module_index] if self.voices and self.voice_index < len(self.voices): voice = self.voices[self.voice_index] - self.env['runtime']['OutputManager'].present_text( - f"{module}: {voice} ({self.voice_index + 1}/{len(self.voices)})", interrupt=True + self.env["runtime"]["OutputManager"].present_text( + f"{module}: {voice} ({self.voice_index + 1}/{len(self.voices)})", + interrupt=True, ) else: - self.env['runtime']['OutputManager'].present_text( - f"{module}: No voices", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"{module}: No voices", interrupt=True + ) def next_voice(self): """Move to next voice""" @@ -175,22 +187,24 @@ class command(): def test_voice(self): """Test current voice""" if not self.voices or self.voice_index >= len(self.voices): - self.env['runtime']['OutputManager'].present_text( - "No voice selected", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "No voice selected", interrupt=True + ) return module = self.modules[self.module_index] voice = self.voices[self.voice_index] - self.env['runtime']['OutputManager'].present_text( - "Testing...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Testing...", interrupt=True + ) if self.preview_voice(module, voice): # Store for apply command - self.env['commandBuffer']['lastTestedModule'] = module - self.env['commandBuffer']['lastTestedVoice'] = voice - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["commandBuffer"]["lastTestedModule"] = module + self.env["commandBuffer"]["lastTestedVoice"] = voice + self.env["runtime"]["OutputManager"].play_sound("Accept") else: - self.env['runtime']['OutputManager'].play_sound('Error') + self.env["runtime"]["OutputManager"].play_sound("Error") def apply_voice(self): """Apply current voice to Fenrir""" @@ -201,29 +215,31 @@ class command(): voice = self.voices[self.voice_index] try: - SettingsManager = self.env['runtime']['SettingsManager'] - SettingsManager.settings['speech']['driver'] = 'speechdDriver' - SettingsManager.settings['speech']['module'] = module - SettingsManager.settings['speech']['voice'] = voice + SettingsManager = self.env["runtime"]["SettingsManager"] + SettingsManager.settings["speech"]["driver"] = "speechdDriver" + SettingsManager.settings["speech"]["module"] = module + SettingsManager.settings["speech"]["voice"] = voice - if 'SpeechDriver' in self.env['runtime']: - SpeechDriver = self.env['runtime']['SpeechDriver'] + if "SpeechDriver" in self.env["runtime"]: + SpeechDriver = self.env["runtime"]["SpeechDriver"] SpeechDriver.shutdown() SpeechDriver.initialize(self.env) - self.env['runtime']['OutputManager'].present_text( - "Voice applied!", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["runtime"]["OutputManager"].present_text( + "Voice applied!", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Accept") except Exception as e: - self.env['runtime']['OutputManager'].present_text( - "Apply failed", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Error') + self.env["runtime"]["OutputManager"].present_text( + "Apply failed", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Error") def preview_voice(self, module, voice): """Test voice with spd-say""" try: - cmd = ['spd-say', '-o', module, '-y', voice, self.testMessage] + cmd = ["spd-say", "-o", module, "-y", voice, self.testMessage] result = subprocess.run(cmd, timeout=10) return result.returncode == 0 except Exception: @@ -233,9 +249,10 @@ class command(): """Get available speech modules""" try: result = subprocess.run( - ['spd-say', '-O'], capture_output=True, text=True, timeout=10) + ["spd-say", "-O"], capture_output=True, text=True, timeout=10 + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") return [line.strip() for line in lines[1:] if line.strip()] except Exception: pass @@ -245,14 +262,18 @@ class command(): """Get voices for module""" try: result = subprocess.run( - ['spd-say', '-o', module, '-L'], capture_output=True, text=True, timeout=10) + ["spd-say", "-o", module, "-L"], + capture_output=True, + text=True, + timeout=10, + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") voices = [] for line in lines[1:]: if not line.strip(): continue - if module.lower() == 'espeak-ng': + if module.lower() == "espeak-ng": voice = self.process_espeak_voice(line) if voice: voices.append(voice) @@ -270,7 +291,11 @@ class command(): return None lang_code = parts[-2].lower() variant = parts[-1].lower() - return f"{lang_code}+{variant}" if variant and variant != 'none' else lang_code + return ( + f"{lang_code}+{variant}" + if variant and variant != "none" + else lang_code + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_apply.py b/src/fenrirscreenreader/commands/commands/voice_browser_apply.py index c4940ae4..e9dc13ce 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_apply.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_apply.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: apply current voice" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].apply_voice() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].apply_voice() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_exit.py b/src/fenrirscreenreader/commands/commands/voice_browser_exit.py index f351984f..5234b66e 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_exit.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_exit.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: exit browser mode" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].exit_voice_browser() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].exit_voice_browser() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_next_module.py b/src/fenrirscreenreader/commands/commands/voice_browser_next_module.py index 44551589..487ac7f6 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_next_module.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_next_module.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: next module" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].next_module() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].next_module() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_next_voice.py b/src/fenrirscreenreader/commands/commands/voice_browser_next_voice.py index 6fc8ca5c..97c3b0fa 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_next_voice.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_next_voice.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: next voice" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].next_voice() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].next_voice() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_prev_module.py b/src/fenrirscreenreader/commands/commands/voice_browser_prev_module.py index e8ab884f..491f955e 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_prev_module.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_prev_module.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: previous module" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].prev_module() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].prev_module() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_prev_voice.py b/src/fenrirscreenreader/commands/commands/voice_browser_prev_voice.py index 4372c1ad..058c397f 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_prev_voice.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_prev_voice.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: previous voice" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].prev_voice() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].prev_voice() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_safe.py b/src/fenrirscreenreader/commands/commands/voice_browser_safe.py index ccbb0386..934cf628 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_safe.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_safe.py @@ -1,19 +1,21 @@ #!/usr/bin/env python3 -from fenrirscreenreader.core.i18n import _ - import subprocess import threading import time +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass def initialize(self, environment): self.env = environment - self.testMessage = "Voice test: The quick brown fox jumps over the lazy dog." + self.testMessage = ( + "Voice test: The quick brown fox jumps over the lazy dog." + ) def shutdown(self): pass @@ -23,38 +25,47 @@ class command(): def run(self): try: - self.env['runtime']['OutputManager'].present_text( - "Starting safe voice browser", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Starting safe voice browser", interrupt=True + ) # Get modules with timeout protection modules = self.get_speechd_modules_with_timeout() if not modules: - self.env['runtime']['OutputManager'].present_text( - "No speech modules found", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "No speech modules found", interrupt=True + ) return # Get current position from commandBuffer or start fresh - module_index = self.env['commandBuffer'].get( - 'safeBrowserModuleIndex', 0) - voice_index = self.env['commandBuffer'].get( - 'safeBrowserVoiceIndex', 0) + module_index = self.env["commandBuffer"].get( + "safeBrowserModuleIndex", 0 + ) + voice_index = self.env["commandBuffer"].get( + "safeBrowserVoiceIndex", 0 + ) # Ensure valid module index if module_index >= len(modules): module_index = 0 current_module = modules[module_index] - self.env['runtime']['OutputManager'].present_text( - f"Loading voices for {current_module}...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Loading voices for {current_module}...", interrupt=True + ) # Get voices with timeout protection voices = self.get_module_voices_with_timeout(current_module) if not voices: - self.env['runtime']['OutputManager'].present_text( - f"No voices in {current_module}, trying next module", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"No voices in {current_module}, trying next module", + interrupt=True, + ) module_index = (module_index + 1) % len(modules) - self.env['commandBuffer']['safeBrowserModuleIndex'] = module_index - self.env['commandBuffer']['safeBrowserVoiceIndex'] = 0 + self.env["commandBuffer"][ + "safeBrowserModuleIndex" + ] = module_index + self.env["commandBuffer"]["safeBrowserVoiceIndex"] = 0 return # Ensure valid voice index @@ -64,27 +75,31 @@ class command(): current_voice = voices[voice_index] # Announce current selection - self.env['runtime']['OutputManager'].present_text( - f"Module: {current_module} ({module_index + 1}/{len(modules)})", interrupt=True + self.env["runtime"]["OutputManager"].present_text( + f"Module: {current_module} ({module_index + 1}/{len(modules)})", + interrupt=True, ) - self.env['runtime']['OutputManager'].present_text( - f"Voice: {current_voice} ({voice_index + 1}/{len(voices)})", interrupt=True + self.env["runtime"]["OutputManager"].present_text( + f"Voice: {current_voice} ({voice_index + 1}/{len(voices)})", + interrupt=True, ) # Test voice in background thread to avoid blocking - self.env['runtime']['OutputManager'].present_text( - "Testing voice...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Testing voice...", interrupt=True + ) # Use threading to prevent freezing test_thread = threading.Thread( - target=self.test_voice_async, args=( - current_module, current_voice)) + target=self.test_voice_async, + args=(current_module, current_voice), + ) test_thread.daemon = True test_thread.start() # Store tested voice for apply command - self.env['commandBuffer']['lastTestedModule'] = current_module - self.env['commandBuffer']['lastTestedVoice'] = current_voice + self.env["commandBuffer"]["lastTestedModule"] = current_module + self.env["commandBuffer"]["lastTestedVoice"] = current_voice # Advance to next voice for next run voice_index += 1 @@ -93,23 +108,26 @@ class command(): module_index = (module_index + 1) % len(modules) # Store position for next run - self.env['commandBuffer']['safeBrowserModuleIndex'] = module_index - self.env['commandBuffer']['safeBrowserVoiceIndex'] = voice_index + self.env["commandBuffer"]["safeBrowserModuleIndex"] = module_index + self.env["commandBuffer"]["safeBrowserVoiceIndex"] = voice_index # Give instructions - self.env['runtime']['OutputManager'].present_text( - "Run again for next voice, or use apply voice command", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Run again for next voice, or use apply voice command", + interrupt=True, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Voice browser error: {str(e)}", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Error') + self.env["runtime"]["OutputManager"].present_text( + f"Voice browser error: {str(e)}", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Error") def test_voice_async(self, module, voice): """Test voice in background thread to avoid blocking""" try: # Run with strict timeout - cmd = ['spd-say', '-o', module, '-y', voice, self.testMessage] + cmd = ["spd-say", "-o", module, "-y", voice, self.testMessage] result = subprocess.run(cmd, timeout=5, capture_output=True) # Schedule success sound for main thread @@ -129,32 +147,39 @@ class command(): """Get speech modules with timeout protection""" try: result = subprocess.run( - ['spd-say', '-O'], capture_output=True, text=True, timeout=3) + ["spd-say", "-O"], capture_output=True, text=True, timeout=3 + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") modules = [line.strip() for line in lines[1:] if line.strip()] # Limit to first 10 modules to prevent overload return modules[:10] except subprocess.TimeoutExpired: - self.env['runtime']['OutputManager'].present_text( - "Module detection timed out", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Module detection timed out", interrupt=True + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Module detection failed: {str(e)}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Module detection failed: {str(e)}", interrupt=True + ) return [] def get_module_voices_with_timeout(self, module): """Get voices with timeout and limits""" try: result = subprocess.run( - ['spd-say', '-o', module, '-L'], capture_output=True, text=True, timeout=5) + ["spd-say", "-o", module, "-L"], + capture_output=True, + text=True, + timeout=5, + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") voices = [] for line in lines[1:]: if not line.strip(): continue - if module.lower() == 'espeak-ng': + if module.lower() == "espeak-ng": voice = self.process_espeak_voice(line) if voice: voices.append(voice) @@ -163,17 +188,21 @@ class command(): # Limit voice count to prevent memory issues if len(voices) > 1000: - self.env['runtime']['OutputManager'].present_text( - f"found {len(voices)} voices, limiting to first 1000", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"found {len(voices)} voices, limiting to first 1000", + interrupt=True, + ) voices = voices[:1000] return voices except subprocess.TimeoutExpired: - self.env['runtime']['OutputManager'].present_text( - f"Voice detection for {module} timed out", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Voice detection for {module} timed out", interrupt=True + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Voice detection failed: {str(e)}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Voice detection failed: {str(e)}", interrupt=True + ) return [] def process_espeak_voice(self, voiceLine): @@ -184,7 +213,11 @@ class command(): return None lang_code = parts[-2].lower() variant = parts[-1].lower() - return f"{lang_code}+{variant}" if variant and variant != 'none' else lang_code + return ( + f"{lang_code}+{variant}" + if variant and variant != "none" + else lang_code + ) except Exception: return None diff --git a/src/fenrirscreenreader/commands/commands/voice_browser_test.py b/src/fenrirscreenreader/commands/commands/voice_browser_test.py index 25fd0beb..d08bc024 100644 --- a/src/fenrirscreenreader/commands/commands/voice_browser_test.py +++ b/src/fenrirscreenreader/commands/commands/voice_browser_test.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,8 +17,8 @@ class command(): return "Voice browser: test current voice" def run(self): - if 'voiceBrowserInstance' in self.env['runtime']: - self.env['runtime']['voiceBrowserInstance'].test_voice() + if "voiceBrowserInstance" in self.env["runtime"]: + self.env["runtime"]["voiceBrowserInstance"].test_voice() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/help/curr_help.py b/src/fenrirscreenreader/commands/help/curr_help.py index dbf734bd..b7123c9e 100644 --- a/src/fenrirscreenreader/commands/help/curr_help.py +++ b/src/fenrirscreenreader/commands/help/curr_help.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,11 +18,11 @@ class command(): pass def get_description(self): - return _('get current help message') + return _("get current help message") def run(self): - text = self.env['runtime']['HelpManager'].get_help_for_current_index() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + text = self.env["runtime"]["HelpManager"].get_help_for_current_index() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/help/next_help.py b/src/fenrirscreenreader/commands/help/next_help.py index 94e21295..bde46aab 100644 --- a/src/fenrirscreenreader/commands/help/next_help.py +++ b/src/fenrirscreenreader/commands/help/next_help.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,12 +18,12 @@ class command(): pass def get_description(self): - return _('get next help message') + return _("get next help message") def run(self): - self.env['runtime']['HelpManager'].next_index() - text = self.env['runtime']['HelpManager'].get_help_for_current_index() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["HelpManager"].next_index() + text = self.env["runtime"]["HelpManager"].get_help_for_current_index() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/help/prev_help.py b/src/fenrirscreenreader/commands/help/prev_help.py index c33e14ac..61eb614a 100644 --- a/src/fenrirscreenreader/commands/help/prev_help.py +++ b/src/fenrirscreenreader/commands/help/prev_help.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,12 +18,12 @@ class command(): pass def get_description(self): - return _('get prev help message') + return _("get prev help message") def run(self): - self.env['runtime']['HelpManager'].prev_index() - text = self.env['runtime']['HelpManager'].get_help_for_current_index() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["HelpManager"].prev_index() + text = self.env["runtime"]["HelpManager"].get_help_for_current_index() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onByteInput/10000-shut_up.py b/src/fenrirscreenreader/commands/onByteInput/10000-shut_up.py index f8971eeb..0a233a33 100644 --- a/src/fenrirscreenreader/commands/onByteInput/10000-shut_up.py +++ b/src/fenrirscreenreader/commands/onByteInput/10000-shut_up.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,29 +19,37 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'interruptOnKeyPress'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "interruptOnKeyPress" + ): return - if self.env['runtime']['InputManager'].no_key_pressed(): + if self.env["runtime"]["InputManager"].no_key_pressed(): return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): return - if len( - self.env['input']['currInput']) <= len( - self.env['input']['prevInput']): + if len(self.env["input"]["currInput"]) <= len( + self.env["input"]["prevInput"] + ): return # if the filter is set - if self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'interruptOnKeyPressFilter').strip() != '': - filter_list = self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'interruptOnKeyPressFilter').split(',') - for currInput in self.env['input']['currInput']: + if ( + self.env["runtime"]["SettingsManager"] + .get_setting("keyboard", "interruptOnKeyPressFilter") + .strip() + != "" + ): + filter_list = ( + self.env["runtime"]["SettingsManager"] + .get_setting("keyboard", "interruptOnKeyPressFilter") + .split(",") + ) + for currInput in self.env["input"]["currInput"]: if currInput not in filter_list: return - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py b/src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py index 3bd28d11..697c4f90 100644 --- a/src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py +++ b/src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,23 @@ class command(): pass def get_description(self): - return _('disables speech until next keypress') + return _("disables speech until next keypress") def run(self): - if not self.env['commandBuffer']['enableSpeechOnKeypress']: + if not self.env["commandBuffer"]["enableSpeechOnKeypress"]: return - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', str( - self.env['commandBuffer']['enableSpeechOnKeypress'])) - self.env['commandBuffer']['enableSpeechOnKeypress'] = False + self.env["runtime"]["SettingsManager"].set_setting( + "speech", + "enabled", + str(self.env["commandBuffer"]["enableSpeechOnKeypress"]), + ) + self.env["commandBuffer"]["enableSpeechOnKeypress"] = False # Also disable prompt watching since speech was manually re-enabled - if 'silenceUntilPrompt' in self.env['commandBuffer']: - self.env['commandBuffer']['silenceUntilPrompt'] = False - self.env['runtime']['OutputManager'].present_text( - _("speech enabled"), sound_icon ='SpeechOn', interrupt=True) + if "silenceUntilPrompt" in self.env["commandBuffer"]: + self.env["commandBuffer"]["silenceUntilPrompt"] = False + self.env["runtime"]["OutputManager"].present_text( + _("speech enabled"), sound_icon="SpeechOn", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/15000-char_echo.py b/src/fenrirscreenreader/commands/onCursorChange/15000-char_echo.py index bd897e34..ba7c6ca2 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/15000-char_echo.py +++ b/src/fenrirscreenreader/commands/onCursorChange/15000-char_echo.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,52 +19,65 @@ class command(): pass def get_description(self): - return 'No Description found' + return _("Announces characters as they are typed") def run(self): # enabled? - active = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'keyboard', 'charEchoMode') + active = self.env["runtime"]["SettingsManager"].get_setting_as_int( + "keyboard", "charEchoMode" + ) # 0 = off if active == 0: return # 2 = caps only if active == 2: - if not self.env['input']['newCapsLock']: + if not self.env["input"]["newCapsLock"]: return # big changes are no char (but the value is bigger than one maybe the # differ needs longer than you can type, so a little strange random # buffer for now) x_move = abs( - self.env['screen']['new_cursor']['x'] - - self.env['screen']['old_cursor']['x']) + self.env["screen"]["new_cursor"]["x"] + - self.env["screen"]["old_cursor"]["x"] + ) if x_move > 3: return - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: - if self.env['runtime']['InputManager'].get_last_deepest_input() in [ - ['KEY_TAB']]: + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: + if self.env["runtime"][ + "InputManager" + ].get_last_deepest_input() in [["KEY_TAB"]]: return - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: - if self.env['runtime']['ByteManager'].get_last_byte_key() in [ - b' ', b'\t']: + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: + if self.env["runtime"]["ByteManager"].get_last_byte_key() in [ + b" ", + b"\t", + ]: return # detect deletion or chilling - if self.env['screen']['new_cursor']['x'] <= self.env['screen']['old_cursor']['x']: + if ( + self.env["screen"]["new_cursor"]["x"] + <= self.env["screen"]["old_cursor"]["x"] + ): return # is there any change? - if not self.env['runtime']['ScreenManager'].is_delta(): + if not self.env["runtime"]["ScreenManager"].is_delta(): return # filter unneded space on word begin - curr_delta = self.env['screen']['new_delta'] - if len(curr_delta.strip()) != len(curr_delta) and \ - curr_delta.strip() != '': + curr_delta = self.env["screen"]["new_delta"] + if ( + len(curr_delta.strip()) != len(curr_delta) + and curr_delta.strip() != "" + ): curr_delta = curr_delta.strip() - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( curr_delta, interrupt=True, ignore_punctuation=True, announce_capital=True, - flush=False) + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/25000-word_echo_type.py b/src/fenrirscreenreader/commands/onCursorChange/25000-word_echo_type.py index ace1e51d..bf14391d 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/25000-word_echo_type.py +++ b/src/fenrirscreenreader/commands/onCursorChange/25000-word_echo_type.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils import string +from fenrirscreenreader.core.i18n import _ +from fenrirscreenreader.utils import word_utils -class command(): + +class command: def __init__(self): pass @@ -21,48 +21,61 @@ class command(): pass def get_description(self): - return 'No Description found' + return _("Announces completed words during typing") def run(self): # is it enabled? - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'wordEcho'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "wordEcho" + ): return - # is naviation? - if self.env['screen']['new_cursor']['x'] - \ - self.env['screen']['old_cursor']['x'] != 1: + # is navigation? + if ( + self.env["screen"]["new_cursor"]["x"] + - self.env["screen"]["old_cursor"]["x"] + != 1 + ): return # just when cursor move worddetection is needed - if not self.env['runtime']['CursorManager'].is_cursor_horizontal_move(): + if not self.env["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move(): return # for now no new line - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return # currently writing - if self.env['runtime']['ScreenManager'].is_delta(): + if self.env["runtime"]["ScreenManager"].is_delta(): return # get the word - new_content = self.env['screen']['new_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] - x, y, curr_word, end_of_screen, line_break = word_utils.get_current_word( - self.env['screen']['new_cursor']['x'], 0, new_content) + new_content = self.env["screen"]["new_content_text"].split("\n")[ + self.env["screen"]["new_cursor"]["y"] + ] + x, y, curr_word, end_of_screen, line_break = ( + word_utils.get_current_word( + self.env["screen"]["new_cursor"]["x"], 0, new_content + ) + ) # is there a word? - if curr_word == '': + if curr_word == "": return # at the end of a word - if not new_content[self.env['screen']['new_cursor']['x']].isspace(): + if ( + self.env["screen"]["new_cursor"]["x"] >= len(new_content) + or not new_content[self.env["screen"]["new_cursor"]["x"]].isspace() + ): return # at the end of a word - if (x + - len(curr_word) != self.env['screen']['new_cursor']['x']) and (x + - len(curr_word) != self.env['screen']['new_cursor']['x'] - - 1): + if (x + len(curr_word) != self.env["screen"]["new_cursor"]["x"]) and ( + x + len(curr_word) != self.env["screen"]["new_cursor"]["x"] - 1 + ): return - self.env['runtime']['OutputManager'].present_text( - curr_word, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + curr_word, interrupt=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/35000-spell_check.py b/src/fenrirscreenreader/commands/onCursorChange/35000-spell_check.py index d79e33b2..26e464f7 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/35000-spell_check.py +++ b/src/fenrirscreenreader/commands/onCursorChange/35000-spell_check.py @@ -2,26 +2,27 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils import os import string +from fenrirscreenreader.core.i18n import _ +from fenrirscreenreader.utils import word_utils + initialized = False try: import enchant + initialized = True except Exception as e: pass -class command(): +class command: def __init__(self): - self.language = '' - self.spellChecker = '' + self.language = "" + self.spellChecker = "" def initialize(self, environment): self.env = environment @@ -31,118 +32,144 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def update_spell_language(self): if not initialized: return self.spellChecker = enchant.Dict( - self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage')) - self.language = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') + self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) + ) + self.language = self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) def run(self): if not initialized: return - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoSpellCheck'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoSpellCheck" + ): return - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'spellCheckLanguage') != self.language: + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "general", "spellCheckLanguage" + ) + != self.language + ): try: self.update_spell_language() except Exception as e: return # just when horizontal cursor move worddetection is needed - if not self.env['runtime']['CursorManager'].is_cursor_horizontal_move(): + if not self.env["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move(): return # for now no new line - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return # more than a keyecho? - if len(self.env['screen']['new_delta']) > 1: + if len(self.env["screen"]["new_delta"]) > 1: return # deletion - if self.env['runtime']['ScreenManager'].is_negative_delta(): + if self.env["runtime"]["ScreenManager"].is_negative_delta(): return # first place could not be the end of a word - if self.env['screen']['new_cursor']['x'] == 0: + if self.env["screen"]["new_cursor"]["x"] == 0: return # get the word (just for speedup only look at current line - new_content = self.env['screen']['new_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] - x, y, curr_word, end_of_screen, line_break = word_utils.get_current_word( - self.env['screen']['new_cursor']['x'], 0, new_content) + new_content = self.env["screen"]["new_content_text"].split("\n")[ + self.env["screen"]["new_cursor"]["y"] + ] + x, y, curr_word, end_of_screen, line_break = ( + word_utils.get_current_word( + self.env["screen"]["new_cursor"]["x"], 0, new_content + ) + ) # was this a typed word? - if self.env['runtime']['ScreenManager'].is_delta(): - if not (new_content[self.env['screen']['old_cursor']['x']] in string.whitespace + - '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' and x != self.env['screen']['old_cursor']['x']): + if self.env["runtime"]["ScreenManager"].is_delta(): + if not ( + new_content[self.env["screen"]["old_cursor"]["x"]] + in string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' + and x != self.env["screen"]["old_cursor"]["x"] + ): return else: curr_word = curr_word.strip( - string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~') + string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' + ) else: # or just arrow arround? - if not new_content[self.env['screen']['new_cursor']['x']].isspace(): + if not new_content[ + self.env["screen"]["new_cursor"]["x"] + ].isspace(): return - if (x + - len(curr_word) != self.env['screen']['new_cursor']['x']) and (x + - len(curr_word) != self.env['screen']['new_cursor']['x'] - - 1): + if ( + x + len(curr_word) != self.env["screen"]["new_cursor"]["x"] + ) and ( + x + len(curr_word) != self.env["screen"]["new_cursor"]["x"] - 1 + ): return # just on end of word - if self.env['screen']['new_cursor']['x'] > 0: - if not new_content[self.env['screen']['old_cursor'] - ['x'] - 1].lower() in string.ascii_lowercase: + if self.env["screen"]["new_cursor"]["x"] > 0: + if ( + not new_content[ + self.env["screen"]["old_cursor"]["x"] - 1 + ].lower() + in string.ascii_lowercase + ): return # ignore bash buildins if curr_word in [ - 'cd', - 'fg', - 'bg', - 'alias', - 'bind', - 'dir', - 'caller', - 'buildin', - 'command', - 'declare', - 'echo', - 'enable', - 'help', - 'let', - 'local', - 'logout', - 'mapfile', - 'printf', - 'read', - 'readarray', - 'source', - 'type', - 'typeset', - 'ulimit', - 'unalias']: + "cd", + "fg", + "bg", + "alias", + "bind", + "dir", + "caller", + "buildin", + "command", + "declare", + "echo", + "enable", + "help", + "let", + "local", + "logout", + "mapfile", + "printf", + "read", + "readarray", + "source", + "type", + "typeset", + "ulimit", + "unalias", + ]: return # ignore the application name - if curr_word.upper() == 'FENRIR': + if curr_word.upper() == "FENRIR": return - if curr_word[0] == '-': + if curr_word[0] == "-": return - if curr_word[0] == '/': + if curr_word[0] == "/": return - if curr_word[0] == '#': + if curr_word[0] == "#": return - if curr_word.startswith('./'): + if curr_word.startswith("./"): return - if '@' in curr_word and '.' in curr_word: + if "@" in curr_word and "." in curr_word: return - if curr_word[0] == '@': + if curr_word[0] == "@": return if curr_word.isnumeric(): return @@ -168,8 +195,12 @@ class command(): pass if not self.spellChecker.check(curr_word): - self.env['runtime']['OutputManager'].present_text( - _('misspelled'), sound_icon ='mispell', interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("misspelled"), + sound_icon="mispell", + interrupt=False, + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/45000-char_delete_echo.py b/src/fenrirscreenreader/commands/onCursorChange/45000-char_delete_echo.py index 425ff85b..aedf398e 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/45000-char_delete_echo.py +++ b/src/fenrirscreenreader/commands/onCursorChange/45000-char_delete_echo.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,39 +19,46 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'charDeleteEcho'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "charDeleteEcho" + ): return # detect typing or chilling - if self.env['screen']['new_cursor']['x'] >= self.env['screen']['old_cursor']['x']: + if ( + self.env["screen"]["new_cursor"]["x"] + >= self.env["screen"]["old_cursor"]["x"] + ): return # More than just a deletion happend - if self.env['runtime']['ScreenManager'].is_delta(ignoreSpace=True): + if self.env["runtime"]["ScreenManager"].is_delta(ignoreSpace=True): return # no deletion - if not self.env['runtime']['ScreenManager'].is_negative_delta(): + if not self.env["runtime"]["ScreenManager"].is_negative_delta(): return # too much for a single backspace... # word begin produce a diff wiht len == 2 |a | others with 1 |a| - if len(self.env['screen']['newNegativeDelta']) > 2: + if len(self.env["screen"]["newNegativeDelta"]) > 2: return - curr_negative_delta = self.env['screen']['newNegativeDelta'] - if len(curr_negative_delta.strip()) != len(curr_negative_delta) and \ - curr_negative_delta.strip() != '': + curr_negative_delta = self.env["screen"]["newNegativeDelta"] + if ( + len(curr_negative_delta.strip()) != len(curr_negative_delta) + and curr_negative_delta.strip() != "" + ): curr_negative_delta = curr_negative_delta.strip() - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( curr_negative_delta, interrupt=True, ignore_punctuation=True, announce_capital=True, - flush=False) + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py b/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py index e62bd65a..66619ce9 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py +++ b/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import char_utils from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): pass @@ -21,55 +20,85 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'cursor'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "cursor" + ): return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): return # detect an change on the screen, we just want to cursor arround, so no # change should appear - if self.env['runtime']['ScreenManager'].is_delta(): + if self.env["runtime"]["ScreenManager"].is_delta(): return - if self.env['runtime']['ScreenManager'].is_negative_delta(): + if self.env["runtime"]["ScreenManager"].is_negative_delta(): return # is a vertical change? - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return # is it a horizontal change? - if not self.env['runtime']['CursorManager'].is_cursor_horizontal_move(): + if not self.env["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move(): return # echo word insteed of char - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'wordEcho'): - if abs(self.env['screen']['old_cursor']['x'] - - self.env['screen']['new_cursor']['x']) != 1: + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "wordEcho" + ): + if ( + abs( + self.env["screen"]["old_cursor"]["x"] + - self.env["screen"]["new_cursor"]["x"] + ) + != 1 + ): # get the word - new_content = self.env['screen']['new_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] - x, y, curr_word, end_of_screen, line_break = word_utils.get_current_word( - self.env['screen']['new_cursor']['x'], 0, new_content) - if self.env['screen']['new_cursor']['x'] == x: + new_content = self.env["screen"]["new_content_text"].split( + "\n" + )[self.env["screen"]["new_cursor"]["y"]] + x, y, curr_word, end_of_screen, line_break = ( + word_utils.get_current_word( + self.env["screen"]["new_cursor"]["x"], 0, new_content + ) + ) + if self.env["screen"]["new_cursor"]["x"] == x: return x, y, curr_char = char_utils.get_current_char( - self.env['screen']['new_cursor']['x'], self.env['screen']['new_cursor']['y'], self.env['screen']['new_content_text']) + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + self.env["screen"]["new_content_text"], + ) if curr_char.isspace(): # Only announce spaces during pure navigation (arrow keys) # Check if this is really navigation by looking at input history - if (self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY'] and self.env['runtime'][ - 'InputManager'].get_last_deepest_input()[0] in ['KEY_LEFT', 'KEY_RIGHT', 'KEY_UP', 'KEY_DOWN']): + if self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "KEY" + ] and self.env["runtime"]["InputManager"].get_last_deepest_input()[ + 0 + ] in [ + "KEY_LEFT", + "KEY_RIGHT", + "KEY_UP", + "KEY_DOWN", + ]: char_utils.present_char_for_review( - self.env, curr_char, interrupt=True, announce_capital=True, flush=False) + self.env, + curr_char, + interrupt=True, + announce_capital=True, + flush=False, + ) else: - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( curr_char, interrupt=True, ignore_punctuation=True, announce_capital=True, - flush=False) + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/55000-tab_completion.py b/src/fenrirscreenreader/commands/onCursorChange/55000-tab_completion.py index d8996f4b..1dc95fc0 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/55000-tab_completion.py +++ b/src/fenrirscreenreader/commands/onCursorChange/55000-tab_completion.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,41 +19,50 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): # try to detect the tab completion by cursor change - x_move = self.env['screen']['new_cursor']['x'] - \ - self.env['screen']['old_cursor']['x'] + x_move = ( + self.env["screen"]["new_cursor"]["x"] + - self.env["screen"]["old_cursor"]["x"] + ) if x_move <= 0: return - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: if not ( - self.env['runtime']['InputManager'].get_last_deepest_input() in [ - ['KEY_TAB']]): + self.env["runtime"]["InputManager"].get_last_deepest_input() + in [["KEY_TAB"]] + ): if x_move < 5: return - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: found = False - for currByte in self.env['runtime']['ByteManager'].get_last_byte_key( - ): + for currByte in self.env["runtime"][ + "ByteManager" + ].get_last_byte_key(): if currByte == 9: found = True if not found: if x_move < 5: return # is there any change? - if not self.env['runtime']['ScreenManager'].is_delta(): + if not self.env["runtime"]["ScreenManager"].is_delta(): return - if not x_move == len(self.env['screen']['new_delta']): + if not x_move == len(self.env["screen"]["new_delta"]): return # filter unneded space on word begin - curr_delta = self.env['screen']['new_delta'] - if len(curr_delta.strip()) != len(curr_delta) and \ - curr_delta.strip() != '': + curr_delta = self.env["screen"]["new_delta"] + if ( + len(curr_delta.strip()) != len(curr_delta) + and curr_delta.strip() != "" + ): curr_delta = curr_delta.strip() - self.env['runtime']['OutputManager'].present_text( - curr_delta, interrupt=True, announce_capital=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + curr_delta, interrupt=True, announce_capital=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_navigation.py b/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_navigation.py index 3a23b24d..32c8d4ec 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_navigation.py +++ b/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_navigation.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core.i18n import _ - -from fenrirscreenreader.utils import word_utils import string +from fenrirscreenreader.core.i18n import _ +from fenrirscreenreader.utils import word_utils -class command(): + +class command: def __init__(self): pass @@ -21,41 +21,54 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): # is navigation? - if not abs(self.env['screen']['old_cursor']['x'] - - self.env['screen']['new_cursor']['x']) > 1: + if ( + not abs( + self.env["screen"]["old_cursor"]["x"] + - self.env["screen"]["new_cursor"]["x"] + ) + > 1 + ): return # just when cursor move worddetection is needed - if not self.env['runtime']['CursorManager'].is_cursor_horizontal_move(): + if not self.env["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move(): return # for now no new line - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return # currently writing - if self.env['runtime']['ScreenManager'].is_delta(): + if self.env["runtime"]["ScreenManager"].is_delta(): return # get the word - new_content = self.env['screen']['new_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] - x, y, curr_word, end_of_screen, line_break = word_utils.get_current_word( - self.env['screen']['new_cursor']['x'], 0, new_content) + new_content = self.env["screen"]["new_content_text"].split("\n")[ + self.env["screen"]["new_cursor"]["y"] + ] + x, y, curr_word, end_of_screen, line_break = ( + word_utils.get_current_word( + self.env["screen"]["new_cursor"]["x"], 0, new_content + ) + ) # is there a word? - if curr_word == '': + if curr_word == "": return # at the start of a word - if (x + len(curr_word) != self.env['screen']['new_cursor']['x']) and \ - (self.env['screen']['new_cursor']['x'] != x): + if (x + len(curr_word) != self.env["screen"]["new_cursor"]["x"]) and ( + self.env["screen"]["new_cursor"]["x"] != x + ): return - self.env['runtime']['OutputManager'].present_text( - curr_word, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + curr_word, interrupt=True, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/65000-present_line_if_cursor_change_vertical.py b/src/fenrirscreenreader/commands/onCursorChange/65000-present_line_if_cursor_change_vertical.py index 53e67342..28f9d7ab 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/65000-present_line_if_cursor_change_vertical.py +++ b/src/fenrirscreenreader/commands/onCursorChange/65000-present_line_if_cursor_change_vertical.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): self.lastIdent = -1 @@ -21,58 +20,77 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'cursor'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "cursor" + ): return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): self.lastIdent = 0 return # this leads to problems in vim -> status line change -> no # announcement, so we do check the lengh as hack - if self.env['runtime']['ScreenManager'].is_delta(): + if self.env["runtime"]["ScreenManager"].is_delta(): return # is a vertical change? - if not self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if not self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return x, y, curr_line = line_utils.get_current_line( - self.env['screen']['new_cursor']['x'], self.env['screen']['new_cursor']['y'], self.env['screen']['new_content_text']) + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["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["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True, flush=False + ) else: # ident curr_ident = len(curr_line) - len(curr_line.lstrip()) if self.lastIdent == -1: self.lastIdent = curr_ident do_interrupt = True - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoPresentIndent'): - if self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'autoPresentIndentMode') in [0, 1]: - self.env['runtime']['OutputManager'].play_frequence( - curr_ident * 50, 0.1, interrupt=do_interrupt) - if self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'autoPresentIndentMode') in [0, 2]: + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoPresentIndent" + ): + if self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "autoPresentIndentMode" + ) in [0, 1]: + self.env["runtime"]["OutputManager"].play_frequence( + curr_ident * 50, 0.1, interrupt=do_interrupt + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "autoPresentIndentMode" + ) in [0, 2]: if self.lastIdent != curr_ident: - self.env['runtime']['OutputManager'].present_text( - _('indented ') + str(curr_ident) + ' ', interrupt=do_interrupt, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("indented ") + str(curr_ident) + " ", + interrupt=do_interrupt, + flush=False, + ) do_interrupt = False # barrier say_line = curr_line - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'): - is_barrier, barrierLine = self.env['runtime']['BarrierManager'].handle_line_barrier( - self.env['screen']['new_content_text'].split('\n'), self.env['screen']['new_cursor']['x'], self.env['screen']['new_cursor']['y']) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ): + is_barrier, barrierLine = self.env["runtime"][ + "BarrierManager" + ].handle_line_barrier( + self.env["screen"]["new_content_text"].split("\n"), + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + ) if is_barrier: say_line = barrierLine # output - self.env['runtime']['OutputManager'].present_text( - say_line, interrupt=do_interrupt, flush=False) + self.env["runtime"]["OutputManager"].present_text( + say_line, interrupt=do_interrupt, flush=False + ) self.lastIdent = curr_ident def set_callback(self, callback): diff --git a/src/fenrirscreenreader/commands/onCursorChange/68000-auto_identation_horizontal.py b/src/fenrirscreenreader/commands/onCursorChange/68000-auto_identation_horizontal.py index 8b6cfa77..1392562c 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/68000-auto_identation_horizontal.py +++ b/src/fenrirscreenreader/commands/onCursorChange/68000-auto_identation_horizontal.py @@ -2,15 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import line_utils from fenrirscreenreader.utils import word_utils -class command(): +class command: def __init__(self): self.lastIdent = -1 @@ -21,27 +20,36 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'cursor'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "cursor" + ): return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): self.lastIdent = 0 return # is a vertical change? - if not self.env['runtime']['CursorManager'].is_cursor_horizontal_move(): + if not self.env["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move(): return x, y, curr_line = line_utils.get_current_line( - self.env['screen']['new_cursor']['x'], self.env['screen']['new_cursor']['y'], self.env['screen']['new_content_text']) - curr_ident = self.env['screen']['new_cursor']['x'] + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + self.env["screen"]["new_content_text"], + ) + curr_ident = self.env["screen"]["new_cursor"]["x"] if not curr_line.isspace(): # ident lastIdent, lastY, last_line = line_utils.get_current_line( - self.env['screen']['new_cursor']['x'], self.env['screen']['new_cursor']['y'], self.env['screen']['old_content_text']) + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + self.env["screen"]["old_content_text"], + ) if curr_line.strip() != last_line.strip(): return if len(curr_line.lstrip()) == len(last_line.lstrip()): @@ -53,17 +61,24 @@ class command(): self.lastIdent = curr_ident if curr_ident <= 0: return - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'autoPresentIndent'): - if self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'autoPresentIndentMode') in [0, 1]: - self.env['runtime']['OutputManager'].play_frequence( - curr_ident * 50, 0.1, interrupt=False) - if self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'autoPresentIndentMode') in [0, 2]: + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "autoPresentIndent" + ): + if self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "autoPresentIndentMode" + ) in [0, 1]: + self.env["runtime"]["OutputManager"].play_frequence( + curr_ident * 50, 0.1, interrupt=False + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "autoPresentIndentMode" + ) in [0, 2]: if self.lastIdent != curr_ident: - self.env['runtime']['OutputManager'].present_text( - _('indented ') + str(curr_ident) + ' ', interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("indented ") + str(curr_ident) + " ", + interrupt=False, + flush=False, + ) self.lastIdent = curr_ident def set_callback(self, callback): diff --git a/src/fenrirscreenreader/commands/onCursorChange/85000-has_attribute.py b/src/fenrirscreenreader/commands/onCursorChange/85000-has_attribute.py index 342c6488..1de21923 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/85000-has_attribute.py +++ b/src/fenrirscreenreader/commands/onCursorChange/85000-has_attribute.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ - from fenrirscreenreader.utils import screen_utils -class command(): +class command: def __init__(self): pass @@ -20,25 +19,30 @@ class command(): pass def get_description(self): - return _('Reads attributes of current cursor position') + return _("Reads attributes of current cursor position") def run(self): # is it enabled? - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'hasattributes'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "hasattributes" + ): return # is a vertical change? - if not (self.env['runtime']['CursorManager'].is_cursor_vertical_move() or - self.env['runtime']['CursorManager'].is_cursor_horizontal_move()): + if not ( + self.env["runtime"]["CursorManager"].is_cursor_vertical_move() + or self.env["runtime"]["CursorManager"].is_cursor_horizontal_move() + ): return - cursor_pos = self.env['screen']['new_cursor'] + cursor_pos = self.env["screen"]["new_cursor"] - if not self.env['runtime']['AttributeManager'].has_attributes( - cursor_pos): + if not self.env["runtime"]["AttributeManager"].has_attributes( + cursor_pos + ): return - self.env['runtime']['OutputManager'].present_text( - 'has attribute', sound_icon ='HasAttributes', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "has attribute", sound_icon="HasAttributes", interrupt=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onCursorChange/95000-exit_review_mode.py b/src/fenrirscreenreader/commands/onCursorChange/95000-exit_review_mode.py index b568b07f..86744b8e 100644 --- a/src/fenrirscreenreader/commands/onCursorChange/95000-exit_review_mode.py +++ b/src/fenrirscreenreader/commands/onCursorChange/95000-exit_review_mode.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,14 +19,15 @@ class command(): pass def get_description(self): - return _('exits review mode') + return _("exits review mode") def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'review', 'leaveReviewOnCursorChange'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "leaveReviewOnCursorChange" + ): return - if self.env['runtime']['CursorManager'].is_review_mode(): - self.env['runtime']['CursorManager'].clear_review_cursor() + if self.env["runtime"]["CursorManager"].is_review_mode(): + self.env["runtime"]["CursorManager"].clear_review_cursor() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py b/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py index 17ace9af..23539642 100755 --- a/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py +++ b/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py @@ -1,35 +1,34 @@ #!/usr/bin/env python3 +import datetime +import time + from fenrirscreenreader.core.i18n import _ -import time # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -import time -import datetime +# By Chrys, Storm Dragon, and contributors. -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment self.last_time = datetime.datetime.now() - self.lastDateString = '' - self.lastTimeString = '' + self.lastDateString = "" + self.lastTimeString = "" def shutdown(self): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - self.env['runtime']['ScreenDriver'].get_session_information() + self.env["runtime"]["ScreenDriver"].get_session_information() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py b/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py index 493122ea..36956e27 100755 --- a/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py +++ b/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py @@ -2,45 +2,48 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import datetime +import time from fenrirscreenreader.core.i18n import _ -import time -import datetime - -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment self.last_time = datetime.datetime.now() - self.lastDateString = '' - self.lastTimeString = '' + self.lastDateString = "" + self.lastTimeString = "" def shutdown(self): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'enabled'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "enabled" + ): return - on_minutes = self.env['runtime']['SettingsManager'].get_setting( - 'time', 'on_minutes') - delay_sec = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'time', 'delay_sec') + on_minutes = self.env["runtime"]["SettingsManager"].get_setting( + "time", "on_minutes" + ) + delay_sec = self.env["runtime"]["SettingsManager"].get_setting_as_int( + "time", "delay_sec" + ) # no need - if on_minutes == '' and delay_sec <= 0: + if on_minutes == "" and delay_sec <= 0: return - on_minutes = on_minutes.split(',') + on_minutes = on_minutes.split(",") now = datetime.datetime.now() # ignore on_minutes if there is a delay_sec @@ -56,44 +59,54 @@ class command(): if now.minute == self.last_time.minute: return - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) date_string = datetime.datetime.strftime(now, date_format) - present_date = self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'present_date') and self.lastDateString != date_string - present_time = self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'present_time') + present_date = ( + self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "present_date" + ) + and self.lastDateString != date_string + ) + present_time = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_bool("time", "present_time") # no changed value to announce if not (present_date or present_time): return - time_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'time_format') + time_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "time_format" + ) time_string = datetime.datetime.strftime(now, time_format) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'interrupt'): - self.env['runtime']['OutputManager'].interrupt_output() - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'time', 'announce'): - self.env['runtime']['OutputManager'].play_sound_icon('announce') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "interrupt" + ): + self.env["runtime"]["OutputManager"].interrupt_output() + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "time", "announce" + ): + self.env["runtime"]["OutputManager"].play_sound_icon("announce") if present_time: # present the time - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( _("It's {0}").format( - time_string.replace( - ':00', - " O'clock ").lstrip('0')), - sound_icon ='', - interrupt=False) + time_string.replace(":00", " O'clock ").lstrip("0") + ), + sound_icon="", + interrupt=False, + ) # Check if it's 12:00 AM if now.hour == 0 and now.minute == 0: # present the date - self.env['runtime']['OutputManager'].present_text( - date_string, sound_icon ='', interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=False + ) self.last_time = datetime.datetime.now() self.lastTimeString = time_string diff --git a/src/fenrirscreenreader/commands/onKeyInput/10000-shut_up.py b/src/fenrirscreenreader/commands/onKeyInput/10000-shut_up.py index cdc9a065..a4e8bfb7 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/10000-shut_up.py +++ b/src/fenrirscreenreader/commands/onKeyInput/10000-shut_up.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,29 +18,37 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'interruptOnKeyPress'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "interruptOnKeyPress" + ): return - if self.env['runtime']['InputManager'].no_key_pressed(): + if self.env["runtime"]["InputManager"].no_key_pressed(): return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): return - if len( - self.env['input']['currInput']) <= len( - self.env['input']['prevInput']): + if len(self.env["input"]["currInput"]) <= len( + self.env["input"]["prevInput"] + ): return # if the filter is set - if self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'interruptOnKeyPressFilter').strip() != '': - filter_list = self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'interruptOnKeyPressFilter').split(',') - for currInput in self.env['input']['currInput']: + if ( + self.env["runtime"]["SettingsManager"] + .get_setting("keyboard", "interruptOnKeyPressFilter") + .strip() + != "" + ): + filter_list = ( + self.env["runtime"]["SettingsManager"] + .get_setting("keyboard", "interruptOnKeyPressFilter") + .split(",") + ) + for currInput in self.env["input"]["currInput"]: if currInput not in filter_list: return - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py b/src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py index 82de81f9..a2ff07ad 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py +++ b/src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,24 +19,27 @@ class command(): pass def get_description(self): - return _('disables speech until next keypress') + return _("disables speech until next keypress") def run(self): - if self.env['runtime']['InputManager'].no_key_pressed(): + if self.env["runtime"]["InputManager"].no_key_pressed(): return - if len(self.env['input']['prevInput']) > 0: + if len(self.env["input"]["prevInput"]) > 0: return - if not self.env['commandBuffer']['enableSpeechOnKeypress']: + if not self.env["commandBuffer"]["enableSpeechOnKeypress"]: return - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', str( - self.env['commandBuffer']['enableSpeechOnKeypress'])) - self.env['commandBuffer']['enableSpeechOnKeypress'] = False + self.env["runtime"]["SettingsManager"].set_setting( + "speech", + "enabled", + str(self.env["commandBuffer"]["enableSpeechOnKeypress"]), + ) + self.env["commandBuffer"]["enableSpeechOnKeypress"] = False # Also disable prompt watching since speech was manually re-enabled - if 'silenceUntilPrompt' in self.env['commandBuffer']: - self.env['commandBuffer']['silenceUntilPrompt'] = False - self.env['runtime']['OutputManager'].present_text( - _("speech enabled"), sound_icon ='SpeechOn', interrupt=True) + if "silenceUntilPrompt" in self.env["commandBuffer"]: + self.env["commandBuffer"]["silenceUntilPrompt"] = False + self.env["runtime"]["OutputManager"].present_text( + _("speech enabled"), sound_icon="SpeechOn", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onKeyInput/80000-capslock.py b/src/fenrirscreenreader/commands/onKeyInput/80000-capslock.py index 251516be..0957607d 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/80000-capslock.py +++ b/src/fenrirscreenreader/commands/onKeyInput/80000-capslock.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,22 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - if self.env['input']['oldCapsLock'] == self.env['input']['newCapsLock']: + if ( + self.env["input"]["oldCapsLock"] + == self.env["input"]["newCapsLock"] + ): return - if self.env['input']['newCapsLock']: - self.env['runtime']['OutputManager'].present_text( - _("Capslock on"), interrupt=True) + if self.env["input"]["newCapsLock"]: + self.env["runtime"]["OutputManager"].present_text( + _("Capslock on"), interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("Capslock off"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Capslock off"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onKeyInput/80300-scrolllock.py b/src/fenrirscreenreader/commands/onKeyInput/80300-scrolllock.py index 42f2ce54..ea4584be 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/80300-scrolllock.py +++ b/src/fenrirscreenreader/commands/onKeyInput/80300-scrolllock.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,22 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - if self.env['input']['oldScrollLock'] == self.env['input']['newScrollLock']: + if ( + self.env["input"]["oldScrollLock"] + == self.env["input"]["newScrollLock"] + ): return - if self.env['input']['newScrollLock']: - self.env['runtime']['OutputManager'].present_text( - _("Scrolllock on"), interrupt=True) + if self.env["input"]["newScrollLock"]: + self.env["runtime"]["OutputManager"].present_text( + _("Scrolllock on"), interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("Scrolllock off"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Scrolllock off"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onKeyInput/80500-numlock.py b/src/fenrirscreenreader/commands/onKeyInput/80500-numlock.py index 3395dec7..429ffe26 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/80500-numlock.py +++ b/src/fenrirscreenreader/commands/onKeyInput/80500-numlock.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,19 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - if self.env['input']['oldNumLock'] == self.env['input']['newNumLock']: + if self.env["input"]["oldNumLock"] == self.env["input"]["newNumLock"]: return - if self.env['input']['newNumLock']: - self.env['runtime']['OutputManager'].present_text( - _("Numlock on"), interrupt=True) + if self.env["input"]["newNumLock"]: + self.env["runtime"]["OutputManager"].present_text( + _("Numlock on"), interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _("Numlock off"), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Numlock off"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onKeyInput/81000-key_echo.py b/src/fenrirscreenreader/commands/onKeyInput/81000-key_echo.py index e5391fb6..5f168595 100644 --- a/src/fenrirscreenreader/commands/onKeyInput/81000-key_echo.py +++ b/src/fenrirscreenreader/commands/onKeyInput/81000-key_echo.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,11 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - if self.env['runtime']['HelpManager'].is_tutorial_mode(): - self.env['runtime']['InputManager'].key_echo() + if self.env["runtime"]["HelpManager"].is_tutorial_mode(): + self.env["runtime"]["InputManager"].key_echo() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onPlugInputDevice/50000-plugSound.py b/src/fenrirscreenreader/commands/onPlugInputDevice/50000-plugSound.py index 0658d1f9..fe4f4a3e 100755 --- a/src/fenrirscreenreader/commands/onPlugInputDevice/50000-plugSound.py +++ b/src/fenrirscreenreader/commands/onPlugInputDevice/50000-plugSound.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import time +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -21,22 +21,24 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): play_sound = False - device_list = self.env['runtime']['InputManager'].get_last_detected_devices( - ) + device_list = self.env["runtime"][ + "InputManager" + ].get_last_detected_devices() try: for deviceEntry in device_list: # dont play sounds for virtual devices - play_sound = play_sound or not deviceEntry['virtual'] + play_sound = play_sound or not deviceEntry["virtual"] except Exception as e: play_sound = True if play_sound: if time.time() - self.last_time > 5: - self.env['runtime']['OutputManager'].play_sound_icon( - sound_icon ='accept', interrupt=True) + self.env["runtime"]["OutputManager"].play_sound_icon( + sound_icon="accept", interrupt=True + ) last_time = time.time() def set_callback(self, callback): diff --git a/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py b/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py index 680c6bca..0ddc03f2 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,10 +18,10 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/20000-reset_last_cursor_attribute.py b/src/fenrirscreenreader/commands/onScreenChanged/20000-reset_last_cursor_attribute.py index 265021c2..a0362dcc 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/20000-reset_last_cursor_attribute.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/20000-reset_last_cursor_attribute.py @@ -1,14 +1,13 @@ - #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +18,10 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - self.env['runtime']['AttributeManager'].reset_last_cursor_attribute() + self.env["runtime"]["AttributeManager"].reset_last_cursor_attribute() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/21000-reset_barrier_change.py b/src/fenrirscreenreader/commands/onScreenChanged/21000-reset_barrier_change.py index 4ef4d363..c9bacda8 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/21000-reset_barrier_change.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/21000-reset_barrier_change.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +19,10 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - self.env['runtime']['BarrierManager'].reset_barrier_change() + self.env["runtime"]["BarrierManager"].reset_barrier_change() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/70000-barrier_detect.py b/src/fenrirscreenreader/commands/onScreenChanged/70000-barrier_detect.py index e5d1d4d1..16e64a3e 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/70000-barrier_detect.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/70000-barrier_detect.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,19 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ): return - self.env['runtime']['BarrierManager'].handle_line_barrier( - self.env['screen']['new_content_text'].split('\n'), - self.env['screen']['new_cursor']['x'], - self.env['screen']['new_cursor']['y']) + self.env["runtime"]["BarrierManager"].handle_line_barrier( + self.env["screen"]["new_content_text"].split("\n"), + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py b/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py index 7a2aee89..1a786559 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,17 +19,20 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - _("screen {0}").format( - self.env['screen']['newTTY']), - sound_icon ='ChangeTTY', + self.env["runtime"]["OutputManager"].present_text( + _("screen {0}").format(self.env["screen"]["newTTY"]), + sound_icon="ChangeTTY", interrupt=True, - flush=False) - self.env['runtime']['OutputManager'].present_text( - self.env['screen']['new_content_text'], interrupt=False, flush=False) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + self.env["screen"]["new_content_text"], + interrupt=False, + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py b/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py index d35e1209..4ba4da6b 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +19,10 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - self.env['runtime']['CursorManager'].clear_marks() + self.env["runtime"]["CursorManager"].clear_marks() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py b/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py index 74a95e2c..66922939 100644 --- a/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py +++ b/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,14 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'review', 'leaveReviewOnScreenChange'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "review", "leaveReviewOnScreenChange" + ): return - self.env['runtime']['CursorManager'].clear_review_cursor() + self.env["runtime"]["CursorManager"].clear_review_cursor() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py b/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py index 995f415a..8fc085c8 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,16 +18,19 @@ class command(): pass def get_description(self): - return _('enables or disables tracking of highlighted') + return _("enables or disables tracking of highlighted") def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'highlight'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "highlight" + ): return - attribute_delta = self.env['runtime']['AttributeManager'].get_attribute_delta( + attribute_delta = self.env["runtime"][ + "AttributeManager" + ].get_attribute_delta() + self.env["runtime"]["OutputManager"].present_text( + attribute_delta, sound_icon="", interrupt=True, flush=False ) - self.env['runtime']['OutputManager'].present_text( - attribute_delta, sound_icon ='', interrupt=True, flush=False) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py b/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py index cbb12837..29f9ec3b 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,74 +19,86 @@ class command(): pass def get_description(self): - return '' + return "" def run(self): - if self.env['screen']['newAttribDelta'] != '': + if self.env["screen"]["newAttribDelta"] != "": return - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): return - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): return - if self.env['runtime']['AttributeManager'].is_attribute_change(): + if self.env["runtime"]["AttributeManager"].is_attribute_change(): return # hack for pdmenu and maybe other dialog apps that place the cursor at last cell/row # this is not to be identified as history - if (self.env['screen']['new_cursor']['x'] == self.env['runtime']['ScreenManager'].get_columns( - ) - 1) and (self.env['screen']['new_cursor']['y'] == self.env['runtime']['ScreenManager'].get_rows() - 1): + if ( + self.env["screen"]["new_cursor"]["x"] + == self.env["runtime"]["ScreenManager"].get_columns() - 1 + ) and ( + self.env["screen"]["new_cursor"]["y"] + == self.env["runtime"]["ScreenManager"].get_rows() - 1 + ): return - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: if not ( - self.env['runtime']['InputManager'].get_last_deepest_input() in [ - ['KEY_UP'], - ['KEY_DOWN']]): + self.env["runtime"]["InputManager"].get_last_deepest_input() + in [["KEY_UP"], ["KEY_DOWN"]] + ): return - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: if not ( - self.env['runtime']['ByteManager'].get_last_byte_key() in [ - b'^[[A', - b'^[[B']): + self.env["runtime"]["ByteManager"].get_last_byte_key() + in [b"^[[A", b"^[[B"] + ): return # Get the current cursor's line from both old and new content - prev_line = self.env['screen']['old_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] - curr_line = self.env['screen']['new_content_text'].split( - '\n')[self.env['screen']['new_cursor']['y']] + prev_line = self.env["screen"]["old_content_text"].split("\n")[ + self.env["screen"]["new_cursor"]["y"] + ] + curr_line = self.env["screen"]["new_content_text"].split("\n")[ + self.env["screen"]["new_cursor"]["y"] + ] - is_blank = curr_line.strip() == '' + is_blank = curr_line.strip() == "" if prev_line == curr_line: - if self.env['screen']['new_delta'] != '': + if self.env["screen"]["new_delta"] != "": return announce = curr_line if not is_blank: - curr_prompt = curr_line.find('$') - root_prompt = curr_line.find('#') + curr_prompt = curr_line.find("$") + root_prompt = curr_line.find("#") if curr_prompt <= 0: if root_prompt > 0: curr_prompt = root_prompt else: announce = curr_line if curr_prompt > 0: - remove_digits = str.maketrans('0123456789', ' ') + remove_digits = str.maketrans("0123456789", " ") if prev_line[:curr_prompt].translate( - remove_digits) == curr_line[:curr_prompt].translate(remove_digits): - announce = curr_line[curr_prompt + 1:] + remove_digits + ) == curr_line[:curr_prompt].translate(remove_digits): + announce = curr_line[curr_prompt + 1 :] else: announce = curr_line if is_blank: - self.env['runtime']['OutputManager'].present_text( - _("blank"), sound_icon ='EmptyLine', interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + _("blank"), sound_icon="EmptyLine", interrupt=True, flush=False + ) else: - self.env['runtime']['OutputManager'].present_text( - announce, interrupt=True, flush=False) + self.env["runtime"]["OutputManager"].present_text( + announce, interrupt=True, flush=False + ) - self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True + self.env["commandsIgnore"]["onScreenUpdate"]["CHAR_DELETE_ECHO"] = True + self.env["commandsIgnore"]["onScreenUpdate"]["CHAR_ECHO"] = True + self.env["commandsIgnore"]["onScreenUpdate"]["INCOMING_IGNORE"] = True def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/65000-progress_detector.py b/src/fenrirscreenreader/commands/onScreenUpdate/65000-progress_detector.py index 4880e87e..56502712 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/65000-progress_detector.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/65000-progress_detector.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug +from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,20 +19,26 @@ class command(): pass def get_description(self): - return 'Detects progress patterns for progress bar monitoring' + return "Detects progress patterns for progress bar monitoring" def run(self): # Only run if progress monitoring is enabled try: - if 'progressMonitoring' in self.env['commandBuffer'] and self.env['commandBuffer']['progressMonitoring']: + if ( + "progressMonitoring" in self.env["commandBuffer"] + and self.env["commandBuffer"]["progressMonitoring"] + ): # Check if current line is a prompt - if so, reset progress # state if self.is_current_line_prompt(): self.reset_progress_state() # Only check new incoming text (new_delta), but filter out # screen changes - elif self.env['screen']['new_delta'] and self.is_real_progress_update(): - self.detect_progress(self.env['screen']['new_delta']) + elif ( + self.env["screen"]["new_delta"] + and self.is_real_progress_update() + ): + self.detect_progress(self.env["screen"]["new_delta"]) except Exception as e: # Silently ignore errors to avoid disrupting normal operation pass @@ -41,26 +46,30 @@ class command(): def is_real_progress_update(self): """Check if this is a real progress update vs screen change/window switch""" # If the screen/application changed, it's not a progress update - if self.env['runtime']['ScreenManager'].is_screen_change(): + if self.env["runtime"]["ScreenManager"].is_screen_change(): return False # If there was a large cursor movement, it's likely navigation, not # progress - if self.env['runtime']['CursorManager'].is_cursor_vertical_move(): + if self.env["runtime"]["CursorManager"].is_cursor_vertical_move(): x_move = abs( - self.env['screen']['new_cursor']['x'] - - self.env['screen']['old_cursor']['x']) + self.env["screen"]["new_cursor"]["x"] + - self.env["screen"]["old_cursor"]["x"] + ) y_move = abs( - self.env['screen']['new_cursor']['y'] - - self.env['screen']['old_cursor']['y']) + self.env["screen"]["new_cursor"]["y"] + - self.env["screen"]["old_cursor"]["y"] + ) # Large movements suggest navigation, not progress output if y_move > 2 or x_move > 20: return False # Check if delta is too large (screen change) vs small incremental # updates - delta_length = len(self.env['screen']['new_delta']) - if delta_length > 200: # Allow longer progress lines like Claude Code's status + delta_length = len(self.env["screen"]["new_delta"]) + if ( + delta_length > 200 + ): # Allow longer progress lines like Claude Code's status return False # Check if current line looks like a prompt - progress unlikely during @@ -72,11 +81,12 @@ class command(): def reset_progress_state(self): """Reset progress state when a prompt is detected, allowing new progress operations to start fresh""" - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "Resetting progress state due to prompt detection", - debug.DebugLevel.INFO) - self.env['commandBuffer']['lastProgressValue'] = -1 - self.env['commandBuffer']['lastProgressTime'] = 0 + debug.DebugLevel.INFO, + ) + self.env["commandBuffer"]["lastProgressValue"] = -1 + self.env["commandBuffer"]["lastProgressTime"] = 0 def detect_progress(self, text): import re @@ -85,8 +95,9 @@ class command(): current_time = time.time() # Debug: Print what we're checking - self.env['runtime']['DebugManager'].write_debug_out( - "Progress detector checking: '" + text + "'", debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "Progress detector checking: '" + text + "'", debug.DebugLevel.INFO + ) # Note: Auto-disable on 100% completion removed to respect user # settings @@ -94,63 +105,85 @@ class command(): # Pattern 1: Percentage (50%, 25.5%, etc.) # Filter out common non-progress percentages (weather, system stats, # etc.) - percent_match = re.search(r'(\d+(?:\.\d+)?)\s*%', text) + percent_match = re.search(r"(\d+(?:\.\d+)?)\s*%", text) if percent_match: percentage = float(percent_match.group(1)) # Only trigger on realistic progress percentages (0-100%) if 0 <= percentage <= 100: # Filter out weather/system stats that contain percentages if not re.search( - r'\b(?:humidity|cpu|memory|disk|usage|temp|weather|forecast)\b', + r"\b(?:humidity|cpu|memory|disk|usage|temp|weather|forecast)\b", text, - re.IGNORECASE): - self.env['runtime']['DebugManager'].write_debug_out( - "found percentage: " + str(percentage), debug.DebugLevel.INFO) - if percentage != self.env['commandBuffer']['lastProgressValue']: - self.env['runtime']['DebugManager'].write_debug_out( - "Playing tone for: " + str(percentage), debug.DebugLevel.INFO) + re.IGNORECASE, + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "found percentage: " + str(percentage), + debug.DebugLevel.INFO, + ) + if ( + percentage + != self.env["commandBuffer"]["lastProgressValue"] + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Playing tone for: " + str(percentage), + debug.DebugLevel.INFO, + ) self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"][ + "lastProgressValue" + ] = percentage + self.env["commandBuffer"][ + "lastProgressTime" + ] = current_time return # Pattern 1b: Time/token activity (not percentage-based, so use single # beep) - time_match = re.search(r'(\d+)s\s', text) - token_match = re.search(r'(\d+)\s+tokens', text) + time_match = re.search(r"(\d+)s\s", text) + token_match = re.search(r"(\d+)\s+tokens", text) # Pattern 1c: dd command output (bytes copied with transfer rate) - dd_match = re.search(r'\d+\s+bytes.*copied.*\d+\s+s.*[kMGT]?B/s', text) + dd_match = re.search(r"\d+\s+bytes.*copied.*\d+\s+s.*[kMGT]?B/s", text) # Pattern 1d: Curl-style transfer data (bytes, speed indicators) curl_match = re.search( - r'(\d+\s+\d+\s+\d+\s+\d+.*?(?:k|M|G)?.*?--:--:--|Speed)', text) + r"(\d+\s+\d+\s+\d+\s+\d+.*?(?:k|M|G)?.*?--:--:--|Speed)", text + ) if time_match or token_match or dd_match or curl_match: # For non-percentage progress, use a single activity beep every 2 # seconds - if current_time - \ - self.env['commandBuffer']['lastProgressTime'] >= 2.0: - self.env['runtime']['DebugManager'].write_debug_out( - "Playing activity beep for transfer progress", debug.DebugLevel.INFO) + if ( + current_time - self.env["commandBuffer"]["lastProgressTime"] + >= 2.0 + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Playing activity beep for transfer progress", + debug.DebugLevel.INFO, + ) self.play_activity_beep() - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressTime"] = current_time return # Pattern 2: Fraction (15/100, 3 of 10, etc.) - fraction_match = re.search(r'(\d+)\s*(?:of|/)\s*(\d+)', text) + 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)) if total > 0: percentage = (current / total) * 100 - if percentage != self.env['commandBuffer']['lastProgressValue']: + if ( + percentage + != self.env["commandBuffer"]["lastProgressValue"] + ): self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressValue"] = percentage + self.env["commandBuffer"][ + "lastProgressTime" + ] = current_time return # Pattern 3: Progress bars ([#### ], [====> ], etc.) # Improved pattern to avoid matching IRC channels like [#channel] - bar_match = re.search(r'\[([#=\-\*]+)([\s\.]*)\]', text) + bar_match = re.search(r"\[([#=\-\*]+)([\s\.]*)\]", text) if bar_match: filled = len(bar_match.group(1)) unfilled = len(bar_match.group(2)) @@ -158,27 +191,35 @@ class command(): # 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))): + not bar_match.group(2) + or re.match(r"^[\s\.]*$", bar_match.group(2)) + ): percentage = (filled / total) * 100 - if percentage != self.env['commandBuffer']['lastProgressValue']: + if ( + percentage + != self.env["commandBuffer"]["lastProgressValue"] + ): self.play_progress_tone(percentage) - self.env['commandBuffer']['lastProgressValue'] = percentage - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressValue"] = percentage + self.env["commandBuffer"][ + "lastProgressTime" + ] = current_time return # Pattern 4: Generic activity indicators (Loading..., Working..., etc.) activity_pattern = re.search( - r'(loading|processing|working|installing|downloading|compiling|building).*\.{2,}', + r"(loading|processing|working|installing|downloading|compiling|building).*\.{2,}", text, - re.IGNORECASE) + re.IGNORECASE, + ) if activity_pattern: # Play a steady beep every 2 seconds for ongoing activity - if current_time - \ - self.env['commandBuffer']['lastProgressTime'] >= 2.0: + if ( + current_time - self.env["commandBuffer"]["lastProgressTime"] + >= 2.0 + ): self.play_activity_beep() - self.env['commandBuffer']['lastProgressTime'] = current_time + self.env["commandBuffer"]["lastProgressTime"] = current_time def play_progress_tone(self, percentage): # Map 0-100% to 400-1200Hz frequency range @@ -195,8 +236,8 @@ class command(): def play_quiet_tone(self, frequency, duration): """Play a quiet tone using Sox directly""" - import subprocess import shlex + import subprocess # Build the Sox command: play -qn synth tri gain # -8 @@ -204,17 +245,20 @@ class command(): try: # Only play if sound is enabled - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'): + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): subprocess.Popen( shlex.split(command), stdin=None, stdout=None, stderr=None, - shell=False) + shell=False, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Sox tone error: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Sox tone error: " + str(e), debug.DebugLevel.ERROR + ) def is_current_line_prompt(self): """Check if the current line looks like a standalone prompt (not command with progress)""" @@ -222,10 +266,10 @@ class command(): try: # Get the current screen content - if not self.env['screen']['new_content_text']: + if not self.env["screen"]["new_content_text"]: return False - lines = self.env['screen']['new_content_text'].split('\n') + lines = self.env["screen"]["new_content_text"].split("\n") if not lines: return False @@ -238,34 +282,34 @@ class command(): lines_to_check.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): + 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']]) + lines[self.env["screen"]["new_cursor"]["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 - + r"^\s*\$\s*$", # Just $ (with whitespace) + r"^\s*#\s*$", # Just # (with whitespace) + r"^\s*>\s*$", # Just > (with whitespace) + r"^\[.*\]\s*[\\\$#>]\s*$", # [path]$ without commands + r"^[a-zA-Z0-9._-]+[\\\$#>]\s*$", # bash-5.1$ without commands # Interactive prompt patterns (these ARE standalone) - r'.*\?\s*\[[YyNn]/[YyNn]\]\s*$', # ? [Y/n] or ? [y/N] style - r'.*\?\s*\[[Yy]es/[Nn]o\]\s*$', # ? [Yes/No] style + r".*\?\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".*continue\?\s*\[[YyNn]/[YyNn]\].*$", + 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: @@ -276,22 +320,21 @@ class command(): # 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)) + 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, # it's a command line, not a standalone prompt prompt_end = max( - line.rfind('$'), - line.rfind('#'), - line.rfind('>'), - line.rfind('\\') + 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 ( + prompt_end >= 0 and prompt_end < len(line) - 5 + ): # More than just whitespace after prompt continue # This is a command line, not a standalone prompt for pattern in standalone_prompt_patterns: diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/66000-prompt_detector.py b/src/fenrirscreenreader/commands/onScreenUpdate/66000-prompt_detector.py index b290baf0..080b9f34 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/66000-prompt_detector.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/66000-prompt_detector.py @@ -2,14 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug +from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,46 +19,59 @@ class command(): pass def get_description(self): - return 'Detects shell prompts for silence until prompt feature' + return "Detects shell prompts for silence until prompt feature" def run(self): # Only run if silence until prompt is active try: - if 'silenceUntilPrompt' in self.env['commandBuffer'] and self.env['commandBuffer']['silenceUntilPrompt']: + if ( + "silenceUntilPrompt" in self.env["commandBuffer"] + and self.env["commandBuffer"]["silenceUntilPrompt"] + ): # Check the current line for prompt patterns - if self.env['screen']['new_content_text']: - lines = self.env['screen']['new_content_text'].split('\n') - if lines and self.env['screen']['new_cursor']['y'] < len( - lines): - current_line = lines[self.env['screen'] - ['new_cursor']['y']] + if self.env["screen"]["new_content_text"]: + lines = self.env["screen"]["new_content_text"].split("\n") + if lines and self.env["screen"]["new_cursor"]["y"] < len( + lines + ): + current_line = lines[ + self.env["screen"]["new_cursor"]["y"] + ] self.check_for_prompt(current_line) except Exception as e: # Silently ignore errors to avoid disrupting normal operation - self.env['runtime']['DebugManager'].write_debug_out( - 'prompt_detector run: Error in prompt detection: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "prompt_detector run: Error in prompt detection: " + str(e), + debug.DebugLevel.ERROR, + ) def check_for_prompt(self, text): """Check if the current line contains a shell prompt pattern""" import re # Debug: Print what we're checking - self.env['runtime']['DebugManager'].write_debug_out( - "Prompt detector checking: '" + text + "'", debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "Prompt detector checking: '" + text + "'", debug.DebugLevel.INFO + ) # First check for exact matches from settings (with backward # compatibility) try: - exact_matches = self.env['runtime']['SettingsManager'].get_setting( - 'prompt', 'exact_matches') + exact_matches = self.env["runtime"]["SettingsManager"].get_setting( + "prompt", "exact_matches" + ) if exact_matches: - exact_list = [match.strip() - for match in exact_matches.split(',') if match.strip()] + exact_list = [ + match.strip() + for match in exact_matches.split(",") + if match.strip() + ] for exactMatch in exact_list: if text.strip() == exactMatch: - self.env['runtime']['DebugManager'].write_debug_out( - "found exact prompt match: " + exactMatch, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "found exact prompt match: " + exactMatch, + debug.DebugLevel.INFO, + ) self._restore_speech() return True except Exception as e: @@ -70,70 +82,76 @@ class command(): # Get custom patterns from settings (with backward compatibility) prompt_patterns = [] try: - custom_patterns = self.env['runtime']['SettingsManager'].get_setting( - 'prompt', 'custom_patterns') + custom_patterns = self.env["runtime"][ + "SettingsManager" + ].get_setting("prompt", "custom_patterns") # Add custom patterns from settings if they exist if custom_patterns: custom_list = [ - pattern.strip() for pattern in custom_patterns.split(',') if pattern.strip()] + pattern.strip() + for pattern in custom_patterns.split(",") + if pattern.strip() + ] prompt_patterns.extend(custom_list) except Exception as e: # Prompt section doesn't exist in settings, skip custom patterns pass # Add default shell prompt patterns - prompt_patterns.extend([ - r'^\s*\$\s*$', # Just $ (with whitespace) - r'^\s*#\s*$', # Just # (with whitespace) - r'^\s*>\s*$', # Just > (with whitespace) - r'.*@.*[\\\$#>]\s*$', - # Contains @ and ends with prompt char (user@host style) - r'^\[.*\]\s*[\\\$#>]\s*$', # [anything]$ style prompts - # Simple shell names like bash-5.1$ - r'^[a-zA-Z0-9._-]+[\\\$#>]\s*$', - - # Interactive prompt patterns - # Package manager confirmation prompts - r'.*\?\s*\[[YyNn]/[YyNn]\]\s*$', # ? [Y/n] or ? [y/N] style - r'.*\?\s*\[[Yy]es/[Nn]o\]\s*$', # ? [Yes/No] style - 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'.*ok\s*\[[YyNn]/[YyNn]\].*$', # "Is this ok [y/N]:" style - # pacman ":: Proceed? [Y/n]" style - r'^::.*\?\s*\[[YyNn]/[YyNn]\].*$', - - # Authentication prompts - # [sudo] password for user: - r'^\[[Ss]udo\]\s*[Pp]assword\s*for\s+.*:\s*$', - r'^[Pp]assword\s*:\s*$', # Password: - r'.*[Pp]assword\s*:\s*$', # general password prompts - r".*'s\s*[Pp]assword\s*:\s*$", # user's password: - r'^[Ee]nter\s+[Pp]assphrase.*:\s*$', # Enter passphrase: - # Please enter passphrase: - r'^[Pp]lease\s+enter\s+[Pp]assphrase.*:\s*$', - - # General confirmation and continuation prompts - # Press any key to continue - r'^[Pp]ress\s+any\s+key\s+to\s+continue.*$', - r'^[Aa]re\s+you\s+sure\?\s*.*$', # Are you sure? - r'^[Pp]lease\s+confirm.*$', # Please confirm - r'.*confirm.*\([YyNn]/[YyNn]\).*$', # confirm (y/n) - r'.*\([Yy]/[Nn]\)\s*$', # ends with (Y/n) or (y/N) - ]) + prompt_patterns.extend( + [ + r"^\s*\$\s*$", # Just $ (with whitespace) + r"^\s*#\s*$", # Just # (with whitespace) + r"^\s*>\s*$", # Just > (with whitespace) + r".*@.*[\\\$#>]\s*$", + # Contains @ and ends with prompt char (user@host style) + r"^\[.*\]\s*[\\\$#>]\s*$", # [anything]$ style prompts + # Simple shell names like bash-5.1$ + r"^[a-zA-Z0-9._-]+[\\\$#>]\s*$", + # Interactive prompt patterns + # Package manager confirmation prompts + r".*\?\s*\[[YyNn]/[YyNn]\]\s*$", # ? [Y/n] or ? [y/N] style + r".*\?\s*\[[Yy]es/[Nn]o\]\s*$", # ? [Yes/No] style + 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".*ok\s*\[[YyNn]/[YyNn]\].*$", # "Is this ok [y/N]:" style + # pacman ":: Proceed? [Y/n]" style + r"^::.*\?\s*\[[YyNn]/[YyNn]\].*$", + # Authentication prompts + # [sudo] password for user: + r"^\[[Ss]udo\]\s*[Pp]assword\s*for\s+.*:\s*$", + r"^[Pp]assword\s*:\s*$", # Password: + r".*[Pp]assword\s*:\s*$", # general password prompts + r".*'s\s*[Pp]assword\s*:\s*$", # user's password: + r"^[Ee]nter\s+[Pp]assphrase.*:\s*$", # Enter passphrase: + # Please enter passphrase: + r"^[Pp]lease\s+enter\s+[Pp]assphrase.*:\s*$", + # General confirmation and continuation prompts + # Press any key to continue + r"^[Pp]ress\s+any\s+key\s+to\s+continue.*$", + r"^[Aa]re\s+you\s+sure\?\s*.*$", # Are you sure? + r"^[Pp]lease\s+confirm.*$", # Please confirm + r".*confirm.*\([YyNn]/[YyNn]\).*$", # confirm (y/n) + r".*\([Yy]/[Nn]\)\s*$", # ends with (Y/n) or (y/N) + ] + ) for pattern in prompt_patterns: try: if re.search(pattern, text.strip()): - self.env['runtime']['DebugManager'].write_debug_out( - "found prompt pattern: " + pattern, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "found prompt pattern: " + pattern, + debug.DebugLevel.INFO, + ) self._restore_speech() return True except re.error as e: # Invalid regex pattern, skip it and log the error - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "Invalid prompt pattern: " + pattern + " Error: " + str(e), - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) continue return False @@ -141,16 +159,18 @@ class command(): def _restore_speech(self): """Helper method to restore speech when prompt is detected""" # Disable silence mode - self.env['commandBuffer']['silenceUntilPrompt'] = False + self.env["commandBuffer"]["silenceUntilPrompt"] = False # Also disable the keypress-based speech restoration since we're # enabling it now - if 'enableSpeechOnKeypress' in self.env['commandBuffer']: - self.env['commandBuffer']['enableSpeechOnKeypress'] = False + if "enableSpeechOnKeypress" in self.env["commandBuffer"]: + self.env["commandBuffer"]["enableSpeechOnKeypress"] = False # Re-enable speech - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', 'True') - self.env['runtime']['OutputManager'].present_text( - _("Speech restored"), sound_icon ='SpeechOn', interrupt=True) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "enabled", "True" + ) + self.env["runtime"]["OutputManager"].present_text( + _("Speech restored"), sound_icon="SpeechOn", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py b/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py index 6593fe2b..8bf0d239 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,33 +19,37 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'autoReadIncoming'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "autoReadIncoming" + ): return # is there something to read? - if not self.env['runtime']['ScreenManager'].is_delta(ignoreSpace=True): + if not self.env["runtime"]["ScreenManager"].is_delta(ignoreSpace=True): return # this must be a keyecho or something # if len(self.env['screen']['new_delta'].strip(' \n\t')) <= 1: x_move = abs( - self.env['screen']['new_cursor']['x'] - - self.env['screen']['old_cursor']['x']) + self.env["screen"]["new_cursor"]["x"] + - self.env["screen"]["old_cursor"]["x"] + ) y_move = abs( - self.env['screen']['new_cursor']['y'] - - self.env['screen']['old_cursor']['y']) + self.env["screen"]["new_cursor"]["y"] + - self.env["screen"]["old_cursor"]["y"] + ) - if (x_move >= 1) and x_move == len(self.env['screen']['new_delta']): + if (x_move >= 1) and x_move == len(self.env["screen"]["new_delta"]): # if len(self.env['screen']['new_delta'].strip(' \n\t0123456789')) # <= 2: - if '\n' not in self.env['screen']['new_delta']: + if "\n" not in self.env["screen"]["new_delta"]: return # print(x_move, y_move, len(self.env['screen']['new_delta']), len(self.env['screen']['newNegativeDelta'])) - self.env['runtime']['OutputManager'].present_text( - self.env['screen']['new_delta'], interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + self.env["screen"]["new_delta"], interrupt=False, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py b/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py index 8ba5ae35..a6f877da 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py @@ -1,15 +1,16 @@ #!/usr/bin/env python3 +import time + from fenrirscreenreader.core.i18n import _ -import time # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -class command(): +class command: def __init__(self): pass @@ -20,32 +21,45 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'promote', 'enabled'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "promote", "enabled" + ): return - if self.env['runtime']['SettingsManager'].get_setting( - 'promote', 'list').strip(" \t\n") == '': + if ( + self.env["runtime"]["SettingsManager"] + .get_setting("promote", "list") + .strip(" \t\n") + == "" + ): return - if int( - time.time() - - self.env['input']['lastInputTime']) < self.env['runtime']['SettingsManager'].get_setting_as_int( - 'promote', - 'inactiveTimeoutSec'): + if int(time.time() - self.env["input"]["lastInputTime"]) < self.env[ + "runtime" + ]["SettingsManager"].get_setting_as_int( + "promote", "inactiveTimeoutSec" + ): return - if len( - self.env['runtime']['SettingsManager'].get_setting( - 'promote', - 'list')) == 0: + if ( + len( + self.env["runtime"]["SettingsManager"].get_setting( + "promote", "list" + ) + ) + == 0 + ): return - for promote in self.env['runtime']['SettingsManager'].get_setting( - 'promote', 'list').split(','): - if promote in self.env['screen']['new_delta']: - self.env['runtime']['OutputManager'].play_sound_icon( - 'PromotedText') - self.env['input']['lastInputTime'] = time.time() + for promote in ( + self.env["runtime"]["SettingsManager"] + .get_setting("promote", "list") + .split(",") + ): + if promote in self.env["screen"]["new_delta"]: + self.env["runtime"]["OutputManager"].play_sound_icon( + "PromotedText" + ) + self.env["input"]["lastInputTime"] = time.time() return def set_callback(self, callback): diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/80000-barrier_detect.py b/src/fenrirscreenreader/commands/onScreenUpdate/80000-barrier_detect.py index e26ed52a..33aefd4e 100644 --- a/src/fenrirscreenreader/commands/onScreenUpdate/80000-barrier_detect.py +++ b/src/fenrirscreenreader/commands/onScreenUpdate/80000-barrier_detect.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,18 +19,20 @@ class command(): pass def get_description(self): - return 'No Description found' + return "No Description found" def run(self): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ): return - if not self.env['runtime']['ScreenManager'].is_delta(ignoreSpace=True): + if not self.env["runtime"]["ScreenManager"].is_delta(ignoreSpace=True): return - self.env['runtime']['BarrierManager'].handle_line_barrier( - self.env['screen']['new_content_text'].split('\n'), - self.env['screen']['new_cursor']['x'], - self.env['screen']['new_cursor']['y']) + self.env["runtime"]["BarrierManager"].handle_line_barrier( + self.env["screen"]["new_content_text"].split("\n"), + self.env["screen"]["new_cursor"]["x"], + self.env["screen"]["new_cursor"]["y"], + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py index 9e1914d0..69f7c650 100644 --- a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,21 +19,21 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def load(self): return - print('--------------') - print('default') - print('load new', self.env['screen']['new_application']) - print('--------------') + print("--------------") + print("default") + print("load new", self.env["screen"]["new_application"]) + print("--------------") def unload(self): return - print('--------------') - print('default') - print('unload old', self.env['screen']['oldApplication']) - print('--------------') + print("--------------") + print("default") + print("unload old", self.env["screen"]["oldApplication"]) + print("--------------") def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_entry.py b/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_entry.py index 960f3026..82880896 100644 --- a/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,16 +19,17 @@ class command(): pass def get_description(self): - return _('get current quick menu entry') + 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) + menu = "" + value = "" + menu = self.env["runtime"]["QuickMenuManager"].get_current_entry() + if menu != "": + value = self.env["runtime"]["QuickMenuManager"].get_current_value() + self.env["runtime"]["OutputManager"].present_text( + menu + " " + value, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_value.py b/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_value.py index fc693ca5..11acac5e 100644 --- a/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/quickMenu/current_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,13 @@ class command(): pass def get_description(self): - return _('get current quick menu value') + 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) + value = self.env["runtime"]["QuickMenuManager"].get_current_value() + self.env["runtime"]["OutputManager"].present_text( + value, interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_entry.py b/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_entry.py index c99fd2a7..0a66a36e 100644 --- a/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,24 @@ class command(): pass def get_description(self): - return _('get next quick menu entry') + 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"].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 + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Quick menu not available'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Quick menu not available"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_value.py b/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_value.py index 11b4f312..1ce866cf 100644 --- a/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/quickMenu/next_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,14 @@ class command(): pass def get_description(self): - return _('get next quick menu value') + 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) + 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): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_entry.py b/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_entry.py index 160f0de2..0a288416 100644 --- a/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_entry.py +++ b/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,20 +19,24 @@ class command(): pass def get_description(self): - return _('get previous quick menu entry') + 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"].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 + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Quick menu not available'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("Quick menu not available"), interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_value.py b/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_value.py index 99b2dbfe..aa28e124 100644 --- a/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_value.py +++ b/src/fenrirscreenreader/commands/quickMenu/prev_quick_menu_value.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,13 +19,14 @@ class command(): pass def get_description(self): - return _('get previous quick menu value') + 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) + 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): pass diff --git a/src/fenrirscreenreader/commands/switchTrigger_template.py b/src/fenrirscreenreader/commands/switchTrigger_template.py index 0e0bf5ff..4ba1e79d 100644 --- a/src/fenrirscreenreader/commands/switchTrigger_template.py +++ b/src/fenrirscreenreader/commands/switchTrigger_template.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,7 +19,7 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def unload(self): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/curr_vmenu_entry.py b/src/fenrirscreenreader/commands/vmenu-navigation/curr_vmenu_entry.py index 069eca62..ed1790f5 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/curr_vmenu_entry.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/curr_vmenu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,11 @@ class command(): pass def get_description(self): - return _('get current v menu entry') + return _("get current v menu entry") def run(self): - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/dec_level_vmenu.py b/src/fenrirscreenreader/commands/vmenu-navigation/dec_level_vmenu.py index cc63c686..bcd8980f 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/dec_level_vmenu.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/dec_level_vmenu.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('leave v menu submenu') + return _("leave v menu submenu") def run(self): - self.env['runtime']['VmenuManager'].dec_level() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].dec_level() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/exec_vmenu_entry.py b/src/fenrirscreenreader/commands/vmenu-navigation/exec_vmenu_entry.py index 9279ec99..8adce6f5 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/exec_vmenu_entry.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/exec_vmenu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,10 +19,10 @@ class command(): pass def get_description(self): - return _('execute v menu entry') + return _("execute v menu entry") def run(self): - self.env['runtime']['VmenuManager'].execute_menu() + self.env["runtime"]["VmenuManager"].execute_menu() def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/inc_level_vmenu.py b/src/fenrirscreenreader/commands/vmenu-navigation/inc_level_vmenu.py index 94d0f6cc..5f44c466 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/inc_level_vmenu.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/inc_level_vmenu.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('enter v menu submenu') + return _("enter v menu submenu") def run(self): - self.env['runtime']['VmenuManager'].inc_level() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].inc_level() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/next_vmenu_entry.py b/src/fenrirscreenreader/commands/vmenu-navigation/next_vmenu_entry.py index 449b63cf..d2c17708 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/next_vmenu_entry.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/next_vmenu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('get next v menu entry') + return _("get next v menu entry") def run(self): - self.env['runtime']['VmenuManager'].next_index() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].next_index() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/page_down_vmenu.py b/src/fenrirscreenreader/commands/vmenu-navigation/page_down_vmenu.py index d490a2a3..f8431345 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/page_down_vmenu.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/page_down_vmenu.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('jump down 10% in v menu') + return _("jump down 10% in v menu") def run(self): - self.env['runtime']['VmenuManager'].page_down() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].page_down() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/page_up_vmenu.py b/src/fenrirscreenreader/commands/vmenu-navigation/page_up_vmenu.py index 0de37dce..76bab1fc 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/page_up_vmenu.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/page_up_vmenu.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('jump up 10% in v menu') + return _("jump up 10% in v menu") def run(self): - self.env['runtime']['VmenuManager'].page_up() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].page_up() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/prev_vmenu_entry.py b/src/fenrirscreenreader/commands/vmenu-navigation/prev_vmenu_entry.py index ed0f21c2..12c4dd3f 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/prev_vmenu_entry.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/prev_vmenu_entry.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,12 +19,12 @@ class command(): pass def get_description(self): - return _('get prev v menu entry') + return _("get prev v menu entry") def run(self): - self.env['runtime']['VmenuManager'].prev_index() - text = self.env['runtime']['VmenuManager'].get_current_entry() - self.env['runtime']['OutputManager'].present_text(text, interrupt=True) + self.env["runtime"]["VmenuManager"].prev_index() + text = self.env["runtime"]["VmenuManager"].get_current_entry() + self.env["runtime"]["OutputManager"].present_text(text, interrupt=True) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_a.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_a.py index bfb73612..fec973bd 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_a.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_a.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('a') + super().__init__("a") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_b.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_b.py index 530e00dc..069b0f35 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_b.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_b.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('b') + super().__init__("b") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_c.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_c.py index 3d710545..944396b8 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_c.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_c.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('c') + super().__init__("c") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_d.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_d.py index 070aadca..2147c19e 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_d.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_d.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('d') + super().__init__("d") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_e.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_e.py index 46e6659f..e9de9c51 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_e.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_e.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('e') + super().__init__("e") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_f.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_f.py index 693e2c1d..8b47e14f 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_f.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_f.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('f') + super().__init__("f") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_g.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_g.py index bb53ae0a..523553b4 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_g.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_g.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('g') + super().__init__("g") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_h.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_h.py index b44baccf..5ef84e3d 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_h.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_h.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('h') + super().__init__("h") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_i.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_i.py index dab222a8..6f1317bf 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_i.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_i.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('i') + super().__init__("i") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_j.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_j.py index e76bd33c..6f787659 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_j.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_j.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('j') + super().__init__("j") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_k.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_k.py index c1c07f7d..fe59fbaa 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_k.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_k.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('k') + super().__init__("k") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_l.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_l.py index 136ba02d..ce9bae91 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_l.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_l.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('l') + super().__init__("l") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_m.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_m.py index acd475f2..20dafa53 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_m.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_m.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('m') + super().__init__("m") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_n.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_n.py index 86256ebc..caa87a49 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_n.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_n.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('n') + super().__init__("n") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_o.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_o.py index 801c107b..6e1d2692 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_o.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_o.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('o') + super().__init__("o") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_p.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_p.py index 04c48868..8bfee74d 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_p.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_p.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('p') + super().__init__("p") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_q.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_q.py index 4011606c..03049d76 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_q.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_q.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('q') + super().__init__("q") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_r.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_r.py index 627ce9d8..2959cea9 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_r.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_r.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('r') + super().__init__("r") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_s.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_s.py index 1997378c..715ff0ae 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_s.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_s.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('s') + super().__init__("s") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_t.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_t.py index d66c3690..4ef74e45 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_t.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_t.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('t') + super().__init__("t") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_u.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_u.py index 9cf7e6fe..2adaf8bf 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_u.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_u.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('u') + super().__init__("u") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_v.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_v.py index f24b7d9f..8dc23241 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_v.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_v.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('v') + super().__init__("v") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_w.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_w.py index fd30ebd3..b001e3b5 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_w.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_w.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('w') + super().__init__("w") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_x.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_x.py index 4625a4e0..7ab21315 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_x.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_x.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('x') + super().__init__("x") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_y.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_y.py index 7d12210f..10fa02a6 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_y.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_y.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('y') + super().__init__("y") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/search_z.py b/src/fenrirscreenreader/commands/vmenu-navigation/search_z.py index 35c2e0e1..6af9f577 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/search_z.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/search_z.py @@ -2,15 +2,17 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import importlib.util import os + +from fenrirscreenreader.core.i18n import _ + _spec = importlib.util.spec_from_file_location( - "vmenu_search_base", os.path.join( - os.path.dirname(__file__), "vmenu_search_base.py")) + "vmenu_search_base", + os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"), +) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) vmenu_search_command = _module.vmenu_search_command @@ -18,4 +20,4 @@ vmenu_search_command = _module.vmenu_search_command class command(vmenu_search_command): def __init__(self): - super().__init__('z') + super().__init__("z") diff --git a/src/fenrirscreenreader/commands/vmenu-navigation/vmenu_search_base.py b/src/fenrirscreenreader/commands/vmenu-navigation/vmenu_search_base.py index 9e57906c..b90c9c59 100644 --- a/src/fenrirscreenreader/commands/vmenu-navigation/vmenu_search_base.py +++ b/src/fenrirscreenreader/commands/vmenu-navigation/vmenu_search_base.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class vmenu_search_command(): +class vmenu_search_command: """Base class for VMenu search commands""" def __init__(self, search_char): @@ -20,17 +20,20 @@ class vmenu_search_command(): pass def get_description(self): - return _('search for an menu entry') + return _("search for a menu entry") def run(self): - text = self.env['runtime']['VmenuManager'].search_entry( - self.search_char) - if text != '': - self.env['runtime']['OutputManager'].present_text( - text, interrupt=True) + text = self.env["runtime"]["VmenuManager"].search_entry( + self.search_char + ) + if text != "": + self.env["runtime"]["OutputManager"].present_text( + text, interrupt=True + ) else: - self.env['runtime']['OutputManager'].present_text( - _('not found'), sound_icon ='ErrorScreen', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("not found"), sound_icon="ErrorScreen", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/config_base.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/config_base.py index 8254b407..f1ad1b37 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/config_base.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/config_base.py @@ -2,18 +2,18 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. +import configparser import os import shutil import tempfile -import configparser from datetime import datetime +from fenrirscreenreader.core.i18n import _ -class config_command(): + +class config_command: """Base class for configuration management commands""" def __init__(self): @@ -23,8 +23,10 @@ class config_command(): def initialize(self, environment): self.env = environment - self.settings_file = self.env['runtime']['SettingsManager'].settings_file - self.config = self.env['runtime']['SettingsManager'].settings + self.settings_file = self.env["runtime"][ + "SettingsManager" + ].settings_file + self.config = self.env["runtime"]["SettingsManager"].settings def shutdown(self): pass @@ -34,22 +36,24 @@ class config_command(): def present_text(self, text, interrupt=True, flush=True): """Present text to user with proper speech handling""" - self.env['runtime']['OutputManager'].present_text( - text, interrupt=interrupt, flush=flush) + self.env["runtime"]["OutputManager"].present_text( + text, interrupt=interrupt, flush=flush + ) def play_sound(self, soundName): """Play system sound""" - sound_icon = '' - if soundName == 'Accept': - sound_icon = 'Accept' - elif soundName == 'Error': - sound_icon = 'ErrorSound' - elif soundName == 'Cancel': - sound_icon = 'Cancel' + sound_icon = "" + if soundName == "Accept": + sound_icon = "Accept" + elif soundName == "Error": + sound_icon = "ErrorSound" + elif soundName == "Cancel": + sound_icon = "Cancel" if sound_icon: - self.env['runtime']['OutputManager'].present_text( - '', sound_icon =sound_icon, interrupt=False) + self.env["runtime"]["OutputManager"].present_text( + "", sound_icon=sound_icon, interrupt=False + ) def backup_config(self, announce=True): """Create backup of current configuration file""" @@ -81,8 +85,8 @@ class config_command(): """Reload configuration from file""" try: # Force settings manager to reload from file - self.env['runtime']['SettingsManager'].load_settings() - self.config = self.env['runtime']['SettingsManager'].settings + self.env["runtime"]["SettingsManager"].load_settings() + self.config = self.env["runtime"]["SettingsManager"].settings return True except Exception as e: @@ -93,18 +97,17 @@ class config_command(): """Find default configuration file path""" # Look for default config in multiple locations default_paths = [ - '/etc/fenrir/settings/settings.conf.default', - '/usr/share/fenrir/settings/settings.conf', + "/etc/fenrir/settings/settings.conf.default", + "/usr/share/fenrir/settings/settings.conf", os.path.join( - os.path.dirname( - self.settings_file), - 'settings.conf.default'), + os.path.dirname(self.settings_file), "settings.conf.default" + ), os.path.join( - os.path.dirname( - os.path.dirname( - self.settings_file)), - 'settings', - 'settings.conf.default')] + os.path.dirname(os.path.dirname(self.settings_file)), + "settings", + "settings.conf.default", + ), + ] for path in default_paths: if os.path.exists(path): @@ -119,25 +122,25 @@ class config_command(): self.config = configparser.ConfigParser() # Add basic sections and settings - self.config.add_section('speech') - self.config.set('speech', 'driver', 'speechdDriver') - self.config.set('speech', 'rate', '0.75') - self.config.set('speech', 'pitch', '0.5') - self.config.set('speech', 'volume', '1.0') + self.config.add_section("speech") + self.config.set("speech", "driver", "speechdDriver") + self.config.set("speech", "rate", "0.75") + self.config.set("speech", "pitch", "0.5") + self.config.set("speech", "volume", "1.0") - self.config.add_section('sound') - self.config.set('sound', 'driver', 'genericDriver') - self.config.set('sound', 'volume', '0.7') + self.config.add_section("sound") + self.config.set("sound", "driver", "genericDriver") + self.config.set("sound", "volume", "0.7") - self.config.add_section('keyboard') - self.config.set('keyboard', 'driver', 'evdevDriver') - self.config.set('keyboard', 'keyboardLayout', 'desktop') + self.config.add_section("keyboard") + self.config.set("keyboard", "driver", "evdevDriver") + self.config.set("keyboard", "keyboardLayout", "desktop") - self.config.add_section('screen') - self.config.set('screen', 'driver', 'vcsaDriver') + self.config.add_section("screen") + self.config.set("screen", "driver", "vcsaDriver") - self.config.add_section('general') - self.config.set('general', 'debug_mode', 'Off') + self.config.add_section("general") + self.config.set("general", "debug_mode", "Off") return True diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/set_punctuation_level.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/set_punctuation_level.py index 5e3eef24..1d1b6124 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/set_punctuation_level.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/set_punctuation_level.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,34 +21,34 @@ class command(config_command): return "Set punctuation verbosity level" def run(self): - current_level = self.get_setting('general', 'punctuationLevel', 'some') + current_level = self.get_setting("general", "punctuationLevel", "some") # Present current level level_descriptions = { - 'none': 'None - no punctuation spoken', - 'some': 'Some - basic punctuation only', - 'most': 'Most - detailed punctuation', - 'all': 'All - every punctuation mark' + "none": "None - no punctuation spoken", + "some": "Some - basic punctuation only", + "most": "Most - detailed punctuation", + "all": "All - every punctuation mark", } - current_description = level_descriptions.get(current_level, 'Unknown') + current_description = level_descriptions.get(current_level, "Unknown") self.present_text(f"Current punctuation level: {current_description}") # Cycle through the four levels - levels = ['none', 'some', 'most', 'all'] + levels = ["none", "some", "most", "all"] try: current_index = levels.index(current_level) next_index = (current_index + 1) % len(levels) new_level = levels[next_index] except ValueError: - new_level = 'some' # Default to some + new_level = "some" # Default to some - success = self.set_setting('general', 'punctuationLevel', new_level) + success = self.set_setting("general", "punctuationLevel", new_level) if success: new_description = level_descriptions[new_level] self.present_text(f"Punctuation level set to: {new_description}") - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to change punctuation level") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/toggle_debug.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/toggle_debug.py index f4504699..2f50a329 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/toggle_debug.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/general/toggle_debug.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,30 +21,33 @@ class command(config_command): return "Toggle debug mode" def run(self): - current_level = self.get_setting('general', 'debug_level', '0') + current_level = self.get_setting("general", "debug_level", "0") # Present current debug level - if current_level == '0': + if current_level == "0": self.present_text("Current debug mode: disabled") - new_level = '1' + new_level = "1" state_text = "enabled" else: self.present_text(f"Current debug level: {current_level}") - new_level = '0' + new_level = "0" state_text = "disabled" - success = self.set_setting('general', 'debug_level', new_level) + success = self.set_setting("general", "debug_level", new_level) if success: self.present_text(f"Debug mode {state_text}") - if new_level != '0': - debug_mode = self.get_setting('general', 'debug_mode', 'File') - if debug_mode == 'File': + if new_level != "0": + debug_mode = self.get_setting("general", "debug_mode", "File") + if debug_mode == "File": self.present_text( - "Debug output will be written to log file") + "Debug output will be written to log file" + ) else: - self.present_text("Debug output will be printed to console") - self.play_sound('Accept') + self.present_text( + "Debug output will be printed to console" + ) + self.play_sound("Accept") else: self.present_text("Failed to change debug mode") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/select_layout.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/select_layout.py index c147039f..0df0e590 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/select_layout.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/select_layout.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -22,20 +22,19 @@ class command(config_command): def run(self): current_layout = self.get_setting( - 'keyboard', 'keyboardLayout', 'desktop') + "keyboard", "keyboardLayout", "desktop" + ) # Present current layout self.present_text(f"Current keyboard layout: {current_layout}") # Find available keyboard layouts - keyboard_path = '/etc/fenrirscreenreader/keyboard' + keyboard_path = "/etc/fenrirscreenreader/keyboard" if not os.path.isdir(keyboard_path): # Development path keyboard_path = os.path.join( - os.path.dirname( - self.settings_file), - '..', - 'keyboard') + os.path.dirname(self.settings_file), "..", "keyboard" + ) available_layouts = self.get_available_layouts(keyboard_path) @@ -49,19 +48,22 @@ class command(config_command): # Current layout not found, use first available new_layout = available_layouts[0] - success = self.set_setting('keyboard', 'keyboardLayout', new_layout) + success = self.set_setting( + "keyboard", "keyboardLayout", new_layout + ) if success: self.present_text(f"Keyboard layout changed to: {new_layout}") self.present_text( - "Please restart Fenrir for this change to take effect.") - self.play_sound('Accept') + "Please restart Fenrir for this change to take effect." + ) + self.play_sound("Accept") else: self.present_text("Failed to change keyboard layout") - self.play_sound('Error') + self.play_sound("Error") else: self.present_text("Only default keyboard layout is available") - self.play_sound('Cancel') + self.play_sound("Cancel") def get_available_layouts(self, keyboard_path): """Find available keyboard layout files""" @@ -70,7 +72,7 @@ class command(config_command): if os.path.isdir(keyboard_path): try: for file in os.listdir(keyboard_path): - if file.endswith('.conf') and not file.startswith('.'): + if file.endswith(".conf") and not file.startswith("."): layout_name = file[:-5] # Remove .conf extension layouts.append(layout_name) except Exception: @@ -78,6 +80,6 @@ class command(config_command): # Ensure we have at least the default layouts if not layouts: - layouts = ['desktop', 'laptop'] + layouts = ["desktop", "laptop"] return sorted(layouts) diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/set_char_echo.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/set_char_echo.py index 250d0ac0..ef527a5d 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/set_char_echo.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/set_char_echo.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,33 +21,35 @@ class command(config_command): return "Set character echo mode" def run(self): - current_mode = self.get_setting('keyboard', 'charEchoMode', '1') + current_mode = self.get_setting("keyboard", "charEchoMode", "1") # Present current mode mode_descriptions = { - '0': 'None - no character echo', - '1': 'Always - echo all typed characters', - '2': 'Caps Lock - echo only when caps lock is on' + "0": "None - no character echo", + "1": "Always - echo all typed characters", + "2": "Caps Lock - echo only when caps lock is on", } - current_description = mode_descriptions.get(current_mode, 'Unknown') - self.present_text(f"Current character echo mode: {current_description}") + current_description = mode_descriptions.get(current_mode, "Unknown") + self.present_text( + f"Current character echo mode: {current_description}" + ) # Cycle through the three modes - modes = ['0', '1', '2'] + modes = ["0", "1", "2"] try: current_index = modes.index(current_mode) next_index = (current_index + 1) % len(modes) new_mode = modes[next_index] except ValueError: - new_mode = '1' # Default to always + new_mode = "1" # Default to always - success = self.set_setting('keyboard', 'charEchoMode', new_mode) + success = self.set_setting("keyboard", "charEchoMode", new_mode) if success: new_description = mode_descriptions[new_mode] self.present_text(f"Character echo mode set to: {new_description}") - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to change character echo mode") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_grab_devices.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_grab_devices.py index 22c6736a..42297d22 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_grab_devices.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_grab_devices.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,21 +21,24 @@ class command(config_command): return "Toggle exclusive keyboard access" def run(self): - current_state = self.getBooleanSetting('keyboard', 'grabDevices', True) - new_state = self.toggleBooleanSetting('keyboard', 'grabDevices') + current_state = self.getBooleanSetting("keyboard", "grabDevices", True) + new_state = self.toggleBooleanSetting("keyboard", "grabDevices") if new_state != current_state: state_text = "enabled" if new_state else "disabled" self.present_text(f"Exclusive keyboard access {state_text}") if new_state: self.present_text( - "Fenrir will have exclusive control of keyboard input") + "Fenrir will have exclusive control of keyboard input" + ) else: self.present_text( - "Fenrir will share keyboard input with other applications") + "Fenrir will share keyboard input with other applications" + ) self.present_text( - "Please restart Fenrir for this change to take effect") - self.play_sound('Accept') + "Please restart Fenrir for this change to take effect" + ) + self.play_sound("Accept") else: self.present_text("Failed to change keyboard grab setting") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_word_echo.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_word_echo.py index de537806..712c3e95 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_word_echo.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/keyboard/toggle_word_echo.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,8 +21,8 @@ class command(config_command): return "Toggle word echo when pressing space" def run(self): - current_state = self.getBooleanSetting('keyboard', 'wordEcho', False) - new_state = self.toggleBooleanSetting('keyboard', 'wordEcho') + current_state = self.getBooleanSetting("keyboard", "wordEcho", False) + new_state = self.toggleBooleanSetting("keyboard", "wordEcho") if new_state != current_state: state_text = "enabled" if new_state else "disabled" @@ -31,8 +31,9 @@ class command(config_command): self.present_text("Words will be spoken when you press space") else: self.present_text( - "Words will not be spoken when you press space") - self.play_sound('Accept') + "Words will not be spoken when you press space" + ) + self.play_sound("Accept") else: self.present_text("Failed to change word echo setting") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/backup_config.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/backup_config.py index 89f8a702..e85f1fd9 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/backup_config.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/backup_config.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -27,8 +27,14 @@ class command(config_command): if success: # Force the message to be queued and spoken - self.env['runtime']['OutputManager'].present_text( - "Configuration backup created successfully", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + "Configuration backup created successfully", + interrupt=False, + flush=False, + ) else: - self.env['runtime']['OutputManager'].present_text( - "Failed to create configuration backup", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + "Failed to create configuration backup", + interrupt=False, + flush=False, + ) diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reload_config.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reload_config.py index 38c3c271..70265e7a 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reload_config.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reload_config.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -27,7 +27,7 @@ class command(config_command): if success: self.present_text("Configuration reloaded successfully") - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to reload configuration") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reset_defaults.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reset_defaults.py index 00c8cc12..87e4a1ad 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reset_defaults.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/reset_defaults.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 +import importlib.util +import os +import shutil + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util -import shutil - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -30,8 +30,9 @@ class command(config_command): if not backupSuccess: self.present_text( "Failed to create backup. Reset cancelled for safety.", - interrupt=False) - self.play_sound('Error') + interrupt=False, + ) + self.play_sound("Error") return # Find default configuration file @@ -48,16 +49,21 @@ class command(config_command): self.present_text( "Configuration reset to defaults successfully", interrupt=False, - flush=False) + flush=False, + ) self.present_text( "Please restart Fenrir for all changes to take effect", interrupt=False, - flush=False) + flush=False, + ) except Exception as e: self.present_text( f"Failed to reset configuration: { - str(e)}", interrupt=False, flush=False) + str(e)}", + interrupt=False, + flush=False, + ) else: # Manually create basic default configuration self.create_basic_defaults() @@ -65,24 +71,24 @@ class command(config_command): def find_default_config(self): """Find the default configuration file""" possible_paths = [ - '/usr/share/fenrirscreenreader/config/settings/settings.conf', - '/etc/fenrirscreenreader/settings/settings.conf.default', + "/usr/share/fenrirscreenreader/config/settings/settings.conf", + "/etc/fenrirscreenreader/settings/settings.conf.default", os.path.join( - os.path.dirname( - self.settings_file), - 'settings.conf.default'), + os.path.dirname(self.settings_file), "settings.conf.default" + ), # Development path os.path.join( os.path.dirname(__file__), - '..', - '..', - '..', - '..', - '..', - '..', - 'config', - 'settings', - 'settings.conf') + "..", + "..", + "..", + "..", + "..", + "..", + "config", + "settings", + "settings.conf", + ), ] for path in possible_paths: @@ -97,60 +103,65 @@ class command(config_command): self.config.clear() # Basic speech defaults - self.config['speech'] = { - 'enabled': 'True', - 'driver': 'speechdDriver', - 'rate': '0.5', - 'pitch': '0.5', - 'volume': '1.0', - 'autoReadIncoming': 'True' + self.config["speech"] = { + "enabled": "True", + "driver": "speechdDriver", + "rate": "0.5", + "pitch": "0.5", + "volume": "1.0", + "autoReadIncoming": "True", } # Basic sound defaults - self.config['sound'] = { - 'enabled': 'True', - 'driver': 'genericDriver', - 'theme': 'default', - 'volume': '0.7' + self.config["sound"] = { + "enabled": "True", + "driver": "genericDriver", + "theme": "default", + "volume": "0.7", } # Basic keyboard defaults - self.config['keyboard'] = { - 'driver': 'evdevDriver', - 'device': 'ALL', - 'keyboardLayout': 'desktop', - 'charEchoMode': '1', - 'wordEcho': 'False', - 'charDeleteEcho': 'True' + self.config["keyboard"] = { + "driver": "evdevDriver", + "device": "ALL", + "keyboardLayout": "desktop", + "charEchoMode": "1", + "wordEcho": "False", + "charDeleteEcho": "True", } # Basic screen defaults - self.config['screen'] = { - 'driver': 'vcsaDriver', - 'encoding': 'auto' + self.config["screen"] = { + "driver": "vcsaDriver", + "encoding": "auto", } # Basic general defaults - self.config['general'] = { - 'punctuationLevel': 'some', - 'debug_level': '0', - 'numberOfClipboards': '50' + self.config["general"] = { + "punctuationLevel": "some", + "debug_level": "0", + "numberOfClipboards": "50", } # Write the configuration - with open(self.settings_file, 'w') as configfile: + with open(self.settings_file, "w") as configfile: self.config.write(configfile) self.present_text( "Basic default configuration created", interrupt=False, - flush=False) + flush=False, + ) self.present_text( "Please restart Fenrir for changes to take effect", interrupt=False, - flush=False) + flush=False, + ) except Exception as e: self.present_text( f"Failed to create default configuration: { - str(e)}", interrupt=False, flush=False) + str(e)}", + interrupt=False, + flush=False, + ) diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/revert_to_saved.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/revert_to_saved.py index 5ba3924e..6acdb9a3 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/revert_to_saved.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/revert_to_saved.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,46 +17,59 @@ class command(): return "Discard temporary changes and revert to saved settings" def run(self): - self.env['runtime']['OutputManager'].present_text( - "Reverting to saved configuration...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Reverting to saved configuration...", interrupt=True + ) try: # Reload settings from file, discarding runtime changes - SettingsManager = self.env['runtime']['SettingsManager'] + SettingsManager = self.env["runtime"]["SettingsManager"] SettingsManager.load_settings() # Reinitialize speech system with restored settings - if 'SpeechDriver' in self.env['runtime']: + if "SpeechDriver" in self.env["runtime"]: try: - SpeechDriver = self.env['runtime']['SpeechDriver'] + SpeechDriver = self.env["runtime"]["SpeechDriver"] SpeechDriver.shutdown() SpeechDriver.initialize(self.env) except Exception as e: print( - f'revert_to_saved SpeechDriver: Error reinitializing speech driver: { - str(e)}') + f"revert_to_saved SpeechDriver: Error reinitializing speech driver: { + str(e)}" + ) # Reinitialize sound system with restored settings - if 'sound_driver' in self.env['runtime']: + if "sound_driver" in self.env["runtime"]: try: - sound_driver = self.env['runtime']['sound_driver'] + sound_driver = self.env["runtime"]["sound_driver"] sound_driver.shutdown() sound_driver.initialize(self.env) except Exception as e: print( - f'revert_to_saved sound_driver: Error reinitializing sound driver: { - str(e)}') + f"revert_to_saved sound_driver: Error reinitializing sound driver: { + str(e)}" + ) - self.env['runtime']['OutputManager'].present_text( - "Successfully reverted to saved settings", interrupt=False, flush=False) - self.env['runtime']['OutputManager'].present_text( - "All temporary changes have been discarded", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + "Successfully reverted to saved settings", + interrupt=False, + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + "All temporary changes have been discarded", + interrupt=False, + flush=False, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Error reverting settings: {str(e)}", interrupt=False, flush=False) - self.env['runtime']['OutputManager'].present_text( - "You may need to restart Fenrir", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Error reverting settings: {str(e)}", + interrupt=False, + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + "You may need to restart Fenrir", interrupt=False, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_config.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_config.py index 56bce4e3..44ab18d0 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_config.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_config.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -28,12 +28,12 @@ class command(config_command): self.reload_config() # Write the configuration file - with open(self.settings_file, 'w') as configfile: + with open(self.settings_file, "w") as configfile: self.config.write(configfile) self.present_text("Configuration saved successfully") - self.play_sound('Accept') + self.play_sound("Accept") except Exception as e: self.present_text(f"Failed to save configuration: {str(e)}") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_session_settings.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_session_settings.py index 79a1d91b..ed6e98a3 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_session_settings.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/save_session_settings.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -17,22 +17,33 @@ class command(): return "Save current session settings to configuration file" def run(self): - self.env['runtime']['OutputManager'].present_text( - "Saving current session settings to configuration file...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Saving current session settings to configuration file...", + interrupt=True, + ) try: # This calls the settings manager's save method which writes # current runtime settings to file - self.env['runtime']['SettingsManager'].save_settings() + self.env["runtime"]["SettingsManager"].save_settings() - self.env['runtime']['OutputManager'].present_text( - "Session settings saved successfully!", interrupt=False, flush=False) - self.env['runtime']['OutputManager'].present_text( - "All temporary changes are now permanent.", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + "Session settings saved successfully!", + interrupt=False, + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + "All temporary changes are now permanent.", + interrupt=False, + flush=False, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Failed to save settings: {str(e)}", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Failed to save settings: {str(e)}", + interrupt=False, + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/show_unsaved_changes.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/show_unsaved_changes.py index 6dfd8b07..8ac8b27e 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/show_unsaved_changes.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/management/show_unsaved_changes.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -from fenrirscreenreader.core.i18n import _ - import configparser +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -19,27 +19,31 @@ class command(): return "Show temporary changes not yet saved to file" def run(self): - self.env['runtime']['OutputManager'].present_text( - "Checking for unsaved changes...", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Checking for unsaved changes...", interrupt=True + ) try: # Read the current config file - settings_file = self.env['runtime']['SettingsManager'].settings_file + settings_file = self.env["runtime"][ + "SettingsManager" + ].settings_file file_config = configparser.ConfigParser(interpolation=None) file_config.read(settings_file) # Compare with runtime settings - runtime_settings = self.env['runtime']['SettingsManager'].settings + runtime_settings = self.env["runtime"]["SettingsManager"].settings changes = [] # Check speech settings specifically speech_sections = [ - 'speech', - 'sound', - 'keyboard', - 'screen', - 'general'] + "speech", + "sound", + "keyboard", + "screen", + "general", + ] for section in speech_sections: if section in runtime_settings and section in file_config: @@ -52,31 +56,40 @@ class command(): if runtime_value != file_value: changes.append( - f"{section}.{option}: {file_value} → {runtime_value}") + f"{section}.{option}: {file_value} → {runtime_value}" + ) if changes: - self.env['runtime']['OutputManager'].present_text( - f"found {len(changes)} unsaved changes:", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"found {len(changes)} unsaved changes:", interrupt=True + ) for change in changes[:5]: # Limit to first 5 changes - self.env['runtime']['OutputManager'].present_text( - change, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + change, interrupt=True + ) if len(changes) > 5: - self.env['runtime']['OutputManager'].present_text( - f"... and {len(changes) - 5} more changes", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"... and {len(changes) - 5} more changes", + interrupt=True, + ) - self.env['runtime']['OutputManager'].present_text( - "Use save command to make these changes permanent", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["runtime"]["OutputManager"].present_text( + "Use save command to make these changes permanent", + interrupt=True, + ) + self.env["runtime"]["OutputManager"].play_sound("Accept") else: - self.env['runtime']['OutputManager'].present_text( - "No unsaved changes found", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Cancel') + self.env["runtime"]["OutputManager"].present_text( + "No unsaved changes found", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Cancel") except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Error checking for changes: {str(e)}", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Error') + self.env["runtime"]["OutputManager"].present_text( + f"Error checking for changes: {str(e)}", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Error") def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/select_driver.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/select_driver.py index 4cdc3b9e..59ad6793 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/select_driver.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/select_driver.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,37 +21,39 @@ class command(config_command): return "Select screen driver" def run(self): - current_driver = self.get_setting('screen', 'driver', 'vcsaDriver') + current_driver = self.get_setting("screen", "driver", "vcsaDriver") # Present current driver driver_descriptions = { - 'vcsaDriver': 'VCSA Driver - Linux TTY console access', - 'ptyDriver': 'PTY Driver - terminal emulation', - 'dummyDriver': 'Dummy Driver - for testing only', - 'debugDriver': 'Debug Driver - development/debugging' + "vcsaDriver": "VCSA Driver - Linux TTY console access", + "ptyDriver": "PTY Driver - terminal emulation", + "dummyDriver": "Dummy Driver - for testing only", + "debugDriver": "Debug Driver - development/debugging", } current_description = driver_descriptions.get( - current_driver, 'Unknown driver') + current_driver, "Unknown driver" + ) self.present_text(f"Current screen driver: {current_description}") # Cycle through the available drivers - drivers = ['vcsaDriver', 'ptyDriver', 'dummyDriver', 'debugDriver'] + drivers = ["vcsaDriver", "ptyDriver", "dummyDriver", "debugDriver"] try: current_index = drivers.index(current_driver) next_index = (current_index + 1) % len(drivers) new_driver = drivers[next_index] except ValueError: - new_driver = 'vcsaDriver' # Default to VCSA + new_driver = "vcsaDriver" # Default to VCSA - success = self.set_setting('screen', 'driver', new_driver) + success = self.set_setting("screen", "driver", new_driver) if success: new_description = driver_descriptions[new_driver] self.present_text(f"Screen driver changed to: {new_description}") self.present_text( - "Please restart Fenrir for this change to take effect.") - self.play_sound('Accept') + "Please restart Fenrir for this change to take effect." + ) + self.play_sound("Accept") else: self.present_text("Failed to change screen driver") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/set_encoding.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/set_encoding.py index c0b2bee3..448cee37 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/set_encoding.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/screen/set_encoding.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,30 +21,31 @@ class command(config_command): return "Set screen text encoding" def run(self): - current_encoding = self.get_setting('screen', 'encoding', 'auto') + current_encoding = self.get_setting("screen", "encoding", "auto") # Present current encoding self.present_text(f"Current screen encoding: {current_encoding}") # Cycle through available encodings - encodings = ['auto', 'utf-8', 'cp1252', 'iso-8859-1'] + encodings = ["auto", "utf-8", "cp1252", "iso-8859-1"] try: current_index = encodings.index(current_encoding) next_index = (current_index + 1) % len(encodings) new_encoding = encodings[next_index] except ValueError: - new_encoding = 'auto' # Default to auto + new_encoding = "auto" # Default to auto - success = self.set_setting('screen', 'encoding', new_encoding) + success = self.set_setting("screen", "encoding", new_encoding) if success: self.present_text(f"Screen encoding set to: {new_encoding}") - if new_encoding == 'auto': + if new_encoding == "auto": self.present_text( - "Fenrir will automatically detect text encoding") + "Fenrir will automatically detect text encoding" + ) else: self.present_text(f"Fenrir will use {new_encoding} encoding") - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to change screen encoding") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/adjust_volume.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/adjust_volume.py index 5f065cbc..f483a87a 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/adjust_volume.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/adjust_volume.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,31 +21,33 @@ class command(config_command): return "Adjust sound volume" def run(self): - current_volume = self.getFloatSetting('sound', 'volume', 0.7) + current_volume = self.getFloatSetting("sound", "volume", 0.7) # Present current volume volume_percent = int(current_volume * 100) self.present_text(f"Current sound volume: {volume_percent} percent") # Adjust volume by 10% - new_volume = self.adjustFloatSetting('sound', 'volume', 0.1, 0.0, 1.0) + new_volume = self.adjustFloatSetting("sound", "volume", 0.1, 0.0, 1.0) if new_volume != current_volume: new_percent = int(new_volume * 100) self.present_text( - f"Sound volume set to {new_percent} percent", - interrupt=False) - self.play_sound('Accept') + f"Sound volume set to {new_percent} percent", interrupt=False + ) + self.play_sound("Accept") else: # If we hit the maximum, try decreasing instead new_volume = self.adjustFloatSetting( - 'sound', 'volume', -0.1, 0.0, 1.0) + "sound", "volume", -0.1, 0.0, 1.0 + ) if new_volume != current_volume: new_percent = int(new_volume * 100) self.present_text( f"Sound volume set to {new_percent} percent", - interrupt=False) - self.play_sound('Accept') + interrupt=False, + ) + self.play_sound("Accept") else: self.present_text("Sound volume unchanged", interrupt=False) - self.play_sound('Cancel') + self.play_sound("Cancel") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_driver.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_driver.py index 81269896..3bc10bb1 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_driver.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_driver.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,27 +21,31 @@ class command(config_command): return "Select sound driver (genericDriver or gstreamerDriver)" def run(self): - current_driver = self.get_setting('sound', 'driver', 'genericDriver') + current_driver = self.get_setting("sound", "driver", "genericDriver") # Present current driver self.present_text(f"Current sound driver: {current_driver}") # Toggle between the two available drivers - if current_driver == 'genericDriver': - new_driver = 'gstreamerDriver' - driver_description = "GStreamer Driver - advanced multimedia framework" + if current_driver == "genericDriver": + new_driver = "gstreamerDriver" + driver_description = ( + "GStreamer Driver - advanced multimedia framework" + ) else: - new_driver = 'genericDriver' + new_driver = "genericDriver" driver_description = "Generic Driver - uses SOX for audio playback" - success = self.set_setting('sound', 'driver', new_driver) + success = self.set_setting("sound", "driver", new_driver) if success: self.present_text( - f"Sound driver changed to {new_driver}. {driver_description}") + f"Sound driver changed to {new_driver}. {driver_description}" + ) self.present_text( - "Please restart Fenrir for this change to take effect.") - self.play_sound('Accept') + "Please restart Fenrir for this change to take effect." + ) + self.play_sound("Accept") else: self.present_text("Failed to change sound driver") - self.play_sound('Error') + self.play_sound("Error") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_theme.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_theme.py index 65f2a170..be50a087 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_theme.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/select_theme.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,16 +21,16 @@ class command(config_command): return "Select sound theme" def run(self): - current_theme = self.get_setting('sound', 'theme', 'default') + current_theme = self.get_setting("sound", "theme", "default") # Present current theme self.present_text(f"Current sound theme: {current_theme}") # Look for available sound themes sound_paths = [ - '/usr/share/sounds', - '/usr/share/fenrirscreenreader/sounds', - os.path.expanduser('~/.local/share/fenrirscreenreader/sounds') + "/usr/share/sounds", + "/usr/share/fenrirscreenreader/sounds", + os.path.expanduser("~/.local/share/fenrirscreenreader/sounds"), ] available_themes = self.get_available_themes(sound_paths) @@ -45,29 +45,32 @@ class command(config_command): # Current theme not found in available themes, use first one new_theme = available_themes[0] - success = self.set_setting('sound', 'theme', new_theme) + success = self.set_setting("sound", "theme", new_theme) if success: self.present_text(f"Sound theme changed to: {new_theme}") - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to change sound theme") - self.play_sound('Error') + self.play_sound("Error") else: self.present_text("Only default sound theme is available") - self.play_sound('Cancel') + self.play_sound("Cancel") def get_available_themes(self, searchPaths): """Find available sound themes in the search paths""" - themes = ['default'] # Always include default + themes = ["default"] # Always include default for path in searchPaths: if os.path.isdir(path): try: for item in os.listdir(path): full_path = os.path.join(path, item) - if os.path.isdir( - full_path) and item != 'default' and item not in themes: + if ( + os.path.isdir(full_path) + and item != "default" + and item not in themes + ): # Check if it looks like a sound theme (contains # sound files) if self.is_valid_sound_theme(full_path): @@ -79,7 +82,7 @@ class command(config_command): def is_valid_sound_theme(self, themePath): """Check if a directory contains sound files""" - sound_extensions = ['.wav', '.ogg', '.mp3', '.flac'] + sound_extensions = [".wav", ".ogg", ".mp3", ".flac"] try: for file in os.listdir(themePath): if any(file.lower().endswith(ext) for ext in sound_extensions): diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/toggle_enabled.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/toggle_enabled.py index cd648e9f..51249c78 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/toggle_enabled.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/sound/toggle_enabled.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import importlib.util +import os + from fenrirscreenreader.core.i18n import _ -import os -import importlib.util - # Load base configuration class -_base_path = os.path.join(os.path.dirname(__file__), '..', 'config_base.py') +_base_path = os.path.join(os.path.dirname(__file__), "..", "config_base.py") _spec = importlib.util.spec_from_file_location("config_base", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) @@ -21,14 +21,14 @@ class command(config_command): return "Toggle sound output on or off" def run(self): - current_state = self.getBooleanSetting('sound', 'enabled', True) - new_state = self.toggleBooleanSetting('sound', 'enabled') + current_state = self.getBooleanSetting("sound", "enabled", True) + new_state = self.toggleBooleanSetting("sound", "enabled") if new_state != current_state: state_text = "enabled" if new_state else "disabled" self.present_text(f"Sound {state_text}") # Only play sound if we enabled sound if new_state: - self.play_sound('Accept') + self.play_sound("Accept") else: self.present_text("Failed to change sound setting") diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_pitch.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_pitch.py index 6ed85581..a215e79d 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_pitch.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_pitch.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,15 +20,18 @@ class command(): try: # Get current pitch current_pitch = float( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'pitch')) + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "pitch" + ) + ) except Exception as e: current_pitch = 0.5 # Present current pitch pitch_percent = int(current_pitch * 100) - self.env['runtime']['OutputManager'].present_text( - f"Current speech pitch: {pitch_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Current speech pitch: {pitch_percent} percent", interrupt=True + ) # Increase by 10%, wrap around if at max new_pitch = current_pitch + 0.1 @@ -36,13 +39,15 @@ class command(): new_pitch = 0.1 # Wrap to minimum # Apply the new pitch - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'pitch', str(new_pitch)) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "pitch", str(new_pitch) + ) new_percent = int(new_pitch * 100) - self.env['runtime']['OutputManager'].present_text( - f"Speech pitch set to {new_percent} percent", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["runtime"]["OutputManager"].present_text( + f"Speech pitch set to {new_percent} percent", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Accept") def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_rate.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_rate.py index 44c50714..68c4ca94 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_rate.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_rate.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,15 +20,18 @@ class command(): try: # Get current rate current_rate = float( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'rate')) + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "rate" + ) + ) except Exception as e: current_rate = 0.5 # Present current rate rate_percent = int(current_rate * 100) - self.env['runtime']['OutputManager'].present_text( - f"Current speech rate: {rate_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Current speech rate: {rate_percent} percent", interrupt=True + ) # Increase by 10%, wrap around if at max new_rate = current_rate + 0.1 @@ -36,12 +39,16 @@ class command(): new_rate = 0.1 # Wrap to minimum # Apply the new rate - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'rate', str(new_rate)) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "rate", str(new_rate) + ) new_percent = int(new_rate * 100) - self.env['runtime']['OutputManager'].present_text( - f"Speech rate set to {new_percent} percent", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Speech rate set to {new_percent} percent", + interrupt=False, + flush=False, + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_speech_rate.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_speech_rate.py index 3efd8b99..6f474d06 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_speech_rate.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_speech_rate.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,15 +19,16 @@ class command(): def run(self): try: # Get current rate from runtime settings (may be temporary) - SettingsManager = self.env['runtime']['SettingsManager'] - current_rate = float(SettingsManager.get_setting('speech', 'rate')) + SettingsManager = self.env["runtime"]["SettingsManager"] + current_rate = float(SettingsManager.get_setting("speech", "rate")) except Exception as e: current_rate = 0.5 # Present current rate rate_percent = int(current_rate * 100) - self.env['runtime']['OutputManager'].present_text( - f"Current speech rate: {rate_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Current speech rate: {rate_percent} percent", interrupt=True + ) # Increase by 10%, wrap around if at max new_rate = current_rate + 0.1 @@ -35,25 +36,28 @@ class command(): new_rate = 0.1 # Wrap to minimum # Apply ONLY to runtime - this is temporary until saved - SettingsManager = self.env['runtime']['SettingsManager'] - SettingsManager.settings['speech']['rate'] = str(new_rate) + SettingsManager = self.env["runtime"]["SettingsManager"] + SettingsManager.settings["speech"]["rate"] = str(new_rate) # Apply to speech system immediately for this session - if 'SpeechDriver' in self.env['runtime']: + if "SpeechDriver" in self.env["runtime"]: try: - self.env['runtime']['SpeechDriver'].set_rate(new_rate) + self.env["runtime"]["SpeechDriver"].set_rate(new_rate) except Exception as e: print( - f'adjust_speech_rate set_rate: Error setting speech rate: { - str(e)}') + f"adjust_speech_rate set_rate: Error setting speech rate: { + str(e)}" + ) new_percent = int(new_rate * 100) - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( f"Speech rate temporarily set to {new_percent} percent", interrupt=False, - flush=False) - self.env['runtime']['OutputManager'].present_text( - "Use save command to make permanent", interrupt=False, flush=False) + flush=False, + ) + self.env["runtime"]["OutputManager"].present_text( + "Use save command to make permanent", interrupt=False, flush=False + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_volume.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_volume.py index cd3ca596..64c0a48d 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_volume.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/adjust_volume.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -20,15 +20,18 @@ class command(): try: # Get current volume current_volume = float( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'volume')) + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "volume" + ) + ) except Exception as e: current_volume = 1.0 # Present current volume volume_percent = int(current_volume * 100) - self.env['runtime']['OutputManager'].present_text( - f"Current speech volume: {volume_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Current speech volume: {volume_percent} percent", interrupt=True + ) # Increase by 10%, wrap around if at max new_volume = current_volume + 0.1 @@ -36,13 +39,15 @@ class command(): new_volume = 0.1 # Wrap to minimum # Apply the new volume - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'volume', str(new_volume)) + self.env["runtime"]["SettingsManager"].set_setting( + "speech", "volume", str(new_volume) + ) new_percent = int(new_volume * 100) - self.env['runtime']['OutputManager'].present_text( - f"Speech volume set to {new_percent} percent", interrupt=True) - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["runtime"]["OutputManager"].present_text( + f"Speech volume set to {new_percent} percent", interrupt=True + ) + self.env["runtime"]["OutputManager"].play_sound("Accept") def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/show_current_settings.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/show_current_settings.py index 5f91f310..aee52b22 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/show_current_settings.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/fenrir/speech/show_current_settings.py @@ -3,7 +3,7 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -18,63 +18,81 @@ class command(): def run(self): # Get current speech settings - driver = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'driver') - module = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'module') - voice = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'voice') - rate = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'rate') - pitch = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'pitch') - volume = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'volume') - enabled = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'enabled') + driver = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "driver" + ) + module = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "module" + ) + voice = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "voice" + ) + rate = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "rate" + ) + pitch = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "pitch" + ) + volume = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "volume" + ) + enabled = self.env["runtime"]["SettingsManager"].get_setting( + "speech", "enabled" + ) - self.env['runtime']['OutputManager'].present_text( - "Current speech settings:", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Current speech settings:", interrupt=True + ) # Present all settings - self.env['runtime']['OutputManager'].present_text( - f"Speech enabled: {enabled}", interrupt=True) - self.env['runtime']['OutputManager'].present_text( - f"Driver: {driver}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Speech enabled: {enabled}", interrupt=True + ) + self.env["runtime"]["OutputManager"].present_text( + f"Driver: {driver}", interrupt=True + ) if module: - self.env['runtime']['OutputManager'].present_text( - f"Module: {module}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Module: {module}", interrupt=True + ) if voice: - self.env['runtime']['OutputManager'].present_text( - f"Voice: {voice}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Voice: {voice}", interrupt=True + ) try: rate_percent = int(float(rate) * 100) - self.env['runtime']['OutputManager'].present_text( - f"Rate: {rate_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Rate: {rate_percent} percent", interrupt=True + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Rate: {rate}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Rate: {rate}", interrupt=True + ) try: pitch_percent = int(float(pitch) * 100) - self.env['runtime']['OutputManager'].present_text( - f"Pitch: {pitch_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Pitch: {pitch_percent} percent", interrupt=True + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Pitch: {pitch}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Pitch: {pitch}", interrupt=True + ) try: volume_percent = int(float(volume) * 100) - self.env['runtime']['OutputManager'].present_text( - f"Volume: {volume_percent} percent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Volume: {volume_percent} percent", interrupt=True + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Volume: {volume}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Volume: {volume}", interrupt=True + ) - self.env['runtime']['OutputManager'].play_sound('Accept') + self.env["runtime"]["OutputManager"].play_sound("Accept") def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/open.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/open.py index 35ea7ce7..087f99c0 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/open.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/open.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/save.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/save.py index dd71e6bc..1d0fd1c7 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/save.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/file/save.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open save', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open save", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/replace.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/replace.py index c5ffbfda..248aa17c 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/replace.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/replace.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run replace macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run replace macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/search.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/search.py index c66a25b3..6b6b7f23 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/search.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/search.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run search macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run search macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/test.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/test.py index 8e4ff2a1..3b7ae543 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/test.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mc/search/test.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the date') + return _("presents the date") def run(self): - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) # get the time formatted date_string = datetime.datetime.strftime( - datetime.datetime.now(), date_format) + datetime.datetime.now(), date_format + ) # 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) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/issue.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/issue.py index 5a705fcc..8bf7f7c3 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/issue.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/issue.py @@ -2,29 +2,34 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment - self.key_macro = [[1, 'KEY_LEFTCTRL'], [1, 'KEY_G'], [ - 0.05, 'sleep'], [0, 'KEY_G'], [0, 'KEY_LEFTCTRL']] + self.key_macro = [ + [1, "KEY_LEFTCTRL"], + [1, "KEY_G"], + [0.05, "sleep"], + [0, "KEY_G"], + [0, "KEY_LEFTCTRL"], + ] def shutdown(self): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['InputManager'].send_keys(self.key_macro) + self.env["runtime"]["InputManager"].send_keys(self.key_macro) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/open.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/open.py index 609776b8..f34fabe6 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/open.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/open.py @@ -2,36 +2,36 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment self.macro = [ - [ - 1, 'KEY_LEFTSHIFT'], [ - 1, 'KEY_LEFTCTRL'], [ - 1, 'KEY_N'], [ - 0.05, 'SLEEP'], [ - 0, 'KEY_N'], [ - 0, 'KEY_LEFTCTRL'], [ - 0, 'KEY_LEFTSHIFT']] + [1, "KEY_LEFTSHIFT"], + [1, "KEY_LEFTCTRL"], + [1, "KEY_N"], + [0.05, "SLEEP"], + [0, "KEY_N"], + [0, "KEY_LEFTCTRL"], + [0, "KEY_LEFTSHIFT"], + ] def shutdown(self): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['InputManager'].send_keys(self.macro) + self.env["runtime"]["InputManager"].send_keys(self.macro) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/save.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/save.py index dd71e6bc..1d0fd1c7 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/save.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/file/save.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open save', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open save", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/replace.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/replace.py index c5ffbfda..248aa17c 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/replace.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/replace.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run replace macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run replace macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/search.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/search.py index c66a25b3..6b6b7f23 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/search.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/search.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run search macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run search macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/test.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/test.py index 8e4ff2a1..3b7ae543 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/test.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/mutt/search/test.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the date') + return _("presents the date") def run(self): - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) # get the time formatted date_string = datetime.datetime.strftime( - datetime.datetime.now(), date_format) + datetime.datetime.now(), date_format + ) # 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) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/Help/about_nano.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/Help/about_nano.py index a5eeda40..fb077565 100755 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/Help/about_nano.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/Help/about_nano.py @@ -5,17 +5,19 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment - self.key_macro = [[1, 'KEY_LEFTCTRL'], - [1, 'KEY_G'], - [0.05, 'SLEEP'], - [0, 'KEY_G'], - [0, 'KEY_LEFTCTRL']] + self.key_macro = [ + [1, "KEY_LEFTCTRL"], + [1, "KEY_G"], + [0.05, "SLEEP"], + [0, "KEY_G"], + [0, "KEY_LEFTCTRL"], + ] def shutdown(self): pass @@ -24,12 +26,15 @@ class command(): return "Learn about the Nano text editor." def run(self): - self.env['runtime']['OutputManager'].present_text( - "Okay, loading the information about Nano.", interrupt=True) - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: - self.env['runtime']['InputManager'].send_keys(self.key_macro) - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: - self.env['runtime']['ByteManager'].send_bytes(self.byteMakro) + self.env["runtime"]["OutputManager"].present_text( + "Okay, loading the information about Nano.", interrupt=True + ) + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: + self.env["runtime"]["InputManager"].send_keys(self.key_macro) + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: + self.env["runtime"]["ByteManager"].send_bytes(self.byteMakro) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/open.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/open.py index 35ea7ce7..087f99c0 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/open.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/open.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/save.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/save.py index 604ee4a0..1d5b4796 100755 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/save.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/file/save.py @@ -5,17 +5,19 @@ from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass def initialize(self, environment): self.env = environment - self.key_macro = [[1, 'KEY_LEFTCTRL'], - [1, 'KEY_S'], - [0.05, 'SLEEP'], - [0, 'KEY_S'], - [0, 'KEY_LEFTCTRL']] + self.key_macro = [ + [1, "KEY_LEFTCTRL"], + [1, "KEY_S"], + [0.05, "SLEEP"], + [0, "KEY_S"], + [0, "KEY_LEFTCTRL"], + ] def shutdown(self): pass @@ -24,12 +26,15 @@ class command(): return "Save your work." def run(self): - self.env['runtime']['OutputManager'].present_text( - "Okay, you will now be asked to save your work.", interrupt=True) - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: - self.env['runtime']['InputManager'].send_keys(self.key_macro) - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: - self.env['runtime']['ByteManager'].send_bytes(self.byteMakro) + self.env["runtime"]["OutputManager"].present_text( + "Okay, you will now be asked to save your work.", interrupt=True + ) + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: + self.env["runtime"]["InputManager"].send_keys(self.key_macro) + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: + self.env["runtime"]["ByteManager"].send_bytes(self.byteMakro) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/replace.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/replace.py index c5ffbfda..248aa17c 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/replace.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/replace.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run replace macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run replace macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/search.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/search.py index c66a25b3..6b6b7f23 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/search.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/search.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run search macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run search macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/test.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/test.py index 8e4ff2a1..3b7ae543 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/test.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/nano/search/test.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the date') + return _("presents the date") def run(self): - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) # get the time formatted date_string = datetime.datetime.strftime( - datetime.datetime.now(), date_format) + datetime.datetime.now(), date_format + ) # 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) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/open.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/open.py index 35ea7ce7..087f99c0 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/open.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/open.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/save.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/save.py index dd71e6bc..1d0fd1c7 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/save.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/file/save.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run open save', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run open save", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/replace.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/replace.py index c5ffbfda..248aa17c 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/replace.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/replace.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run replace macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run replace macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/search.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/search.py index c66a25b3..6b6b7f23 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/search.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/search.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -19,11 +19,12 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - self.env['runtime']['OutputManager'].present_text( - 'ok i run search macro', interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "ok i run search macro", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/test.py b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/test.py index 8e4ff2a1..3b7ae543 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/test.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/KEY/vim/search/test.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from fenrirscreenreader.core.i18n import _ +# By Chrys, Storm Dragon, and contributors. import datetime +from fenrirscreenreader.core.i18n import _ -class command(): + +class command: def __init__(self): pass @@ -20,20 +20,23 @@ class command(): pass def get_description(self): - return _('presents the date') + return _("presents the date") def run(self): - date_format = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'date_format') + date_format = self.env["runtime"]["SettingsManager"].get_setting( + "general", "date_format" + ) # get the time formatted date_string = datetime.datetime.strftime( - datetime.datetime.now(), date_format) + datetime.datetime.now(), date_format + ) # 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) + self.env["runtime"]["OutputManager"].present_text( + date_string, sound_icon="", interrupt=True + ) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/commands/vmenu-profiles/template.py b/src/fenrirscreenreader/commands/vmenu-profiles/template.py index 6b2ba8bb..91c556d2 100644 --- a/src/fenrirscreenreader/commands/vmenu-profiles/template.py +++ b/src/fenrirscreenreader/commands/vmenu-profiles/template.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core.i18n import _ -class command(): +class command: def __init__(self): pass @@ -24,13 +24,15 @@ class command(): pass def get_description(self): - return 'No description found' + return "No description found" def run(self): - if self.env['runtime']['InputManager'].get_shortcut_type() in ['KEY']: - self.env['runtime']['InputManager'].send_keys(self.key_macro) - elif self.env['runtime']['InputManager'].get_shortcut_type() in ['BYTE']: - self.env['runtime']['ByteManager'].send_bytes(self.byteMakro) + if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]: + self.env["runtime"]["InputManager"].send_keys(self.key_macro) + elif self.env["runtime"]["InputManager"].get_shortcut_type() in [ + "BYTE" + ]: + self.env["runtime"]["ByteManager"].send_bytes(self.byteMakro) def set_callback(self, callback): pass diff --git a/src/fenrirscreenreader/core/applicationManager.py b/src/fenrirscreenreader/core/applicationManager.py index b6639fc6..14f7d426 100644 --- a/src/fenrirscreenreader/core/applicationManager.py +++ b/src/fenrirscreenreader/core/applicationManager.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class ApplicationManager(): +class ApplicationManager: def __init__(self): pass @@ -18,20 +18,23 @@ class ApplicationManager(): pass def get_current_application(self): - curr_app = self.env['screen']['new_application'].upper() + curr_app = self.env["screen"]["new_application"].upper() if not curr_app: - curr_app = 'DEFAULT' - if curr_app == '': - curr_app = 'DEFAULT' + curr_app = "DEFAULT" + if curr_app == "": + curr_app = "DEFAULT" return curr_app def get_prev_application(self): - prev_app = self.env['screen']['oldApplication'].upper() + prev_app = self.env["screen"]["oldApplication"].upper() if not prev_app: - prev_app = 'DEFAULT' - if prev_app == '': - prev_app = 'DEFAULT' + prev_app = "DEFAULT" + if prev_app == "": + prev_app = "DEFAULT" return prev_app def is_application_change(self): - return self.env['screen']['oldApplication'] != self.env['screen']['new_application'] + return ( + self.env["screen"]["oldApplication"] + != self.env["screen"]["new_application"] + ) diff --git a/src/fenrirscreenreader/core/attributeManager.py b/src/fenrirscreenreader/core/attributeManager.py index d4ad5ba9..706ec184 100644 --- a/src/fenrirscreenreader/core/attributeManager.py +++ b/src/fenrirscreenreader/core/attributeManager.py @@ -2,18 +2,19 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +from collections import Counter from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ -from collections import Counter -class AttributeManager(): +class AttributeManager: def __init__(self): self.currAttributes = None self.prevAttributes = None - self.currAttributeDelta = '' + self.currAttributeDelta = "" self.currAttributeCursor = None self.prefAttributeCursor = None self.init_default_attributes() @@ -58,7 +59,7 @@ class AttributeManager(): return self.currAttributeDelta def reset_attribute_delta(self): - self.currAttributeDelta = '' + self.currAttributeDelta = "" def set_attribute_delta(self, currAttributeDelta): self.currAttributeDelta = currAttributeDelta @@ -92,10 +93,11 @@ class AttributeManager(): try: return self.defaultAttributes[0] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'AttributeManager get_attribute_by_xy: Error accessing default attributes: ' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "AttributeManager get_attribute_by_xy: Error accessing default attributes: " + + str(e), + debug.DebugLevel.ERROR, + ) return None def append_default_attributes(self, attribute): @@ -107,18 +109,20 @@ class AttributeManager(): def init_default_attributes(self): self.defaultAttributes = [None] - self.defaultAttributes.append([ - 'default', # fg - 'default', # bg - False, # bold - False, # italics - False, # underscore - False, # strikethrough - False, # reverse - False, # blink - 'default', # fontsize - 'default' # fontfamily - ]) # end attribute + self.defaultAttributes.append( + [ + "default", # fg + "default", # bg + False, # bold + False, # italics + False, # underscore + False, # strikethrough + False, # reverse + False, # blink + "default", # fontsize + "default", # fontfamily + ] + ) # end attribute def is_default_attribute(self, attribute): return attribute in self.defaultAttributes @@ -128,7 +132,9 @@ class AttributeManager(): return False cursor_pos = cursor.copy() try: - attribute = self.get_attribute_by_xy(cursor_pos['x'], cursor_pos['y']) + attribute = self.get_attribute_by_xy( + cursor_pos["x"], cursor_pos["y"] + ) if update: self.set_last_cursor_attribute(attribute) @@ -142,7 +148,7 @@ class AttributeManager(): return False return True - def format_attributes(self, attribute, attribute_format_string=''): + def format_attributes(self, attribute, attribute_format_string=""): # "black", # "red", # "green", @@ -163,124 +169,149 @@ class AttributeManager(): # "blink" # "fontsieze" # "fontfamily" - if attribute_format_string == '': - attribute_format_string = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'attribute_format_string') + if attribute_format_string == "": + attribute_format_string = self.env["runtime"][ + "SettingsManager" + ].get_setting("general", "attribute_format_string") if not attribute_format_string: - return '' - if attribute_format_string == '': - return '' + return "" + if attribute_format_string == "": + return "" if not attribute: - return '' + return "" if len(attribute) != 10: - return '' + return "" # 0 FG color (name) try: attribute_format_string = attribute_format_string.replace( - 'fenrirFGColor', _(attribute[0])) + "fenrirFGColor", _(attribute[0]) + ) except Exception as e: attribute_format_string = attribute_format_string.replace( - 'fenrirFGColor', '') + "fenrirFGColor", "" + ) # 1 BG color (name) try: attribute_format_string = attribute_format_string.replace( - 'fenrirBGColor', _(attribute[1])) + "fenrirBGColor", _(attribute[1]) + ) except Exception as e: attribute_format_string = attribute_format_string.replace( - 'fenrirBGColor', '') + "fenrirBGColor", "" + ) # 2 bold (True/ False) try: if attribute[2]: attribute_format_string = attribute_format_string.replace( - 'fenrirBold', _('bold')) + "fenrirBold", _("bold") + ) except Exception as e: pass - attribute_format_string = attribute_format_string.replace('fenrirBold', '') + attribute_format_string = attribute_format_string.replace( + "fenrirBold", "" + ) # 3 italics (True/ False) try: if attribute[3]: attribute_format_string = attribute_format_string.replace( - 'fenrirItalics', _('italic')) + "fenrirItalics", _("italic") + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirItalics', '') + "fenrirItalics", "" + ) # 4 underline (True/ False) try: if attribute[4]: attribute_format_string = attribute_format_string.replace( - 'fenrirUnderline', _('underline')) + "fenrirUnderline", _("underline") + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirUnderline', '') + "fenrirUnderline", "" + ) # 5 strikethrough (True/ False) try: if attribute[5]: attribute_format_string = attribute_format_string.replace( - 'fenrirStrikethrough', _('strikethrough')) + "fenrirStrikethrough", _("strikethrough") + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirStrikethrough', '') + "fenrirStrikethrough", "" + ) # 6 reverse (True/ False) try: if attribute[6]: attribute_format_string = attribute_format_string.replace( - 'fenrirReverse', _('reverse')) + "fenrirReverse", _("reverse") + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirReverse', '') + "fenrirReverse", "" + ) # 7 blink (True/ False) try: if attribute[7]: attribute_format_string = attribute_format_string.replace( - 'fenrirBlink', _('blink')) + "fenrirBlink", _("blink") + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirBlink', '') + "fenrirBlink", "" + ) # 8 font size (int/ string) try: try: attribute_format_string = attribute_format_string.replace( - 'fenrirFontSize', int(attribute[8])) + "fenrirFontSize", int(attribute[8]) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'AttributeManager formatAttributeToString: Error formatting font size as int: ' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "AttributeManager formatAttributeToString: Error formatting font size as int: " + + str(e), + debug.DebugLevel.ERROR, + ) try: attribute_format_string = attribute_format_string.replace( - 'fenrirFontSize', str(attribute[8])) + "fenrirFontSize", str(attribute[8]) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'AttributeManager formatAttributeToString: Error formatting font size as string: ' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "AttributeManager formatAttributeToString: Error formatting font size as string: " + + str(e), + debug.DebugLevel.ERROR, + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirFontSize', _('default')) + "fenrirFontSize", _("default") + ) # 9 font family (string) try: attribute_format_string = attribute_format_string.replace( - 'fenrirFont', attribute[9]) + "fenrirFont", attribute[9] + ) except Exception as e: pass attribute_format_string = attribute_format_string.replace( - 'fenrirFont', _('default')) + "fenrirFont", _("default") + ) return attribute_format_string @@ -296,7 +327,7 @@ class AttributeManager(): - highlighted_text: string of characters that gained highlighting - cursor_position: dict {'x': col, 'y': row} of first highlighted char """ - result = '' + result = "" curr_cursor = None # Early exit conditions - no attribute comparison possible @@ -314,8 +345,8 @@ class AttributeManager(): return result, curr_cursor # Get current screen text to correlate with attribute changes - text = self.env['runtime']['ScreenManager'].get_screen_text() - text_lines = text.split('\n') + text = self.env["runtime"]["ScreenManager"].get_screen_text() + text_lines = text.split("\n") # Sanity check: text lines must match attribute array dimensions if len(text_lines) != len(self.currAttributes): @@ -327,32 +358,37 @@ class AttributeManager(): # This line has attribute changes - examine each character # position for column in range(len(self.prevAttributes[line])): - if self.prevAttributes[line][column] == self.currAttributes[line][column]: + if ( + self.prevAttributes[line][column] + == self.currAttributes[line][column] + ): # No change at this position continue # Attribute changed at this position - check if it's worth # announcing if self.is_useful_for_tracking( - line, column, self.currAttributes, self.prevAttributes): + line, column, self.currAttributes, self.prevAttributes + ): # First highlighted character becomes cursor position # for navigation if not curr_cursor: - curr_cursor = {'x': column, 'y': line} + curr_cursor = {"x": column, "y": line} # Accumulate highlighted characters result += text_lines[line][column] # Add space between lines of highlighted text for speech # clarity - result += ' ' + result += " " return result, curr_cursor def is_useful_for_tracking( - self, - line, - column, - currAttributes, - prevAttributes, - attribute=1, - mode='zaxe'): + self, + line, + column, + currAttributes, + prevAttributes, + attribute=1, + mode="zaxe", + ): """ Determines if an attribute change at a specific position is worth announcing. @@ -378,29 +414,46 @@ class AttributeManager(): useful = False - if mode == 'default': + if mode == "default": # Simple mode: announce any non-default attribute - useful = not self.is_default_attribute(currAttributes[line][column]) + useful = not self.is_default_attribute( + currAttributes[line][column] + ) - elif (mode == 'zaxe') or (mode == ''): + elif (mode == "zaxe") or (mode == ""): # Context-aware mode: only announce attributes that stand out from surroundings # This prevents announcing entire blocks of highlighted text character by character # by checking if the attribute differs from adjacent lines if line == 0: # Top line: compare against lines below - useful = (currAttributes[line][column][attribute] != currAttributes[line + 1][column][attribute]) and ( - currAttributes[line][column][attribute] != currAttributes[line + 2][column][attribute]) + useful = ( + currAttributes[line][column][attribute] + != currAttributes[line + 1][column][attribute] + ) and ( + currAttributes[line][column][attribute] + != currAttributes[line + 2][column][attribute] + ) elif line >= len(prevAttributes): # Bottom line: compare against lines above - useful = (currAttributes[line][column][attribute] != currAttributes[line - 1][column][attribute]) and ( - currAttributes[line][column][attribute] != currAttributes[line - 2][column][attribute]) + useful = ( + currAttributes[line][column][attribute] + != currAttributes[line - 1][column][attribute] + ) and ( + currAttributes[line][column][attribute] + != currAttributes[line - 2][column][attribute] + ) else: # Middle lines: compare against both directions - useful = (currAttributes[line][column][attribute] != currAttributes[line + 1][column][attribute]) and ( - currAttributes[line][column][attribute] != currAttributes[line - 1][column][attribute]) + useful = ( + currAttributes[line][column][attribute] + != currAttributes[line + 1][column][attribute] + ) and ( + currAttributes[line][column][attribute] + != currAttributes[line - 1][column][attribute] + ) - elif mode == 'barrier': + elif mode == "barrier": # Barrier mode: future enhancement for detecting screen # boundaries/separators useful = True diff --git a/src/fenrirscreenreader/core/barrierManager.py b/src/fenrirscreenreader/core/barrierManager.py index 097789ca..14ee8259 100644 --- a/src/fenrirscreenreader/core/barrierManager.py +++ b/src/fenrirscreenreader/core/barrierManager.py @@ -2,14 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import re import string +from fenrirscreenreader.core import debug -class BarrierManager(): + +class BarrierManager: def __init__(self): self.currIsBarrier = False self.prefIsBarrier = False @@ -32,49 +33,52 @@ class BarrierManager(): return self.currIsBarrier != self.prefIsBarrier def handle_line_barrier( - self, - text, - xCursor, - yCursor, - output=True, - do_interrupt=True): + self, text, xCursor, yCursor, output=True, do_interrupt=True + ): is_barrier = False try: - is_barrier, say_line = self.get_barrier_text(text, xCursor, yCursor) + is_barrier, say_line = self.get_barrier_text( + text, xCursor, yCursor + ) except Exception as e: - return False, '' + return False, "" self.update_barrier_change(is_barrier) if self.is_barrier_change(): if output: if is_barrier: - self.env['runtime']['OutputManager'].play_sound_icon( - sound_icon ='BarrierStart', interrupt=do_interrupt) + self.env["runtime"]["OutputManager"].play_sound_icon( + sound_icon="BarrierStart", interrupt=do_interrupt + ) else: - self.env['runtime']['OutputManager'].play_sound_icon( - sound_icon ='BarrierEnd', interrupt=do_interrupt) + self.env["runtime"]["OutputManager"].play_sound_icon( + sound_icon="BarrierEnd", interrupt=do_interrupt + ) if not is_barrier: - say_line = '' + say_line = "" return is_barrier, say_line def get_barrier_text(self, text, xCursor, yCursor): line = text[yCursor] - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'barrier', 'enabled'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "barrier", "enabled" + ): return False, line offset = xCursor - left_barriers = self.env['runtime']['SettingsManager'].get_setting( - 'barrier', 'left_barriers') - right_barriers = self.env['runtime']['SettingsManager'].get_setting( - 'barrier', 'right_barriers') + left_barriers = self.env["runtime"]["SettingsManager"].get_setting( + "barrier", "left_barriers" + ) + right_barriers = self.env["runtime"]["SettingsManager"].get_setting( + "barrier", "right_barriers" + ) # is the cursor at the begin or end of an entry: # print(line[:offset + 1].count('│'),line[offset:].count('│')) # start for b in left_barriers: - if line[:offset + 1].count(b) > line[offset:].count(b): + if line[: offset + 1].count(b) > line[offset:].count(b): offset = xCursor - 1 start = line[:offset].rfind(b) if start != -1: diff --git a/src/fenrirscreenreader/core/byteManager.py b/src/fenrirscreenreader/core/byteManager.py index abca3768..620317ed 100644 --- a/src/fenrirscreenreader/core/byteManager.py +++ b/src/fenrirscreenreader/core/byteManager.py @@ -2,30 +2,30 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug -from fenrirscreenreader.core.i18n import _ -from fenrirscreenreader.core.eventData import FenrirEventType -import os import inspect +import os import re import time + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import FenrirEventType +from fenrirscreenreader.core.i18n import _ + currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class ByteManager(): +class ByteManager: def __init__(self): self.switchCtrlModeOnce = 0 self.controlMode = True self.repeat = 1 self.lastInputTime = time.time() - self.lastByteKey = b'' + self.lastByteKey = b"" def initialize(self, environment): self.env = environment @@ -36,13 +36,18 @@ class ByteManager(): def unify_escape_seq(self, escapeSequence): converted_escape_sequence = escapeSequence if converted_escape_sequence[0] == 27: - converted_escape_sequence = b'^[' + converted_escape_sequence[1:] + converted_escape_sequence = b"^[" + converted_escape_sequence[1:] if len(converted_escape_sequence) > 1: - if converted_escape_sequence[0] == 94 and converted_escape_sequence[1] == 91: - converted_escape_sequence = b'^[' + converted_escape_sequence[2:] + if ( + converted_escape_sequence[0] == 94 + and converted_escape_sequence[1] == 91 + ): + converted_escape_sequence = ( + b"^[" + converted_escape_sequence[2:] + ) return converted_escape_sequence - def handle_byte_stream(self, event_data, sep=b'\x1b'): + def handle_byte_stream(self, event_data, sep=b"\x1b"): buffer = event_data # handle prefix end_index = buffer.find(sep) @@ -55,28 +60,32 @@ class ByteManager(): self.handle_single_byte_sequence(buffer) return # handle outstanding sequence - while buffer != b'': - end_index = buffer[len(sep):].find(sep) + while buffer != b"": + end_index = buffer[len(sep) :].find(sep) if end_index == -1: curr_sequence = buffer - buffer = b'' + buffer = b"" else: - curr_sequence = buffer[:end_index + len(sep)] - buffer = buffer[end_index + len(sep):] + curr_sequence = buffer[: end_index + len(sep)] + buffer = buffer[end_index + len(sep) :] self.handle_single_byte_sequence(curr_sequence) def handle_byte_input(self, event_data): if not event_data: return - if event_data == b'': + if event_data == b"": return try: - self.env['runtime']['DebugManager'].write_debug_out( - "handle_byte_input " + event_data.decode('utf8'), debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "handle_byte_input " + event_data.decode("utf8"), + debug.DebugLevel.INFO, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ByteManager handle_byte_input: Error decoding byte data: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ByteManager handle_byte_input: Error decoding byte data: " + + str(e), + debug.DebugLevel.ERROR, + ) self.handle_byte_stream(event_data) def handle_single_byte_sequence(self, event_data): @@ -86,27 +95,39 @@ class ByteManager(): self.switchCtrlModeOnce -= 1 is_control_mode = False - if self.controlMode and not self.switchCtrlModeOnce == 1 or\ - not self.controlMode: + if ( + self.controlMode + and not self.switchCtrlModeOnce == 1 + or not self.controlMode + ): is_control_mode = self.handle_control_mode(event_data) is_command = False - if self.controlMode and not self.switchCtrlModeOnce == 1 or\ - not self.controlMode and self.switchCtrlModeOnce == 1: + if ( + self.controlMode + and not self.switchCtrlModeOnce == 1 + or not self.controlMode + and self.switchCtrlModeOnce == 1 + ): if self.lastByteKey == converted_escape_sequence: - if time.time() - self.lastInputTime <= self.env['runtime']['SettingsManager'].get_setting_as_float( - 'keyboard', 'doubleTapTimeout'): + if time.time() - self.lastInputTime <= self.env["runtime"][ + "SettingsManager" + ].get_setting_as_float("keyboard", "doubleTapTimeout"): self.repeat += 1 - shortcut_data = b'' + shortcut_data = b"" for i in range(self.repeat): shortcut_data = shortcut_data + converted_escape_sequence is_command = self.detect_byte_command(shortcut_data) # fall back to single stroke - do we want this? if not is_command: - is_command = self.detect_byte_command(converted_escape_sequence) + is_command = self.detect_byte_command( + converted_escape_sequence + ) self.repeat = 1 if not (is_command or is_control_mode): - self.env['runtime']['ScreenManager'].inject_text_to_screen(event_data) + self.env["runtime"]["ScreenManager"].inject_text_to_screen( + event_data + ) if not is_command: self.repeat = 1 self.lastByteKey = converted_escape_sequence @@ -117,20 +138,29 @@ class ByteManager(): def handle_control_mode(self, escapeSequence): converted_escape_sequence = self.unify_escape_seq(escapeSequence) - if converted_escape_sequence == b'^[R': + if converted_escape_sequence == b"^[R": self.controlMode = not self.controlMode self.switchCtrlModeOnce = 0 if self.controlMode: - self.env['runtime']['OutputManager'].present_text( - _('Sticky Mode On'), sound_icon ='Accept', interrupt=True, flush=True) + self.env["runtime"]["OutputManager"].present_text( + _("Sticky Mode On"), + sound_icon="Accept", + interrupt=True, + flush=True, + ) else: - self.env['runtime']['OutputManager'].present_text( - _('Sticky Mode On'), sound_icon ='Cancel', interrupt=True, flush=True) + self.env["runtime"]["OutputManager"].present_text( + _("Sticky Mode On"), + sound_icon="Cancel", + interrupt=True, + flush=True, + ) return True - if converted_escape_sequence == b'^[:': + if converted_escape_sequence == b"^[:": self.switchCtrlModeOnce = 2 - self.env['runtime']['OutputManager'].present_text( - _('bypass'), sound_icon ='PTYBypass', interrupt=True, flush=True) + self.env["runtime"]["OutputManager"].present_text( + _("bypass"), sound_icon="PTYBypass", interrupt=True, flush=True + ) return True return False @@ -139,55 +169,56 @@ class ByteManager(): def detect_byte_command(self, escapeSequence): converted_escape_sequence = self.unify_escape_seq(escapeSequence) - command = self.env['runtime']['InputManager'].get_command_for_shortcut( - converted_escape_sequence) - if command != '': - self.env['runtime']['EventManager'].put_to_event_queue( - FenrirEventType.execute_command, command) - command = '' + command = self.env["runtime"]["InputManager"].get_command_for_shortcut( + converted_escape_sequence + ) + if command != "": + self.env["runtime"]["EventManager"].put_to_event_queue( + FenrirEventType.execute_command, command + ) + command = "" return True return False def load_byte_shortcuts( - self, - kb_config_path=fenrir_path + - '/../../config/keyboard/pty.conf'): + self, kb_config_path=fenrir_path + "/../../config/keyboard/pty.conf" + ): kb_config = open(kb_config_path, "r") - while (True): + while True: line = kb_config.readline() if not line: break - line = line.replace('\n', '') - if line.replace(" ", "") == '': + line = line.replace("\n", "") + if line.replace(" ", "") == "": continue if line.replace(" ", "").startswith("#"): continue if line.count("=") != 1: continue - values = line.split('=') - clean_shortcut = bytes(values[0], 'UTF-8') + values = line.split("=") + clean_shortcut = bytes(values[0], "UTF-8") repeat = 1 if len(clean_shortcut) > 2: - if chr(clean_shortcut[1]) == ',': + if chr(clean_shortcut[1]) == ",": try: repeat = int(chr(clean_shortcut[0])) clean_shortcut = clean_shortcut[2:] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ByteManager load_byte_shortcuts: Error parsing repeat count: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ByteManager load_byte_shortcuts: Error parsing repeat count: " + + str(e), + debug.DebugLevel.ERROR, + ) repeat = 1 clean_shortcut = clean_shortcut - shortcut = b'' + shortcut = b"" for i in range(repeat): shortcut += clean_shortcut command_name = values[1].upper() - self.env['bindings'][shortcut] = command_name - self.env['runtime']['DebugManager'].write_debug_out( - "Byte Shortcut: " + - str(shortcut) + - ' command:' + - command_name, + self.env["bindings"][shortcut] = command_name + self.env["runtime"]["DebugManager"].write_debug_out( + "Byte Shortcut: " + str(shortcut) + " command:" + command_name, debug.DebugLevel.INFO, - on_any_level=True) + on_any_level=True, + ) kb_config.close() diff --git a/src/fenrirscreenreader/core/commandData.py b/src/fenrirscreenreader/core/commandData.py index 619a9afd..b5f88fe4 100644 --- a/src/fenrirscreenreader/core/commandData.py +++ b/src/fenrirscreenreader/core/commandData.py @@ -2,23 +2,24 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import time from fenrirscreenreader.core import debug -import time # used as shared memory between commands # use this in your own commands command_buffer = { - 'enableSpeechOnKeypress': False, - 'Marks': {'1': None, '2': None}, - 'bookMarks': {}, - 'windowArea': {}, + "enableSpeechOnKeypress": False, + "Marks": {"1": None, "2": None}, + "bookMarks": {}, + "windowArea": {}, } # used by the command_manager command_info = { # 'curr_command': '', - 'lastCommandExecutionTime': time.time(), - 'lastCommandRequestTime': time.time(), + "lastCommandExecutionTime": time.time(), + "lastCommandRequestTime": time.time(), } diff --git a/src/fenrirscreenreader/core/commandManager.py b/src/fenrirscreenreader/core/commandManager.py index 6716339e..ad3eafe6 100644 --- a/src/fenrirscreenreader/core/commandManager.py +++ b/src/fenrirscreenreader/core/commandManager.py @@ -2,365 +2,482 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.utils import module_utils -from fenrirscreenreader.core import debug import glob +import inspect import os import time -import inspect + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import module_utils + currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class CommandManager(): +class CommandManager: def __init__(self): pass def initialize(self, environment): self.env = environment # commands - self.env['commands'] = {} - self.env['commandsIgnore'] = {} - for command_folder in self.env['general']['commandFolderList']: - self.env['runtime']['CommandManager'].load_commands(command_folder) - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'command_path') != '': - self.env['runtime']['CommandManager'].load_commands( - command_folder, self.env['runtime']['SettingsManager'].get_setting( - 'general', 'command_path')) + self.env["commands"] = {} + self.env["commandsIgnore"] = {} + for command_folder in self.env["general"]["commandFolderList"]: + self.env["runtime"]["CommandManager"].load_commands(command_folder) + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "general", "command_path" + ) + != "" + ): + self.env["runtime"]["CommandManager"].load_commands( + command_folder, + self.env["runtime"]["SettingsManager"].get_setting( + "general", "command_path" + ), + ) # scripts for scriptKey - self.env['runtime']['CommandManager'].load_script_commands() + self.env["runtime"]["CommandManager"].load_script_commands() def shutdown(self): - for command_folder in self.env['general']['commandFolderList']: - self.env['runtime']['CommandManager'].shutdown_commands( - command_folder) + for command_folder in self.env["general"]["commandFolderList"]: + self.env["runtime"]["CommandManager"].shutdown_commands( + command_folder + ) - def load_file(self, filepath=''): - if filepath == '': + def load_file(self, filepath=""): + if filepath == "": return None if not os.path.exists(filepath): - self.env['runtime']['DebugManager'].write_debug_out( - "load_file: filepath not exists:" + filepath, debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_file: filepath not exists:" + filepath, + debug.DebugLevel.WARNING, + ) return None if os.path.isdir(filepath): - self.env['runtime']['DebugManager'].write_debug_out( - "load_file: filepath is a directory:" + filepath, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_file: filepath is a directory:" + filepath, + debug.DebugLevel.ERROR, + ) return None if not os.access(filepath, os.R_OK): - self.env['runtime']['DebugManager'].write_debug_out( - "load_file: filepath not readable:" + filepath, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_file: filepath not readable:" + filepath, + debug.DebugLevel.ERROR, + ) return None try: file_name, file_extension = os.path.splitext(filepath) - file_name = file_name.split('/')[-1] - if file_name.startswith('__'): + file_name = file_name.split("/")[-1] + if file_name.startswith("__"): return None - if file_extension.lower() == '.py': + if file_extension.lower() == ".py": command_mod = module_utils.import_module(file_name, filepath) command = command_mod.command() command.initialize(self.env) - self.env['runtime']['DebugManager'].write_debug_out( - "load_file: Load command:" + filepath, debug.DebugLevel.INFO, on_any_level=True) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_file: Load command:" + filepath, + debug.DebugLevel.INFO, + on_any_level=True, + ) return command except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "load_file: Loading command:" + filepath, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_file: Loading command:" + filepath, + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) return None - def load_commands(self, section='commands', command_path=''): - if command_path == '': + def load_commands(self, section="commands", command_path=""): + if command_path == "": command_path = fenrir_path + "/commands/" - if not command_path.endswith('/'): - command_path += '/' + if not command_path.endswith("/"): + command_path += "/" command_folder = command_path + section + "/" if not os.path.exists(command_folder): - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "load_commands: command_folder not exists:" + command_folder, - debug.DebugLevel.WARNING) + debug.DebugLevel.WARNING, + ) return if not os.path.isdir(command_folder): - self.env['runtime']['DebugManager'].write_debug_out( - "load_commands: command_folder not a directory:" + - command_folder, - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_commands: command_folder not a directory:" + + command_folder, + debug.DebugLevel.ERROR, + ) return if not os.access(command_folder, os.R_OK): - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "load_commands: command_folder not readable:" + command_folder, - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) return - self.env['commands'][section] = {} - self.env['commandsIgnore'][section] = {} - command_list = glob.glob(command_folder + '*') + self.env["commands"][section] = {} + self.env["commandsIgnore"][section] = {} + command_list = glob.glob(command_folder + "*") for command in command_list: try: file_name, file_extension = os.path.splitext(command) - file_name = file_name.split('/')[-1] - if file_name.startswith('__'): + file_name = file_name.split("/")[-1] + if file_name.startswith("__"): continue # Skip base classes that shouldn't be loaded as commands - if file_name.endswith('_base'): + if file_name.endswith("_base"): continue # Check if command already exists to prevent duplicate loading - if file_name.upper( - ) in self.env['commands'][section] and self.env['commands'][section][file_name.upper()] is not None: + if ( + file_name.upper() in self.env["commands"][section] + and self.env["commands"][section][file_name.upper()] + is not None + ): continue - if file_extension.lower() == '.py': - command_mod = module_utils.import_module(file_name, command) - self.env['commands'][section][file_name.upper() - ] = command_mod.command() - self.env['commandsIgnore'][section][file_name.upper( - )[file_name.upper().find('-') + 1:] + '_IGNORE'] = False - self.env['commands'][section][file_name.upper() - ].initialize(self.env) - self.env['runtime']['DebugManager'].write_debug_out( - "load_commands: Load command:" + - section + - "." + - file_name.upper(), + if file_extension.lower() == ".py": + command_mod = module_utils.import_module( + file_name, command + ) + self.env["commands"][section][ + file_name.upper() + ] = command_mod.command() + self.env["commandsIgnore"][section][ + file_name.upper()[file_name.upper().find("-") + 1 :] + + "_IGNORE" + ] = False + self.env["commands"][section][ + file_name.upper() + ].initialize(self.env) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_commands: Load command:" + + section + + "." + + file_name.upper(), debug.DebugLevel.INFO, - on_any_level=True) + on_any_level=True, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "load_commands: Loading command:" + command, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "load_commands: Loading command:" + command, + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) continue - def load_script_commands(self, section='commands', script_path=''): - if script_path == '': - script_path = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'script_path') - if not script_path.endswith('/'): - script_path += '/' + def load_script_commands(self, section="commands", script_path=""): + if script_path == "": + script_path = self.env["runtime"]["SettingsManager"].get_setting( + "general", "script_path" + ) + if not script_path.endswith("/"): + script_path += "/" if not os.path.exists(script_path): - if os.path.exists(fenrir_path + '/../../config/scripts/'): - script_path = fenrir_path + '/../../config/scripts/' + if os.path.exists(fenrir_path + "/../../config/scripts/"): + script_path = fenrir_path + "/../../config/scripts/" else: - self.env['runtime']['DebugManager'].write_debug_out( - "scriptpath not exists:" + script_path, debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "scriptpath not exists:" + script_path, + debug.DebugLevel.WARNING, + ) return if not os.path.isdir(script_path): - self.env['runtime']['DebugManager'].write_debug_out( - "scriptpath not a directory:" + script_path, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "scriptpath not a directory:" + script_path, + debug.DebugLevel.ERROR, + ) return if not os.access(script_path, os.R_OK): - self.env['runtime']['DebugManager'].write_debug_out( - "scriptpath not readable:" + script_path, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "scriptpath not readable:" + script_path, + debug.DebugLevel.ERROR, + ) return - command_list = glob.glob(script_path + '*') - sub_command = fenrir_path + '/commands/commands/subprocess.py' + command_list = glob.glob(script_path + "*") + sub_command = fenrir_path + "/commands/commands/subprocess.py" for command in command_list: invalid = False try: file_name, file_extension = os.path.splitext(command) - file_name = file_name.split('/')[-1] - if file_name.startswith('__'): + file_name = file_name.split("/")[-1] + if file_name.startswith("__"): continue - if file_name.upper() in self.env['commands'][section]: + if file_name.upper() in self.env["commands"][section]: continue - command_mod = module_utils.import_module(file_name, sub_command) - self.env['commands'][section][file_name.upper() - ] = command_mod.command() - self.env['commands'][section][file_name.upper()].initialize( - self.env, command) - self.env['runtime']['DebugManager'].write_debug_out( - "Load script:" + - section + - "." + - file_name.upper(), + command_mod = module_utils.import_module( + file_name, sub_command + ) + self.env["commands"][section][ + file_name.upper() + ] = command_mod.command() + self.env["commands"][section][file_name.upper()].initialize( + self.env, command + ) + self.env["runtime"]["DebugManager"].write_debug_out( + "Load script:" + section + "." + file_name.upper(), debug.DebugLevel.INFO, - on_any_level=True) - comm_settings = file_name.upper().split('__-__') + on_any_level=True, + ) + comm_settings = file_name.upper().split("__-__") if len(comm_settings) == 1: keys = comm_settings[0] elif len(comm_settings) == 2: keys = comm_settings[1] elif len(comm_settings) > 2: continue - keys = keys.split('__+__') + keys = keys.split("__+__") shortcut_keys = [] shortcut = [] for key in keys: - if not self.env['runtime']['InputManager'].is_valid_key( - key.upper()): - self.env['runtime']['DebugManager'].write_debug_out( - "invalid key : " + key.upper() + ' script:' + file_name, debug.DebugLevel.WARNING) + if not self.env["runtime"]["InputManager"].is_valid_key( + key.upper() + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "invalid key : " + + key.upper() + + " script:" + + file_name, + debug.DebugLevel.WARNING, + ) invalid = True break shortcut_keys.append(key.upper()) if invalid: continue - if 'KEY_SCRIPT' not in shortcut_keys: - shortcut_keys.append('KEY_SCRIPT') + if "KEY_SCRIPT" not in shortcut_keys: + shortcut_keys.append("KEY_SCRIPT") shortcut.append(1) shortcut.append(sorted(shortcut_keys)) - self.env['bindings'][str(shortcut)] = file_name.upper() + self.env["bindings"][str(shortcut)] = file_name.upper() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Loading script:" + file_name, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Loading script:" + file_name, debug.DebugLevel.ERROR + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) continue def shutdown_commands(self, section): # Check if the section exists in the commands dictionary - if section not in self.env['commands']: - self.env['runtime']['DebugManager'].write_debug_out( + if section not in self.env["commands"]: + self.env["runtime"]["DebugManager"].write_debug_out( "shutdown_commands: section not found:" + section, - debug.DebugLevel.WARNING) + debug.DebugLevel.WARNING, + ) return - for command in sorted(self.env['commands'][section]): + for command in sorted(self.env["commands"][section]): try: - self.env['commands'][section][command].shutdown() - del self.env['commands'][section][command] + self.env["commands"][section][command].shutdown() + del self.env["commands"][section][command] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Shutdown command:" + section + "." + command, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Shutdown command:" + section + "." + command, + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) continue def execute_switch_trigger(self, trigger, unLoadScript, loadScript): - if self.env['runtime']['ScreenManager'].is_ignored_screen(): + if self.env["runtime"]["ScreenManager"].is_ignored_screen(): return # unload old_script = unLoadScript if self.command_exists(old_script, trigger): try: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing switchtrigger.unload:" + trigger + "." + old_script, - debug.DebugLevel.INFO) - self.env['commands'][trigger][old_script].unload() + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing switchtrigger.unload:" + + trigger + + "." + + old_script, + debug.DebugLevel.INFO, + ) + self.env["commands"][trigger][old_script].unload() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing trigger:" + trigger + "." + old_script, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing trigger:" + trigger + "." + old_script, + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) # load new_script = loadScript if self.command_exists(new_script, trigger): try: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing switchtrigger.load:" + trigger + "." + new_script, - debug.DebugLevel.INFO) - self.env['commands'][trigger][new_script].load() + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing switchtrigger.load:" + + trigger + + "." + + new_script, + debug.DebugLevel.INFO, + ) + self.env["commands"][trigger][new_script].load() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing trigger:" + trigger + "." + new_script, debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing trigger:" + trigger + "." + new_script, + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) def execute_default_trigger(self, trigger, force=False): if not force: - if self.env['runtime']['ScreenManager'].is_ignored_screen(): + if self.env["runtime"]["ScreenManager"].is_ignored_screen(): return - for command in sorted(self.env['commands'][trigger]): + for command in sorted(self.env["commands"][trigger]): if self.command_exists(command, trigger): try: - if self.env['commandsIgnore'][trigger][command[command.find( - '-') + 1:] + '_IGNORE']: - self.env['commandsIgnore'][trigger][command[command.find( - '-') + 1:] + '_IGNORE'] = False - self.env['runtime']['DebugManager'].write_debug_out( - "ignore trigger.command:" + trigger + "." + command, debug.DebugLevel.INFO) + if self.env["commandsIgnore"][trigger][ + command[command.find("-") + 1 :] + "_IGNORE" + ]: + self.env["commandsIgnore"][trigger][ + command[command.find("-") + 1 :] + "_IGNORE" + ] = False + self.env["runtime"]["DebugManager"].write_debug_out( + "ignore trigger.command:" + + trigger + + "." + + command, + debug.DebugLevel.INFO, + ) else: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing trigger.command:" + trigger + "." + command, debug.DebugLevel.INFO) - self.env['commands'][trigger][command].run() + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing trigger.command:" + + trigger + + "." + + command, + debug.DebugLevel.INFO, + ) + self.env["commands"][trigger][command].run() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing trigger:" + trigger + "." + command + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing trigger:" + + trigger + + "." + + command + + str(e), + debug.DebugLevel.ERROR, + ) - def execute_command(self, command, section='commands'): - if self.env['runtime']['ScreenManager'].is_ignored_screen(): + def execute_command(self, command, section="commands"): + if self.env["runtime"]["ScreenManager"].is_ignored_screen(): return if self.command_exists(command, section): try: - if self.env['runtime']['HelpManager'].is_tutorial_mode( - ) and section != 'help': - self.env['runtime']['DebugManager'].write_debug_out( - "Tutorial for command:" + section + "." + command, debug.DebugLevel.INFO) - description = self.get_command_description(command, section) - self.env['runtime']['OutputManager'].present_text( - description, interrupt=False) + if ( + self.env["runtime"]["HelpManager"].is_tutorial_mode() + and section != "help" + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Tutorial for command:" + section + "." + command, + debug.DebugLevel.INFO, + ) + description = self.get_command_description( + command, section + ) + self.env["runtime"]["OutputManager"].present_text( + description, interrupt=False + ) else: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing command:" + section + "." + command, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing command:" + section + "." + command, + debug.DebugLevel.INFO, + ) self.run_command(command, section) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Executing command:" + section + "." + command + ' ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Executing command:" + + section + + "." + + command + + " " + + str(e), + debug.DebugLevel.ERROR, + ) - def run_command(self, command, section='commands'): + def run_command(self, command, section="commands"): if self.command_exists(command, section): try: - self.env['runtime']['DebugManager'].write_debug_out( - "run_command command:" + section + "." + command, debug.DebugLevel.INFO) - self.env['commands'][section][command].run() + self.env["runtime"]["DebugManager"].write_debug_out( + "run_command command:" + section + "." + command, + debug.DebugLevel.INFO, + ) + self.env["commands"][section][command].run() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "run_command command:" + section + "." + command + ' ' + str(e), - debug.DebugLevel.ERROR) - self.env['commandInfo']['lastCommandExecutionTime'] = time.time() + self.env["runtime"]["DebugManager"].write_debug_out( + "run_command command:" + + section + + "." + + command + + " " + + str(e), + debug.DebugLevel.ERROR, + ) + self.env["commandInfo"]["lastCommandExecutionTime"] = time.time() - def get_command_description(self, command, section='commands'): + def get_command_description(self, command, section="commands"): if self.command_exists(command, section): try: - return self.env['commands'][section][command].get_description() + return self.env["commands"][section][command].get_description() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'command_manager.get_command_description:' + str(e), debug.DebugLevel.ERROR) - self.env['commandInfo']['lastCommandExecutionTime'] = time.time() + self.env["runtime"]["DebugManager"].write_debug_out( + "command_manager.get_command_description:" + str(e), + debug.DebugLevel.ERROR, + ) + self.env["commandInfo"]["lastCommandExecutionTime"] = time.time() - def command_exists(self, command, section='commands'): + def command_exists(self, command, section="commands"): try: - return (command in self.env['commands'][section]) + return command in self.env["commands"][section] except Exception as e: return False def get_shortcut_for_command(self, command, formatKeys=False): shortcut = [] try: - raw_shortcut = list(self.env['bindings'].keys())[ - list(self.env['bindings'].values()).index(command)] + raw_shortcut = list(self.env["bindings"].keys())[ + list(self.env["bindings"].values()).index(command) + ] # prefer numbers for multitap - for k in ['2', '3', '4', '5', '6', '7', '8']: + for k in ["2", "3", "4", "5", "6", "7", "8"]: if k in raw_shortcut: formatted_key = k if formatKeys: formatted_key = formatted_key.lower() - formatted_key += ' times ' + formatted_key += " times " shortcut.append(formatted_key) raw_shortcut.remove(k) # prefer metha keys for k in [ - 'KEY_FENRIR', - 'KEY_SCRIPT', - 'KEY_CTRL', - 'KEY_SHIFT', - 'KEY_ALT', - 'KEY_META']: + "KEY_FENRIR", + "KEY_SCRIPT", + "KEY_CTRL", + "KEY_SHIFT", + "KEY_ALT", + "KEY_META", + ]: if k in raw_shortcut: formatted_key = k if formatKeys: formatted_key = formatted_key.lower() formatted_key = formatted_key.replace( - 'key_kp', ' keypad ') - formatted_key = formatted_key.replace('key_', ' ') + "key_kp", " keypad " + ) + formatted_key = formatted_key.replace("key_", " ") shortcut.append(formatted_key) raw_shortcut.remove(k) # handle other keys @@ -368,8 +485,8 @@ class CommandManager(): formatted_key = k if formatKeys: formatted_key = formatted_key.lower() - formatted_key = formatted_key.replace('key_kp', ' keypad ') - formatted_key = formatted_key.replace('key_', ' ') + formatted_key = formatted_key.replace("key_kp", " keypad ") + formatted_key = formatted_key.replace("key_", " ") shortcut.append(formatted_key) except Exception as e: pass diff --git a/src/fenrirscreenreader/core/cursorManager.py b/src/fenrirscreenreader/core/cursorManager.py index fb640a57..85f6379a 100644 --- a/src/fenrirscreenreader/core/cursorManager.py +++ b/src/fenrirscreenreader/core/cursorManager.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class CursorManager(): +class CursorManager: def __init__(self): pass @@ -21,92 +21,122 @@ class CursorManager(): Return False if numlock is ON (let keys type numbers) """ # Return False if numlock is ON - return not self.env['input']['newNumLock'] + return not self.env["input"]["newNumLock"] def shutdown(self): pass def clear_marks(self): - 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 is_mark_set(self): - return self.env['commandBuffer']['Marks']['1'] is not None + return self.env["commandBuffer"]["Marks"]["1"] is not None def is_single_mark(self): - return self.env['commandBuffer']['Marks']['1'] is not None and \ - self.env['commandBuffer']['Marks']['2'] is None + return ( + self.env["commandBuffer"]["Marks"]["1"] is not None + and self.env["commandBuffer"]["Marks"]["2"] is None + ) def is_multible_mark(self): - return self.env['commandBuffer']['Marks']['1'] is not None and \ - self.env['commandBuffer']['Marks']['2'] is not None + return ( + self.env["commandBuffer"]["Marks"]["1"] is not None + and self.env["commandBuffer"]["Marks"]["2"] is not None + ) def set_mark(self): curr_cursor = None - if self.env['screen']['newCursorReview']: - curr_cursor = self.env['screen']['newCursorReview'].copy() + if self.env["screen"]["newCursorReview"]: + curr_cursor = self.env["screen"]["newCursorReview"].copy() else: - curr_cursor = self.env['screen']['new_cursor'].copy() - if not self.env['commandBuffer']['Marks']['1']: - self.env['commandBuffer']['Marks']['1'] = curr_cursor.copy() + curr_cursor = self.env["screen"]["new_cursor"].copy() + if not self.env["commandBuffer"]["Marks"]["1"]: + self.env["commandBuffer"]["Marks"]["1"] = curr_cursor.copy() return 1 else: - self.env['commandBuffer']['Marks']['2'] = curr_cursor.copy() + self.env["commandBuffer"]["Marks"]["2"] = curr_cursor.copy() return 2 return 0 def get_review_or_text_cursor(self): - if self.env['screen']['newCursorReview']: - return self.env['screen']['newCursorReview'].copy() + if self.env["screen"]["newCursorReview"]: + return self.env["screen"]["newCursorReview"].copy() else: - return self.env['screen']['new_cursor'].copy() + return self.env["screen"]["new_cursor"].copy() def clear_review_cursor(self): if not self.is_review_mode(): return - self.env['screen']['oldCursorReview'] = None - self.env['screen']['newCursorReview'] = None + self.env["screen"]["oldCursorReview"] = None + self.env["screen"]["newCursorReview"] = None def is_cursor_horizontal_move(self): - return self.env['screen']['new_cursor']['x'] != self.env['screen']['old_cursor']['x'] + return ( + self.env["screen"]["new_cursor"]["x"] + != self.env["screen"]["old_cursor"]["x"] + ) def is_cursor_vertical_move(self): - return self.env['screen']['new_cursor']['y'] != self.env['screen']['old_cursor']['y'] + return ( + self.env["screen"]["new_cursor"]["y"] + != self.env["screen"]["old_cursor"]["y"] + ) def is_review_mode(self): - return self.env['screen']['newCursorReview'] is not None + return self.env["screen"]["newCursorReview"] is not None def enter_review_mode_curr_text_cursor(self, overwrite=False): if self.is_review_mode() and not overwrite: return - self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] - if not self.env['screen']['newCursorReview']: - self.env['screen']['newCursorReview'] = self.env['screen']['new_cursor'].copy() - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', - 'highlight') and self.env['runtime']['AttributeManager'].is_attribute_cursor_active(): - self.env['screen']['newCursorReview'] = self.env['runtime']['AttributeManager'].get_curr_attribute_cursor( - ).copy() + self.env["screen"]["oldCursorReview"] = self.env["screen"][ + "newCursorReview" + ] + if not self.env["screen"]["newCursorReview"]: + self.env["screen"]["newCursorReview"] = self.env["screen"][ + "new_cursor" + ].copy() + if ( + self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "highlight" + ) + and self.env["runtime"][ + "AttributeManager" + ].is_attribute_cursor_active() + ): + self.env["screen"]["newCursorReview"] = ( + self.env["runtime"]["AttributeManager"] + .get_curr_attribute_cursor() + .copy() + ) def set_review_cursor_position(self, x, y): if not self.is_review_mode(): self.enter_review_mode_curr_text_cursor() - self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] - self.env['screen']['newCursorReview']['x'] = x - self.env['screen']['newCursorReview']['y'] = y + self.env["screen"]["oldCursorReview"] = self.env["screen"][ + "newCursorReview" + ] + self.env["screen"]["newCursorReview"]["x"] = x + self.env["screen"]["newCursorReview"]["y"] = y def is_application_window_set(self): try: - curr_app = self.env['runtime']['ApplicationManager'].get_current_application( - ) - if curr_app in self.env['commandBuffer']['windowArea'] and \ - '1' in self.env['commandBuffer']['windowArea'][curr_app] and \ - self.env['commandBuffer']['windowArea'][curr_app]['1'] is not None: + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() + if ( + curr_app in self.env["commandBuffer"]["windowArea"] + and "1" in self.env["commandBuffer"]["windowArea"][curr_app] + and self.env["commandBuffer"]["windowArea"][curr_app]["1"] + is not None + ): return True except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'CursorManager is_application_window_set: Error checking window area: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "CursorManager is_application_window_set: Error checking window area: " + + str(e), + debug.DebugLevel.ERROR, + ) return False def set_window_for_application(self, start=None, end=None): @@ -115,48 +145,60 @@ class CursorManager(): y1 = 0 y2 = 0 if start is None: - if not self.env['commandBuffer']['Marks']['1']: + if not self.env["commandBuffer"]["Marks"]["1"]: return False else: - x1 = self.env['commandBuffer']['Marks']['1']['x'] - y1 = self.env['commandBuffer']['Marks']['1']['y'] + x1 = self.env["commandBuffer"]["Marks"]["1"]["x"] + y1 = self.env["commandBuffer"]["Marks"]["1"]["y"] else: - x1 = start['x'] - y1 = start['y'] + x1 = start["x"] + y1 = start["y"] if end is None: - if not self.env['commandBuffer']['Marks']['2']: + if not self.env["commandBuffer"]["Marks"]["2"]: return False else: - x2 = self.env['commandBuffer']['Marks']['2']['x'] - y2 = self.env['commandBuffer']['Marks']['2']['y'] + x2 = self.env["commandBuffer"]["Marks"]["2"]["x"] + y2 = self.env["commandBuffer"]["Marks"]["2"]["y"] else: - x2 = end['x'] - y2 = end['y'] + x2 = end["x"] + y2 = end["y"] - curr_app = self.env['runtime']['ApplicationManager'].get_current_application() - self.env['commandBuffer']['windowArea'][curr_app] = {} + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() + self.env["commandBuffer"]["windowArea"][curr_app] = {} - if x1 * y1 <= \ - x2 * y2: - self.env['commandBuffer']['windowArea'][curr_app]['1'] = { - 'x': x1, 'y': y1} - self.env['commandBuffer']['windowArea'][curr_app]['2'] = { - 'x': x2, 'y': y2} + if x1 * y1 <= x2 * y2: + self.env["commandBuffer"]["windowArea"][curr_app]["1"] = { + "x": x1, + "y": y1, + } + self.env["commandBuffer"]["windowArea"][curr_app]["2"] = { + "x": x2, + "y": y2, + } else: - self.env['commandBuffer']['windowArea'][curr_app]['1'] = { - 'x': x2, 'y': y2} - self.env['commandBuffer']['windowArea'][curr_app]['2'] = { - 'x': x1, 'y': y1} + self.env["commandBuffer"]["windowArea"][curr_app]["1"] = { + "x": x2, + "y": y2, + } + self.env["commandBuffer"]["windowArea"][curr_app]["2"] = { + "x": x1, + "y": y1, + } return True def clear_window_for_application(self): - curr_app = self.env['runtime']['ApplicationManager'].get_current_application() + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() try: - del self.env['commandBuffer']['windowArea'][curr_app] + del self.env["commandBuffer"]["windowArea"][curr_app] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'CursorManager clear_window_for_application: Error clearing window area: ' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "CursorManager clear_window_for_application: Error clearing window area: " + + str(e), + debug.DebugLevel.ERROR, + ) return False return True diff --git a/src/fenrirscreenreader/core/debugManager.py b/src/fenrirscreenreader/core/debugManager.py index 69a528f4..c905fe71 100644 --- a/src/fenrirscreenreader/core/debugManager.py +++ b/src/fenrirscreenreader/core/debugManager.py @@ -1,19 +1,25 @@ #!/usr/bin/env python3 # Debugger module for the Fenrir screen reader. -from fenrirscreenreader.core import debug -from datetime import datetime -import pathlib import os +import pathlib +from datetime import datetime + +from fenrirscreenreader.core import debug -class DebugManager(): - def __init__(self, file_name=''): +class DebugManager: + def __init__(self, file_name=""): self._file = None self._fileOpened = False - self._fileName = '/tmp/fenrir_' + \ - str(os.getpid()) + '_' + str(datetime.utcnow().strftime('%Y-%m-%d_%H-%M-%S')) + '.log' - if file_name != '': + self._fileName = ( + "/tmp/fenrir_" + + str(os.getpid()) + + "_" + + str(datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S")) + + ".log" + ) + if file_name != "": self._fileName = file_name def initialize(self, environment): @@ -27,18 +33,18 @@ class DebugManager(): self.shutdown() except Exception as e: # Cannot use debug manager to log its own shutdown errors - print(f'DebugManager shutdown: Error during shutdown: {e}') + print(f"DebugManager shutdown: Error during shutdown: {e}") - def open_debug_file(self, file_name=''): + def open_debug_file(self, file_name=""): self._fileOpened = False - if file_name != '': + if file_name != "": self._fileName = file_name - if self._fileName != '': + if self._fileName != "": directory = os.path.dirname(self._fileName) if not os.path.exists(directory): pathlib.Path(directory).mkdir(parents=True, exist_ok=True) try: - self._file = open(self._fileName, 'a') + self._file = open(self._fileName, "a") # Set readable permissions for all users (644) os.chmod(self._fileName, 0o644) self._fileOpened = True @@ -46,44 +52,54 @@ class DebugManager(): print(e) def write_debug_out( - self, - text, - level=debug.DebugLevel.DEACTIVE, - on_any_level=False): + self, text, level=debug.DebugLevel.DEACTIVE, on_any_level=False + ): - mode = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'debug_mode') - if mode == '': - mode = 'FILE' - mode = mode.upper().split(',') - file_mode = 'FILE' in mode - print_mode = 'PRINT' in mode + mode = self.env["runtime"]["SettingsManager"].get_setting( + "general", "debug_mode" + ) + if mode == "": + mode = "FILE" + mode = mode.upper().split(",") + file_mode = "FILE" in mode + print_mode = "PRINT" in mode if ( - int(self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'debug_level')) < int(level)) and not ( - on_any_level and int(self.env['runtime']['SettingsManager'].get_setting_as_int( - 'general', 'debug_level')) > int(debug.DebugLevel.DEACTIVE)): + int( + self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "debug_level" + ) + ) + < int(level) + ) and not ( + on_any_level + and int( + self.env["runtime"]["SettingsManager"].get_setting_as_int( + "general", "debug_level" + ) + ) + > int(debug.DebugLevel.DEACTIVE) + ): if self._fileOpened: self.close_debug_file() return else: if not self._fileOpened and file_mode: self.open_debug_file() - timestamp = str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) + timestamp = str(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f")) if on_any_level: - level_info = 'INFO ANY' + level_info = "INFO ANY" else: level_info = str(level) # Changed order: text comes first, then level and timestamp - msg = text + ' - ' + level_info + ' ' + timestamp + msg = text + " - " + level_info + " " + timestamp if print_mode: print(msg) if file_mode: try: - self._file.write(msg + '\n') + self._file.write(msg + "\n") except Exception as e: print(e) diff --git a/src/fenrirscreenreader/core/dynamicVoiceMenu.py b/src/fenrirscreenreader/core/dynamicVoiceMenu.py index f1f4580b..50b7aef2 100644 --- a/src/fenrirscreenreader/core/dynamicVoiceMenu.py +++ b/src/fenrirscreenreader/core/dynamicVoiceMenu.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -import subprocess import importlib.util import os +import subprocess import time + from fenrirscreenreader.core import debug @@ -27,11 +28,12 @@ class DynamicVoiceCommand: def run(self): try: - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( f"Testing voice { self.voice} from { self.module}. Please wait.", - interrupt=True) + interrupt=True, + ) # Brief pause before testing to avoid speech overlap time.sleep(0.5) @@ -39,45 +41,57 @@ class DynamicVoiceCommand: # Test voice testResult, errorMsg = self.test_voice() if testResult: - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( "Voice test completed successfully. Navigate to Apply Tested Voice to use this voice.", interrupt=False, - flush=False) + flush=False, + ) # Store for confirmation (use same variables as # apply_tested_voice.py) - self.env['commandBuffer']['lastTestedModule'] = self.module - self.env['commandBuffer']['lastTestedVoice'] = self.voice - self.env['commandBuffer']['pendingVoiceModule'] = self.module - self.env['commandBuffer']['pendingVoiceVoice'] = self.voice - self.env['commandBuffer']['voiceTestCompleted'] = True + self.env["commandBuffer"]["lastTestedModule"] = self.module + self.env["commandBuffer"]["lastTestedVoice"] = self.voice + self.env["commandBuffer"]["pendingVoiceModule"] = self.module + self.env["commandBuffer"]["pendingVoiceVoice"] = self.voice + self.env["commandBuffer"]["voiceTestCompleted"] = True else: - self.env['runtime']['OutputManager'].present_text( - f"Voice test failed: {errorMsg}", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Voice test failed: {errorMsg}", + interrupt=False, + flush=False, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Voice selection error: {str(e)}", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Voice selection error: {str(e)}", + interrupt=False, + flush=False, + ) def test_voice(self): """Test voice with spd-say""" try: cmd = [ - 'spd-say', - '-C', - '-w', - '-o', + "spd-say", + "-C", + "-w", + "-o", self.module, - '-y', + "-y", self.voice, - self.testMessage] + self.testMessage, + ] result = subprocess.run( - cmd, timeout=8, capture_output=True, text=True) + cmd, timeout=8, capture_output=True, text=True + ) if result.returncode == 0: return True, "Voice test successful" else: - error_msg = result.stderr.strip( - ) if result.stderr else f"Command failed with return code {result.returncode}" + error_msg = ( + result.stderr.strip() + if result.stderr + else f"Command failed with return code {result.returncode}" + ) return False, error_msg except subprocess.TimeoutExpired: return False, "Voice test timed out" @@ -105,47 +119,55 @@ class DynamicApplyVoiceCommand: def run(self): try: - if not self.env['commandBuffer'].get('voiceTestCompleted', False): - self.env['runtime']['OutputManager'].present_text( - "No voice has been tested yet", interrupt=True) + if not self.env["commandBuffer"].get("voiceTestCompleted", False): + self.env["runtime"]["OutputManager"].present_text( + "No voice has been tested yet", interrupt=True + ) return - module = self.env['commandBuffer']['pendingVoiceModule'] - voice = self.env['commandBuffer']['pendingVoiceVoice'] + module = self.env["commandBuffer"]["pendingVoiceModule"] + voice = self.env["commandBuffer"]["pendingVoiceVoice"] - self.env['runtime']['OutputManager'].present_text( - f"Applying {voice} from {module}", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Applying {voice} from {module}", interrupt=True + ) # Debug: Show current settings - settings_manager = self.env['runtime']['SettingsManager'] - current_module = settings_manager.get_setting('speech', 'module') - current_voice = settings_manager.get_setting('speech', 'voice') - self.env['runtime']['OutputManager'].present_text( - f"Current: {current_voice} from {current_module}", interrupt=False, flush=False) + settings_manager = self.env["runtime"]["SettingsManager"] + current_module = settings_manager.get_setting("speech", "module") + current_voice = settings_manager.get_setting("speech", "voice") + self.env["runtime"]["OutputManager"].present_text( + f"Current: {current_voice} from {current_module}", + interrupt=False, + flush=False, + ) # Apply to runtime settings with fallback - settings_manager = self.env['runtime']['SettingsManager'] + settings_manager = self.env["runtime"]["SettingsManager"] # Store old values for safety - old_driver = settings_manager.get_setting('speech', 'driver') - old_module = settings_manager.get_setting('speech', 'module') - old_voice = settings_manager.get_setting('speech', 'voice') + old_driver = settings_manager.get_setting("speech", "driver") + old_module = settings_manager.get_setting("speech", "module") + old_voice = settings_manager.get_setting("speech", "voice") try: # Apply new settings to runtime only (use set_setting to update # settingArgDict) - settings_manager.set_setting('speech', 'driver', 'speechdDriver') - settings_manager.set_setting('speech', 'module', module) - settings_manager.set_setting('speech', 'voice', voice) + settings_manager.set_setting( + "speech", "driver", "speechdDriver" + ) + settings_manager.set_setting("speech", "module", module) + settings_manager.set_setting("speech", "voice", voice) # Apply settings to speech driver directly - if 'SpeechDriver' in self.env['runtime']: - SpeechDriver = self.env['runtime']['SpeechDriver'] + if "SpeechDriver" in self.env["runtime"]: + SpeechDriver = self.env["runtime"]["SpeechDriver"] # Get current module to see if we're changing modules current_module = settings_manager.get_setting( - 'speech', 'module') - module_changing = (current_module != module) + "speech", "module" + ) + module_changing = current_module != module # Set module and voice on driver instance first SpeechDriver.set_module(module) @@ -154,61 +176,75 @@ class DynamicApplyVoiceCommand: if module_changing: # Module change requires reinitializing the speech # driver - self.env['runtime']['OutputManager'].present_text( - f"Switching from {current_module} to {module} module", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + f"Switching from {current_module} to {module} module", + interrupt=True, + ) SpeechDriver.shutdown() SpeechDriver.initialize(self.env) # Re-set after initialization SpeechDriver.set_module(module) SpeechDriver.set_voice(voice) - self.env['runtime']['OutputManager'].present_text( - "Speech driver reinitialized", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Speech driver reinitialized", interrupt=True + ) # Debug: verify what was actually set - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( f"Speech driver now has module: { SpeechDriver.module}, voice: { - SpeechDriver.voice}", interrupt=True) + SpeechDriver.voice}", + interrupt=True, + ) # Force application by speaking a test message - self.env['runtime']['OutputManager'].present_text( - "Voice applied successfully! You should hear this in the new voice.", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Voice applied successfully! You should hear this in the new voice.", + interrupt=True, + ) # Brief pause then more speech to test time.sleep(1) - self.env['runtime']['OutputManager'].present_text( - "Use save settings to make permanent", interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + "Use save settings to make permanent", interrupt=True + ) # Clear pending state - self.env['commandBuffer']['voiceTestCompleted'] = False + self.env["commandBuffer"]["voiceTestCompleted"] = False # Exit vmenu after successful application - self.env['runtime']['VmenuManager'].set_active(False) + self.env["runtime"]["VmenuManager"].set_active(False) except Exception as e: # Revert on failure - settings_manager.settings['speech']['driver'] = old_driver - settings_manager.settings['speech']['module'] = old_module - settings_manager.settings['speech']['voice'] = old_voice + settings_manager.settings["speech"]["driver"] = old_driver + settings_manager.settings["speech"]["module"] = old_module + settings_manager.settings["speech"]["voice"] = old_voice # Try to reinitialize with old settings - if 'SpeechDriver' in self.env['runtime']: + if "SpeechDriver" in self.env["runtime"]: try: - SpeechDriver = self.env['runtime']['SpeechDriver'] + SpeechDriver = self.env["runtime"]["SpeechDriver"] SpeechDriver.shutdown() SpeechDriver.initialize(self.env) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'dynamicVoiceMenu: Error reinitializing speech driver: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "dynamicVoiceMenu: Error reinitializing speech driver: " + + str(e), + debug.DebugLevel.ERROR, + ) - self.env['runtime']['OutputManager'].present_text( + self.env["runtime"]["OutputManager"].present_text( f"Failed to apply voice, reverted: { - str(e)}", interrupt=False, flush=False) + str(e)}", + interrupt=False, + flush=False, + ) except Exception as e: - self.env['runtime']['OutputManager'].present_text( - f"Apply voice error: {str(e)}", interrupt=False, flush=False) + self.env["runtime"]["OutputManager"].present_text( + f"Apply voice error: {str(e)}", interrupt=False, flush=False + ) def set_callback(self, callback): pass @@ -229,10 +265,12 @@ def add_dynamic_voice_menus(VmenuManager): # Add apply voice command apply_command = DynamicApplyVoiceCommand(env) - voice_browser_menu['Apply Tested Voice Action'] = apply_command + voice_browser_menu["Apply Tested Voice Action"] = apply_command # Add modules as submenus - for module in modules[:8]: # Limit to 8 modules to keep menu manageable + for module in modules[ + :8 + ]: # Limit to 8 modules to keep menu manageable module_menu = {} # Get voices for this module @@ -244,40 +282,50 @@ def add_dynamic_voice_menus(VmenuManager): voice_command = DynamicVoiceCommand(module, voice, env) module_menu[f"{voice} Action"] = voice_command else: - module_menu['No voices available Action'] = create_info_command( - f"No voices found for {module}", env) + module_menu["No voices available Action"] = ( + create_info_command(f"No voices found for {module}", env) + ) voice_browser_menu[f"{module} Menu"] = module_menu # Add to main menu dict - VmenuManager.menuDict['Voice Browser Menu'] = voice_browser_menu + VmenuManager.menuDict["Voice Browser Menu"] = voice_browser_menu except Exception as e: # Use debug manager instead of print for error logging - if 'DebugManager' in env['runtime']: - env['runtime']['DebugManager'].write_debug_out( + if "DebugManager" in env["runtime"]: + env["runtime"]["DebugManager"].write_debug_out( f"Error creating dynamic voice menus: {e}", - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) else: print(f"Error creating dynamic voice menus: {e}") def create_info_command(message, env): """Create a simple info command""" + class InfoCommand: def __init__(self, message, env): self.message = message self.env = env - def initialize(self, environment): pass - def shutdown(self): pass - def get_description(self): return self.message + def initialize(self, environment): + pass + + def shutdown(self): + pass + + def get_description(self): + return self.message def run(self): - self.env['runtime']['OutputManager'].present_text( - self.message, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + self.message, interrupt=True + ) - def set_callback(self, callback): pass + def set_callback(self, callback): + pass return InfoCommand(message, env) @@ -286,9 +334,10 @@ def get_speechd_modules(): """Get available speech modules""" try: result = subprocess.run( - ['spd-say', '-O'], capture_output=True, text=True, timeout=5) + ["spd-say", "-O"], capture_output=True, text=True, timeout=5 + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") return [line.strip() for line in lines[1:] if line.strip()] except Exception: pass @@ -299,14 +348,18 @@ def get_module_voices(module): """Get voices for a module""" try: result = subprocess.run( - ['spd-say', '-o', module, '-L'], capture_output=True, text=True, timeout=8) + ["spd-say", "-o", module, "-L"], + capture_output=True, + text=True, + timeout=8, + ) if result.returncode == 0: - lines = result.stdout.strip().split('\n') + lines = result.stdout.strip().split("\n") voices = [] for line in lines[1:]: if not line.strip(): continue - if module.lower() == 'espeak-ng': + if module.lower() == "espeak-ng": voice = process_espeak_voice(line) if voice: voices.append(voice) @@ -326,6 +379,10 @@ def process_espeak_voice(voiceLine): return None lang_code = parts[-2].lower() variant = parts[-1].lower() - return f"{lang_code}+{variant}" if variant and variant != 'none' else lang_code + return ( + f"{lang_code}+{variant}" + if variant and variant != "none" + else lang_code + ) except Exception: return None diff --git a/src/fenrirscreenreader/core/environment.py b/src/fenrirscreenreader/core/environment.py index d06166af..a14358b5 100644 --- a/src/fenrirscreenreader/core/environment.py +++ b/src/fenrirscreenreader/core/environment.py @@ -2,29 +2,29 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. +from fenrirscreenreader.core import commandData from fenrirscreenreader.core import debug -from fenrirscreenreader.core.settingsData import settings_data +from fenrirscreenreader.core.generalData import general_data +from fenrirscreenreader.core.inputData import input_data +from fenrirscreenreader.core.outputData import output_data +from fenrirscreenreader.core.punctuationData import punctuation_data from fenrirscreenreader.core.runtimeData import runtime_data from fenrirscreenreader.core.screenData import screen_data -from fenrirscreenreader.core.outputData import output_data -from fenrirscreenreader.core.generalData import general_data -from fenrirscreenreader.core import commandData -from fenrirscreenreader.core.inputData import input_data -from fenrirscreenreader.core.punctuationData import punctuation_data +from fenrirscreenreader.core.settingsData import settings_data environment = { - 'screen': screen_data, - 'runtime': runtime_data, - 'general': general_data, - 'settings': settings_data, - 'commandInfo': commandData.command_info, - 'commandBuffer': commandData.command_buffer, - 'input': input_data, - 'punctuation': punctuation_data, - 'output': output_data, - 'soundIcons': {}, - 'bindings': {}, - 'rawBindings': {}, + "screen": screen_data, + "runtime": runtime_data, + "general": general_data, + "settings": settings_data, + "commandInfo": commandData.command_info, + "commandBuffer": commandData.command_buffer, + "input": input_data, + "punctuation": punctuation_data, + "output": output_data, + "soundIcons": {}, + "bindings": {}, + "rawBindings": {}, } diff --git a/src/fenrirscreenreader/core/eventData.py b/src/fenrirscreenreader/core/eventData.py index bcfd9418..7c90b495 100644 --- a/src/fenrirscreenreader/core/eventData.py +++ b/src/fenrirscreenreader/core/eventData.py @@ -2,10 +2,11 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +from enum import Enum from fenrirscreenreader.core import debug -from enum import Enum class FenrirEventType(Enum): diff --git a/src/fenrirscreenreader/core/eventManager.py b/src/fenrirscreenreader/core/eventManager.py index 6c43c949..a42919c3 100644 --- a/src/fenrirscreenreader/core/eventManager.py +++ b/src/fenrirscreenreader/core/eventManager.py @@ -2,18 +2,19 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import time +from ctypes import c_bool +from multiprocessing import Queue +from multiprocessing.sharedctypes import Value +from queue import Empty from fenrirscreenreader.core import debug from fenrirscreenreader.core.eventData import FenrirEventType -from queue import Empty -import time -from multiprocessing import Queue -from multiprocessing.sharedctypes import Value -from ctypes import c_bool -class EventManager(): +class EventManager: def __init__(self): self.running = Value(c_bool, True) # Bounded queue to prevent memory exhaustion @@ -33,40 +34,45 @@ class EventManager(): # print('NET loop ' + str(time.time() - st)) def event_dispatcher(self, event): - self.env['runtime']['DebugManager'].write_debug_out( - 'EventManager:event_dispatcher:start: event: ' + str(event['Type']), debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "EventManager:event_dispatcher:start: event: " + + str(event["Type"]), + debug.DebugLevel.INFO, + ) if not event: return - if not event['Type']: + if not event["Type"]: return - if event['Type'] == FenrirEventType.ignore: + if event["Type"] == FenrirEventType.ignore: return - elif event['Type'] == FenrirEventType.stop_main_loop: + elif event["Type"] == FenrirEventType.stop_main_loop: self.handle_stop_main_loop(event) - elif event['Type'] == FenrirEventType.screen_update: - self.env['runtime']['FenrirManager'].handle_screen_update(event) - elif event['Type'] == FenrirEventType.keyboard_input: - self.env['runtime']['FenrirManager'].handle_input(event) - elif event['Type'] == FenrirEventType.plug_input_device: - self.env['runtime']['FenrirManager'].handle_plug_input_device(event) - elif event['Type'] == FenrirEventType.screen_changed: - self.env['runtime']['FenrirManager'].handle_screen_change(event) - elif event['Type'] == FenrirEventType.heart_beat: - self.env['runtime']['FenrirManager'].handle_heart_beat(event) - elif event['Type'] == FenrirEventType.execute_command: - self.env['runtime']['FenrirManager'].handle_execute_command(event) - elif event['Type'] == FenrirEventType.byte_input: - self.env['runtime']['FenrirManager'].handle_byte_input(event) - elif event['Type'] == FenrirEventType.remote_incomming: - self.env['runtime']['FenrirManager'].handle_remote_incomming(event) + elif event["Type"] == FenrirEventType.screen_update: + self.env["runtime"]["FenrirManager"].handle_screen_update(event) + elif event["Type"] == FenrirEventType.keyboard_input: + self.env["runtime"]["FenrirManager"].handle_input(event) + elif event["Type"] == FenrirEventType.plug_input_device: + self.env["runtime"]["FenrirManager"].handle_plug_input_device( + event + ) + elif event["Type"] == FenrirEventType.screen_changed: + self.env["runtime"]["FenrirManager"].handle_screen_change(event) + elif event["Type"] == FenrirEventType.heart_beat: + self.env["runtime"]["FenrirManager"].handle_heart_beat(event) + elif event["Type"] == FenrirEventType.execute_command: + self.env["runtime"]["FenrirManager"].handle_execute_command(event) + elif event["Type"] == FenrirEventType.byte_input: + self.env["runtime"]["FenrirManager"].handle_byte_input(event) + elif event["Type"] == FenrirEventType.remote_incomming: + self.env["runtime"]["FenrirManager"].handle_remote_incomming(event) def is_main_event_loop_running(self): return self.running.value == 1 def start_main_event_loop(self): self.running.value = 1 - while (self.is_main_event_loop_running()): + while self.is_main_event_loop_running(): self.proceed_event_loop() def handle_stop_main_loop(self, event): @@ -75,7 +81,8 @@ class EventManager(): def stop_main_event_loop(self): self._eventQueue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + {"Type": FenrirEventType.stop_main_loop, "data": None} + ) def clean_event_queue(self): if self._eventQueue.empty(): @@ -108,12 +115,14 @@ class EventManager(): # Queue full - drop oldest event and add new one for critical # events if event in [ - FenrirEventType.screen_update, - FenrirEventType.keyboard_input]: + FenrirEventType.screen_update, + FenrirEventType.keyboard_input, + ]: try: self._eventQueue.get_nowait() # Remove oldest self._eventQueue.put( - {"Type": event, "data": data}, timeout=0.1) + {"Type": event, "data": data}, timeout=0.1 + ) except BaseException: pass # If still can't add, drop the event # For non-critical events, just drop them if queue is full diff --git a/src/fenrirscreenreader/core/fenrirManager.py b/src/fenrirscreenreader/core/fenrirManager.py index c350106d..039f300a 100644 --- a/src/fenrirscreenreader/core/fenrirManager.py +++ b/src/fenrirscreenreader/core/fenrirManager.py @@ -4,223 +4,299 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. -import signal -import time import os +import signal import sys +import time -from fenrirscreenreader.core.i18n import _ -from fenrirscreenreader.core import settingsManager from fenrirscreenreader.core import debug +from fenrirscreenreader.core import settingsManager from fenrirscreenreader.core.eventData import FenrirEventType +from fenrirscreenreader.core.i18n import _ -class FenrirManager(): +class FenrirManager: def __init__(self, cliArgs): self.is_initialized = False + self.environment = None + self.signal_handlers_set = False + try: - self.environment = settingsManager.SettingsManager().init_fenrir_config(cliArgs, self) + self.environment = ( + settingsManager.SettingsManager().init_fenrir_config( + cliArgs, self + ) + ) if not self.environment: raise RuntimeError( - 'Cannot Initialize. Maybe the configfile is not available or not parseable') - except RuntimeError: + "Cannot Initialize. Maybe the configfile is not available or not parseable" + ) + + self.environment["runtime"]["OutputManager"].present_text( + _("Start Fenrir"), sound_icon="ScreenReaderOn", interrupt=True + ) + + # Set signal handlers after successful initialization + signal.signal(signal.SIGINT, self.capture_signal) + signal.signal(signal.SIGTERM, self.capture_signal) + self.signal_handlers_set = True + + self.is_initialized = True + self.modifierInput = False + self.singleKeyCommand = False + self.command = "" + self.set_process_name() + + except Exception as e: + # Clean up any partial initialization + self.cleanup_on_error() raise - self.environment['runtime']['OutputManager'].present_text( - _("Start Fenrir"), sound_icon ='ScreenReaderOn', interrupt=True) - signal.signal(signal.SIGINT, self.capture_signal) - signal.signal(signal.SIGTERM, self.capture_signal) - - self.is_initialized = True - self.modifierInput = False - self.singleKeyCommand = False - self.command = '' - self.set_process_name() - def proceed(self): if not self.is_initialized: return - self.environment['runtime']['EventManager'].start_main_event_loop() + self.environment["runtime"]["EventManager"].start_main_event_loop() self.shutdown() def handle_input(self, event): - self.environment['runtime']['DebugManager'].write_debug_out( - 'DEBUG INPUT fenrirMan:' + str(event), debug.DebugLevel.INFO) + self.environment["runtime"]["DebugManager"].write_debug_out( + "DEBUG INPUT fenrirMan:" + str(event), debug.DebugLevel.INFO + ) - if not event['data']: - event['data'] = self.environment['runtime']['InputManager'].get_input_event() + if not event["data"]: + event["data"] = self.environment["runtime"][ + "InputManager" + ].get_input_event() - if event['data']: - event['data']['EventName'] = self.environment['runtime']['InputManager'].convert_event_name( - event['data']['EventName']) - self.environment['runtime']['InputManager'].handle_input_event( - event['data']) + if event["data"]: + event["data"]["EventName"] = self.environment["runtime"][ + "InputManager" + ].convert_event_name(event["data"]["EventName"]) + self.environment["runtime"]["InputManager"].handle_input_event( + event["data"] + ) else: return - if self.environment['runtime']['InputManager'].no_key_pressed(): - self.environment['runtime']['InputManager'].clear_last_deep_input() + if self.environment["runtime"]["InputManager"].no_key_pressed(): + self.environment["runtime"]["InputManager"].clear_last_deep_input() - if self.environment['runtime']['ScreenManager'].is_ignored_screen(): - self.environment['runtime']['InputManager'].write_event_buffer() + if self.environment["runtime"]["ScreenManager"].is_ignored_screen(): + self.environment["runtime"]["InputManager"].write_event_buffer() else: - if self.environment['runtime']['HelpManager'].is_tutorial_mode(): - self.environment['runtime']['InputManager'].clear_event_buffer() - self.environment['runtime']['InputManager'].key_echo( - event['data']) + if self.environment["runtime"]["HelpManager"].is_tutorial_mode(): + self.environment["runtime"][ + "InputManager" + ].clear_event_buffer() + self.environment["runtime"]["InputManager"].key_echo( + event["data"] + ) - if self.environment['runtime']['VmenuManager'].get_active(): - self.environment['runtime']['InputManager'].clear_event_buffer() + if self.environment["runtime"]["VmenuManager"].get_active(): + self.environment["runtime"][ + "InputManager" + ].clear_event_buffer() self.detect_shortcut_command() if self.modifierInput: - self.environment['runtime']['InputManager'].clear_event_buffer() + self.environment["runtime"][ + "InputManager" + ].clear_event_buffer() if self.singleKeyCommand: - if self.environment['runtime']['InputManager'].no_key_pressed(): - self.environment['runtime']['InputManager'].clear_event_buffer() + if self.environment["runtime"][ + "InputManager" + ].no_key_pressed(): + self.environment["runtime"][ + "InputManager" + ].clear_event_buffer() else: - self.environment['runtime']['InputManager'].write_event_buffer() + self.environment["runtime"][ + "InputManager" + ].write_event_buffer() - if self.environment['runtime']['InputManager'].no_key_pressed(): + if self.environment["runtime"]["InputManager"].no_key_pressed(): self.modifierInput = False self.singleKeyCommand = False - self.environment['runtime']['InputManager'].write_event_buffer() - self.environment['runtime']['InputManager'].handle_device_grab() + self.environment["runtime"]["InputManager"].write_event_buffer() + self.environment["runtime"]["InputManager"].handle_device_grab() - if self.environment['input']['keyForeward'] > 0: - self.environment['input']['keyForeward'] -= 1 + if self.environment["input"]["keyForeward"] > 0: + self.environment["input"]["keyForeward"] -= 1 - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onKeyInput') + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onKeyInput" + ) def handle_byte_input(self, event): - if not event['data'] or event['data'] == b'': + if not event["data"] or event["data"] == b"": return - self.environment['runtime']['ByteManager'].handle_byte_input( - event['data']) - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onByteInput') + self.environment["runtime"]["ByteManager"].handle_byte_input( + event["data"] + ) + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onByteInput" + ) def handle_execute_command(self, event): - if not event['data'] or event['data'] == '': + if not event["data"] or event["data"] == "": return - current_command = event['data'] + current_command = event["data"] # special modes - if self.environment['runtime']['HelpManager'].is_tutorial_mode(): - if self.environment['runtime']['CommandManager'].command_exists( - current_command, 'help'): - self.environment['runtime']['CommandManager'].execute_command( - current_command, 'help') + if self.environment["runtime"]["HelpManager"].is_tutorial_mode(): + if self.environment["runtime"]["CommandManager"].command_exists( + current_command, "help" + ): + self.environment["runtime"]["CommandManager"].execute_command( + current_command, "help" + ) return - elif self.environment['runtime']['VmenuManager'].get_active(): - if self.environment['runtime']['CommandManager'].command_exists( - current_command, 'vmenu-navigation'): - self.environment['runtime']['CommandManager'].execute_command( - current_command, 'vmenu-navigation') + elif self.environment["runtime"]["VmenuManager"].get_active(): + if self.environment["runtime"]["CommandManager"].command_exists( + current_command, "vmenu-navigation" + ): + self.environment["runtime"]["CommandManager"].execute_command( + current_command, "vmenu-navigation" + ) return # default - self.environment['runtime']['CommandManager'].execute_command( - current_command, 'commands') + self.environment["runtime"]["CommandManager"].execute_command( + current_command, "commands" + ) def handle_remote_incomming(self, event): - if not event['data']: + if not event["data"]: return - self.environment['runtime']['RemoteManager'].handle_remote_incomming( - event['data']) + self.environment["runtime"]["RemoteManager"].handle_remote_incomming( + event["data"] + ) def handle_screen_change(self, event): - self.environment['runtime']['ScreenManager'].handle_screen_change( - event['data']) - if self.environment['runtime']['VmenuManager'].get_active(): + self.environment["runtime"]["ScreenManager"].handle_screen_change( + event["data"] + ) + if self.environment["runtime"]["VmenuManager"].get_active(): return - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onScreenChanged') - self.environment['runtime']['ScreenDriver'].get_curr_screen() + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onScreenChanged" + ) + self.environment["runtime"]["ScreenDriver"].get_curr_screen() def handle_screen_update(self, event): - self.environment['runtime']['ScreenManager'].handle_screen_update( - event['data']) + self.environment["runtime"]["ScreenManager"].handle_screen_update( + event["data"] + ) - if time.time() - \ - self.environment['runtime']['InputManager'].get_last_input_time() >= 0.3: - self.environment['runtime']['InputManager'].clear_last_deep_input() + if ( + time.time() + - self.environment["runtime"]["InputManager"].get_last_input_time() + >= 0.3 + ): + self.environment["runtime"]["InputManager"].clear_last_deep_input() - if (self.environment['runtime']['CursorManager'].is_cursor_vertical_move( - ) or self.environment['runtime']['CursorManager'].is_cursor_horizontal_move()): - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onCursorChange') + if ( + self.environment["runtime"][ + "CursorManager" + ].is_cursor_vertical_move() + or self.environment["runtime"][ + "CursorManager" + ].is_cursor_horizontal_move() + ): + self.environment["runtime"][ + "CommandManager" + ].execute_default_trigger("onCursorChange") - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onScreenUpdate') - self.environment['runtime']['InputManager'].clear_last_deep_input() + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onScreenUpdate" + ) + self.environment["runtime"]["InputManager"].clear_last_deep_input() def handle_plug_input_device(self, event): try: - self.environment['runtime']['InputManager'].set_last_detected_devices( - event['data']) + self.environment["runtime"][ + "InputManager" + ].set_last_detected_devices(event["data"]) except Exception as e: - self.environment['runtime']['DebugManager'].write_debug_out( - 'handle_plug_input_device: Error setting last detected devices: ' + str(e), - debug.DebugLevel.ERROR) - self.environment['runtime']['InputManager'].handle_plug_input_device( - event['data']) - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onPlugInputDevice', force=True) - self.environment['runtime']['InputManager'].set_last_detected_devices( - None) + self.environment["runtime"]["DebugManager"].write_debug_out( + "handle_plug_input_device: Error setting last detected devices: " + + str(e), + debug.DebugLevel.ERROR, + ) + self.environment["runtime"]["InputManager"].handle_plug_input_device( + event["data"] + ) + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onPlugInputDevice", force=True + ) + self.environment["runtime"]["InputManager"].set_last_detected_devices( + None + ) def handle_heart_beat(self, event): - self.environment['runtime']['CommandManager'].execute_default_trigger( - 'onHeartBeat', force=True) + self.environment["runtime"]["CommandManager"].execute_default_trigger( + "onHeartBeat", force=True + ) def detect_shortcut_command(self): - if self.environment['input']['keyForeward'] > 0: + if self.environment["input"]["keyForeward"] > 0: return - if len(self.environment['input']['prevInput']) > len( - self.environment['input']['currInput']): + if len(self.environment["input"]["prevInput"]) > len( + self.environment["input"]["currInput"] + ): return - if self.environment['runtime']['InputManager'].is_key_press(): - self.modifierInput = self.environment['runtime']['InputManager'].curr_key_is_modifier( - ) + if self.environment["runtime"]["InputManager"].is_key_press(): + self.modifierInput = self.environment["runtime"][ + "InputManager" + ].curr_key_is_modifier() else: - if not self.environment['runtime']['InputManager'].no_key_pressed(): + if not self.environment["runtime"][ + "InputManager" + ].no_key_pressed(): if self.singleKeyCommand: - self.singleKeyCommand = len( - self.environment['input']['currInput']) == 1 + self.singleKeyCommand = ( + len(self.environment["input"]["currInput"]) == 1 + ) if not ( - self.singleKeyCommand and self.environment['runtime']['InputManager'].no_key_pressed()): - current_shortcut = self.environment['runtime']['InputManager'].get_curr_shortcut( - ) - self.command = self.environment['runtime']['InputManager'].get_command_for_shortcut( - current_shortcut) + self.singleKeyCommand + and self.environment["runtime"]["InputManager"].no_key_pressed() + ): + current_shortcut = self.environment["runtime"][ + "InputManager" + ].get_curr_shortcut() + self.command = self.environment["runtime"][ + "InputManager" + ].get_command_for_shortcut(current_shortcut) if not self.modifierInput: - if self.environment['runtime']['InputManager'].is_key_press(): - if self.command != '': + if self.environment["runtime"]["InputManager"].is_key_press(): + if self.command != "": self.singleKeyCommand = True if not (self.singleKeyCommand or self.modifierInput): return # fire event - if self.command != '': + if self.command != "": if self.modifierInput: - self.environment['runtime']['EventManager'].put_to_event_queue( - FenrirEventType.execute_command, self.command) - self.command = '' + self.environment["runtime"]["EventManager"].put_to_event_queue( + FenrirEventType.execute_command, self.command + ) + self.command = "" else: if self.singleKeyCommand: - self.environment['runtime']['EventManager'].put_to_event_queue( - FenrirEventType.execute_command, self.command) - self.command = '' + self.environment["runtime"][ + "EventManager" + ].put_to_event_queue( + FenrirEventType.execute_command, self.command + ) + self.command = "" - def set_process_name(self, name='fenrir'): + def set_process_name(self, name="fenrir"): """Attempts to set the process name to 'fenrir'.""" try: from setproctitle import setproctitle @@ -231,40 +307,148 @@ class FenrirManager(): return True try: - from ctypes import cdll, byref, create_string_buffer - libc = cdll.LoadLibrary('libc.so.6') + from ctypes import byref + from ctypes import cdll + from ctypes import create_string_buffer + + libc = cdll.LoadLibrary("libc.so.6") string_buffer = create_string_buffer(len(name) + 1) - string_buffer.value = bytes(name, 'UTF-8') + string_buffer.value = bytes(name, "UTF-8") libc.prctl(15, byref(string_buffer), 0, 0, 0) return True except Exception as e: - self.environment['runtime']['DebugManager'].write_debug_out( - 'setProcName: Error setting process name: ' + str(e), debug.DebugLevel.ERROR) + self.environment["runtime"]["DebugManager"].write_debug_out( + "setProcName: Error setting process name: " + str(e), + debug.DebugLevel.ERROR, + ) return False def shutdown_request(self): try: - self.environment['runtime']['EventManager'].stop_main_event_loop() + self.environment["runtime"]["EventManager"].stop_main_event_loop() except Exception as e: - self.environment['runtime']['DebugManager'].write_debug_out( - 'shutdown_request: Error stopping main event loop: ' + str(e), - debug.DebugLevel.ERROR) + self.environment["runtime"]["DebugManager"].write_debug_out( + "shutdown_request: Error stopping main event loop: " + str(e), + debug.DebugLevel.ERROR, + ) def capture_signal(self, sigInit, frame): self.shutdown_request() def shutdown(self): - self.environment['runtime']['InputManager'].ungrab_all_devices() - self.environment['runtime']['EventManager'].stop_main_event_loop() - self.environment['runtime']['OutputManager'].present_text( - _("Quit Fenrir"), sound_icon ='ScreenReaderOff', interrupt=True) - self.environment['runtime']['EventManager'].clean_event_queue() + self.environment["runtime"]["InputManager"].ungrab_all_devices() + self.environment["runtime"]["EventManager"].stop_main_event_loop() + self.environment["runtime"]["OutputManager"].present_text( + _("Quit Fenrir"), sound_icon="ScreenReaderOff", interrupt=True + ) + self.environment["runtime"]["EventManager"].clean_event_queue() time.sleep(0.6) - for currentManager in self.environment['general']['managerList']: - if self.environment['runtime'][currentManager]: - self.environment['runtime'][currentManager].shutdown() - del self.environment['runtime'][currentManager] + for currentManager in self.environment["general"]["managerList"]: + if self.environment["runtime"][currentManager]: + self.environment["runtime"][currentManager].shutdown() + del self.environment["runtime"][currentManager] self.environment = None + + def cleanup_on_error(self): + """Clean up partially initialized state when initialization fails""" + try: + # Reset signal handlers to default if they were set + if self.signal_handlers_set: + signal.signal(signal.SIGINT, signal.SIG_DFL) + signal.signal(signal.SIGTERM, signal.SIG_DFL) + self.signal_handlers_set = False + + # Clean up any initialized managers + if self.environment: + try: + # Try to ungrab devices if input manager exists + if ( + "runtime" in self.environment + and "InputManager" in self.environment["runtime"] + ): + if self.environment["runtime"]["InputManager"]: + self.environment["runtime"][ + "InputManager" + ].ungrab_all_devices() + except Exception: + pass # Ignore errors during cleanup + + try: + # Try to stop event manager if it exists + if ( + "runtime" in self.environment + and "EventManager" in self.environment["runtime"] + ): + if self.environment["runtime"]["EventManager"]: + self.environment["runtime"][ + "EventManager" + ].stop_main_event_loop() + except Exception: + pass # Ignore errors during cleanup + + try: + # Try to clean up all managers + if ( + "general" in self.environment + and "managerList" in self.environment["general"] + ): + for currentManager in self.environment["general"][ + "managerList" + ]: + if ( + "runtime" in self.environment + and currentManager + in self.environment["runtime"] + and self.environment["runtime"][currentManager] + ): + try: + self.environment["runtime"][ + currentManager + ].shutdown() + del self.environment["runtime"][ + currentManager + ] + except Exception: + pass # Ignore errors during cleanup + except Exception: + pass # Ignore errors during cleanup + + # Clean up socket files that might not be removed by the driver + try: + socket_file = None + if ( + "runtime" in self.environment + and "SettingsManager" in self.environment["runtime"] + ): + try: + socket_file = self.environment["runtime"][ + "SettingsManager" + ].get_setting("remote", "socket_file") + except Exception: + pass # Use default socket file path + + if not socket_file: + # Use default socket file paths + socket_file = "/tmp/fenrirscreenreader-deamon.sock" + if os.path.exists(socket_file): + os.unlink(socket_file) + + # Also try PID-based socket file + pid_socket_file = ( + "/tmp/fenrirscreenreader-" + + str(os.getpid()) + + ".sock" + ) + if os.path.exists(pid_socket_file): + os.unlink(pid_socket_file) + elif os.path.exists(socket_file): + os.unlink(socket_file) + except Exception: + pass # Ignore errors during socket cleanup + + self.environment = None + except Exception: + pass # Ignore all errors during error cleanup diff --git a/src/fenrirscreenreader/core/generalData.py b/src/fenrirscreenreader/core/generalData.py index 7ebf3c04..d91768bd 100644 --- a/src/fenrirscreenreader/core/generalData.py +++ b/src/fenrirscreenreader/core/generalData.py @@ -2,50 +2,51 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug general_data = { - 'args': None, - 'tutorialMode': False, - 'curr_user': '', - 'prev_user': '', - 'managerList': [ - 'AttributeManager', - 'PunctuationManager', - 'ByteManager', - 'CursorManager', - 'ApplicationManager', - 'CommandManager', - 'ScreenManager', - 'InputManager', - 'OutputManager', - 'HelpManager', - 'MemoryManager', - 'EventManager', - 'ProcessManager', - 'VmenuManager', - 'QuickMenuManager', - 'RemoteManager', - 'SettingsManager', - 'SayAllManager', - 'TableManager', - 'TextManager', - 'BarrierManager', - 'DebugManager'], - 'commandFolderList': [ - 'commands', - 'onKeyInput', - 'onByteInput', - 'onCursorChange', - 'onScreenUpdate', - 'onScreenChanged', - 'onHeartBeat', - 'onPlugInputDevice', - 'onApplicationChange', - 'onSwitchApplicationProfile', - 'help', - 'vmenu-navigation', + "args": None, + "tutorialMode": False, + "curr_user": "", + "prev_user": "", + "managerList": [ + "AttributeManager", + "PunctuationManager", + "ByteManager", + "CursorManager", + "ApplicationManager", + "CommandManager", + "ScreenManager", + "InputManager", + "OutputManager", + "HelpManager", + "MemoryManager", + "EventManager", + "ProcessManager", + "VmenuManager", + "QuickMenuManager", + "RemoteManager", + "SettingsManager", + "SayAllManager", + "TableManager", + "TextManager", + "BarrierManager", + "DebugManager", + ], + "commandFolderList": [ + "commands", + "onKeyInput", + "onByteInput", + "onCursorChange", + "onScreenUpdate", + "onScreenChanged", + "onHeartBeat", + "onPlugInputDevice", + "onApplicationChange", + "onSwitchApplicationProfile", + "help", + "vmenu-navigation", ], } diff --git a/src/fenrirscreenreader/core/helpManager.py b/src/fenrirscreenreader/core/helpManager.py index 1afec0a5..23053cb7 100755 --- a/src/fenrirscreenreader/core/helpManager.py +++ b/src/fenrirscreenreader/core/helpManager.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ -class HelpManager(): +class HelpManager: def __init__(self): self.helpDict = {} self.tutorialListIndex = None @@ -20,96 +20,109 @@ class HelpManager(): pass def toggle_tutorial_mode(self): - self.set_tutorial_mode(not self.env['general']['tutorialMode']) + self.set_tutorial_mode(not self.env["general"]["tutorialMode"]) def set_tutorial_mode(self, newTutorialMode): - if self.env['runtime']['VmenuManager'].get_active(): + if self.env["runtime"]["VmenuManager"].get_active(): return - self.env['general']['tutorialMode'] = newTutorialMode + self.env["general"]["tutorialMode"] = newTutorialMode if newTutorialMode: self.create_help_dict() - self.env['bindings'][str([1, ['KEY_ESC']]) - ] = 'TOGGLE_TUTORIAL_MODE' - self.env['bindings'][str([1, ['KEY_UP']])] = 'PREV_HELP' - self.env['bindings'][str([1, ['KEY_DOWN']])] = 'NEXT_HELP' - self.env['bindings'][str([1, ['KEY_SPACE']])] = 'CURR_HELP' + self.env["bindings"][ + str([1, ["KEY_ESC"]]) + ] = "TOGGLE_TUTORIAL_MODE" + self.env["bindings"][str([1, ["KEY_UP"]])] = "PREV_HELP" + self.env["bindings"][str([1, ["KEY_DOWN"]])] = "NEXT_HELP" + self.env["bindings"][str([1, ["KEY_SPACE"]])] = "CURR_HELP" else: try: - self.env['bindings'] = self.env['runtime']['SettingsManager'].get_binding_backup( - ) + self.env["bindings"] = self.env["runtime"][ + "SettingsManager" + ].get_binding_backup() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'HelpManager set_tutorial_mode: Error restoring binding backup: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "HelpManager set_tutorial_mode: Error restoring binding backup: " + + str(e), + debug.DebugLevel.ERROR, + ) def is_tutorial_mode(self): - return self.env['general']['tutorialMode'] + return self.env["general"]["tutorialMode"] def get_formatted_shortcut_for_command(self, command): shortcut = [] raw_shortcut = [] try: - raw_shortcut = list(self.env['bindings'].keys())[ - list(self.env['bindings'].values()).index(command)] - raw_shortcut = self.env['rawBindings'][raw_shortcut] + raw_shortcut = list(self.env["bindings"].keys())[ + list(self.env["bindings"].values()).index(command) + ] + raw_shortcut = self.env["rawBindings"][raw_shortcut] # prefer numbers for multitap if raw_shortcut[0] in range(2, 9): - formatted_key = str(raw_shortcut[0]) + ' times ' + formatted_key = str(raw_shortcut[0]) + " times " shortcut.append(formatted_key) # prefer metha keys for k in [ - 'KEY_FENRIR', - 'KEY_SCRIPT', - 'KEY_CTRL', - 'KEY_SHIFT', - 'KEY_ALT', - 'KEY_META']: + "KEY_FENRIR", + "KEY_SCRIPT", + "KEY_CTRL", + "KEY_SHIFT", + "KEY_ALT", + "KEY_META", + ]: if k in raw_shortcut[1]: formatted_key = k formatted_key = formatted_key.lower() - formatted_key = formatted_key.replace('key_kp', ' keypad ') - formatted_key = formatted_key.replace('key_', ' ') + formatted_key = formatted_key.replace("key_kp", " keypad ") + formatted_key = formatted_key.replace("key_", " ") shortcut.append(formatted_key) raw_shortcut[1].remove(k) # handle other keys for k in raw_shortcut[1]: formatted_key = k formatted_key = formatted_key.lower() - formatted_key = formatted_key.replace('key_kp', ' keypad ') - formatted_key = formatted_key.replace('key_', ' ') + formatted_key = formatted_key.replace("key_kp", " keypad ") + formatted_key = formatted_key.replace("key_", " ") shortcut.append(formatted_key) except Exception as e: - return '' + return "" shortcut = str(shortcut) - shortcut = shortcut.replace('[', '') - shortcut = shortcut.replace(']', '') - shortcut = shortcut.replace("'", '') + shortcut = shortcut.replace("[", "") + shortcut = shortcut.replace("]", "") + shortcut = shortcut.replace("'", "") return shortcut - def get_command_help_text(self, command, section='commands'): + def get_command_help_text(self, command, section="commands"): command_name = command.lower() - command_name = command_name.split('__-__')[0] - command_name = command_name.replace('_', ' ') - command_name = command_name.replace('_', ' ') - if command == 'TOGGLE_TUTORIAL_MODE': - command_description = _('toggles the tutorial mode') + command_name = command_name.split("__-__")[0] + command_name = command_name.replace("_", " ") + command_name = command_name.replace("_", " ") + if command == "TOGGLE_TUTORIAL_MODE": + command_description = _("toggles the tutorial mode") else: - command_description = self.env['runtime']['CommandManager'].get_command_description( - command, section='commands') - if command_description == '': - command_description = 'no Description available' + command_description = self.env["runtime"][ + "CommandManager" + ].get_command_description(command, section="commands") + if command_description == "": + command_description = "no Description available" command_shortcut = self.get_formatted_shortcut_for_command(command) - if command_shortcut == '': - command_shortcut = 'unbound' - helptext = command_name + ', Shortcut ' + \ - command_shortcut + ', Description ' + command_description + if command_shortcut == "": + command_shortcut = "unbound" + helptext = ( + command_name + + ", Shortcut " + + command_shortcut + + ", Description " + + command_description + ) return helptext - def create_help_dict(self, section='commands'): + def create_help_dict(self, section="commands"): self.helpDict = {} - for command in sorted(self.env['commands'][section].keys()): + for command in sorted(self.env["commands"][section].keys()): self.helpDict[len(self.helpDict)] = self.get_command_help_text( - command, section) + command, section + ) if len(self.helpDict) > 0: self.tutorialListIndex = 0 else: @@ -117,7 +130,7 @@ class HelpManager(): def get_help_for_current_index(self): if self.tutorialListIndex is None: - return '' + return "" return self.helpDict[self.tutorialListIndex] def next_index(self): diff --git a/src/fenrirscreenreader/core/i18n.py b/src/fenrirscreenreader/core/i18n.py index d7636c12..f68b8941 100644 --- a/src/fenrirscreenreader/core/i18n.py +++ b/src/fenrirscreenreader/core/i18n.py @@ -2,11 +2,11 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. +import builtins import gettext import locale -import builtins # the only function we really need to call here is gettext.install. # Python3 has simplified this. diff --git a/src/fenrirscreenreader/core/inputData.py b/src/fenrirscreenreader/core/inputData.py index 4e8d3840..68998c22 100644 --- a/src/fenrirscreenreader/core/inputData.py +++ b/src/fenrirscreenreader/core/inputData.py @@ -2,599 +2,601 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import time +from fenrirscreenreader.core import debug + input_data = { - 'currInput': [], - 'prevDeepestInput': [], - 'eventBuffer': [], - 'shortcut_repeat': 0, - 'fenrirKey': [], - 'scriptKey': [], - 'keyForeward': 0, - 'lastInputTime': time.time(), - 'oldNumLock': True, - 'newNumLock': True, - 'oldScrollLock': True, - 'newScrollLock': True, - 'oldCapsLock': False, - 'newCapsLock': False + "currInput": [], + "prevDeepestInput": [], + "eventBuffer": [], + "shortcut_repeat": 0, + "fenrirKey": [], + "scriptKey": [], + "keyForeward": 0, + "lastInputTime": time.time(), + "oldNumLock": True, + "newNumLock": True, + "oldScrollLock": True, + "newScrollLock": True, + "oldCapsLock": False, + "newCapsLock": False, } input_event = { - 'EventName': '', - 'EventValue': '', - 'EventSec': 0, - 'EventUsec': 0, - 'EventState': 0, + "EventName": "", + "EventValue": "", + "EventSec": 0, + "EventUsec": 0, + "EventState": 0, } key_names = [ - 'KEY_RESERVED', - 'KEY_ESC', - 'KEY_1', - 'KEY_2', - 'KEY_3', - 'KEY_4', - 'KEY_5', - 'KEY_6', - 'KEY_7', - 'KEY_8', - 'KEY_9', - 'KEY_0', - 'KEY_MINUS', - 'KEY_EQUAL', - 'KEY_BACKSPACE', - 'KEY_TAB', - 'KEY_Q', - 'KEY_W', - 'KEY_E', - 'KEY_R', - 'KEY_T', - 'KEY_Y', - 'KEY_U', - 'KEY_I', - 'KEY_O', - 'KEY_P', - 'KEY_LEFTBRACE', - 'KEY_RIGHTBRACE', - 'KEY_ENTER', - 'KEY_LEFTCTRL', - 'KEY_A', - 'KEY_S', - 'KEY_D', - 'KEY_F', - 'KEY_G', - 'KEY_H', - 'KEY_J', - 'KEY_K', - 'KEY_L', - 'KEY_SEMICOLON', - 'KEY_APOSTROPHE', - 'KEY_GRAVE', - 'KEY_LEFTSHIFT', - 'KEY_BACKSLASH', - 'KEY_Z', - 'KEY_X', - 'KEY_C', - 'KEY_V', - 'KEY_B', - 'KEY_N', - 'KEY_M', - 'KEY_COMMA', - 'KEY_DOT', - 'KEY_SLASH', - 'KEY_RIGHTSHIFT', - 'KEY_KPASTERISK', - 'KEY_LEFTALT', - 'KEY_SPACE', - 'KEY_CAPSLOCK', - 'KEY_F1', - 'KEY_F2', - 'KEY_F3', - 'KEY_F4', - 'KEY_F5', - 'KEY_F6', - 'KEY_F7', - 'KEY_F8', - 'KEY_F9', - 'KEY_F10', - 'KEY_NUMLOCK', - 'KEY_SCROLLLOCK', - 'KEY_KP7', - 'KEY_KP8', - 'KEY_KP9', - 'KEY_KPMINUS', - 'KEY_KP4', - 'KEY_KP5', - 'KEY_KP6', - 'KEY_KPPLUS', - 'KEY_KP1', - 'KEY_KP2', - 'KEY_KP3', - 'KEY_KP0', - 'KEY_KPDOT', - 'KEY_ZENKAKUHANKAKU', - 'KEY_102ND', - 'KEY_F11', - 'KEY_F12', - 'KEY_RO', - 'KEY_KATAKANA', - 'KEY_HIRAGANA', - 'KEY_HENKAN', - 'KEY_KATAKANAHIRAGANA', - 'KEY_MUHENKAN', - 'KEY_KPJPCOMMA', - 'KEY_KPENTER', - 'KEY_RIGHTCTRL', - 'KEY_KPSLASH', - 'KEY_SYSRQ', - 'KEY_RIGHTALT', - 'KEY_LINEFEED', - 'KEY_HOME', - 'KEY_UP', - 'KEY_PAGEUP', - 'KEY_LEFT', - 'KEY_RIGHT', - 'KEY_END', - 'KEY_DOWN', - 'KEY_PAGEDOWN', - 'KEY_INSERT', - 'KEY_DELETE', - 'KEY_MACRO', - 'KEY_MIN_INTERESTING', - 'KEY_MUTE', - 'KEY_VOLUMEDOWN', - 'KEY_VOLUMEUP', - 'KEY_POWER', - 'KEY_KPEQUAL', - 'KEY_KPPLUSMINUS', - 'KEY_PAUSE', - 'KEY_SCALE', - 'KEY_KPCOMMA', - 'KEY_HANGEUL', - 'KEY_HANGUEL', - 'KEY_HANJA', - 'KEY_YEN', - 'KEY_LEFTMETA', - 'KEY_RIGHTMETA', - 'KEY_COMPOSE', - 'KEY_STOP', - 'KEY_AGAIN', - 'KEY_PROPS', - 'KEY_UNDO', - 'KEY_FRONT', - 'KEY_COPY', - 'KEY_OPEN', - 'KEY_PASTE', - 'KEY_FIND', - 'KEY_CUT', - 'KEY_HELP', - 'KEY_MENU', - 'KEY_CALC', - 'KEY_SETUP', - 'KEY_SLEEP', - 'KEY_WAKEUP', - 'KEY_FILE', - 'KEY_SENDFILE', - 'KEY_DELETEFILE', - 'KEY_XFER', - 'KEY_PROG1', - 'KEY_PROG2', - 'KEY_WWW', - 'KEY_MSDOS', - 'KEY_COFFEE', - 'KEY_SCREENLOCK', - 'KEY_DIRECTION', - 'KEY_ROTATE_DISPLAY', - 'KEY_CYCLEWINDOWS', - 'KEY_MAIL', - 'KEY_BOOKMARKS', - 'KEY_COMPUTER', - 'KEY_BACK', - 'KEY_FORWARD', - 'KEY_CLOSECD', - 'KEY_EJECTCD', - 'KEY_EJECTCLOSECD', - 'KEY_NEXTSONG', - 'KEY_PLAYPAUSE', - 'KEY_PREVIOUSSONG', - 'KEY_STOPCD', - 'KEY_RECORD', - 'KEY_REWIND', - 'KEY_PHONE', - 'KEY_ISO', - 'KEY_CONFIG', - 'KEY_HOMEPAGE', - 'KEY_REFRESH', - 'KEY_EXIT', - 'KEY_MOVE', - 'KEY_EDIT', - 'KEY_SCROLLUP', - 'KEY_SCROLLDOWN', - 'KEY_KPLEFTPAREN', - 'KEY_KPRIGHTPAREN', - 'KEY_NEW', - 'KEY_REDO', - 'KEY_F13', - 'KEY_F14', - 'KEY_F15', - 'KEY_F16', - 'KEY_F17', - 'KEY_F18', - 'KEY_F19', - 'KEY_F20', - 'KEY_F21', - 'KEY_F22', - 'KEY_F23', - 'KEY_F24', - 'KEY_PLAYCD', - 'KEY_PAUSECD', - 'KEY_PROG3', - 'KEY_PROG4', - 'KEY_DASHBOARD', - 'KEY_SUSPEND', - 'KEY_CLOSE', - 'KEY_PLAY', - 'KEY_FASTFORWARD', - 'KEY_BASSBOOST', - 'KEY_PRINT', - 'KEY_HP', - 'KEY_CAMERA', - 'KEY_SOUND', - 'KEY_QUESTION', - 'KEY_EMAIL', - 'KEY_CHAT', - 'KEY_SEARCH', - 'KEY_CONNECT', - 'KEY_FINANCE', - 'KEY_SPORT', - 'KEY_SHOP', - 'KEY_ALTERASE', - 'KEY_CANCEL', - 'KEY_BRIGHTNESSDOWN', - 'KEY_BRIGHTNESSUP', - 'KEY_MEDIA', - 'KEY_SWITCHVIDEOMODE', - 'KEY_KBDILLUMTOGGLE', - 'KEY_KBDILLUMDOWN', - 'KEY_KBDILLUMUP', - 'KEY_SEND', - 'KEY_REPLY', - 'KEY_FORWARDMAIL', - 'KEY_SAVE', - 'KEY_DOCUMENTS', - 'KEY_BATTERY', - 'KEY_BLUETOOTH', - 'KEY_WLAN', - 'KEY_UWB', - 'KEY_UNKNOWN', - 'KEY_VIDEO_NEXT', - 'KEY_VIDEO_PREV', - 'KEY_BRIGHTNESS_CYCLE', - 'KEY_BRIGHTNESS_AUTO', - 'KEY_BRIGHTNESS_ZERO', - 'KEY_DISPLAY_OFF', - 'KEY_WIMAX', - 'KEY_WWAN', - 'KEY_RFKILL', - 'KEY_MICMUTE', - 'BTN_0', - 'BTN_MISC', - 'BTN_1', - 'BTN_2', - 'BTN_3', - 'BTN_4', - 'BTN_5', - 'BTN_6', - 'BTN_7', - 'BTN_8', - 'BTN_9', - 'BTN_LEFT', - 'BTN_MOUSE', - 'BTN_RIGHT', - 'BTN_MIDDLE', - 'BTN_SIDE', - 'BTN_EXTRA', - 'BTN_FORWARD', - 'BTN_BACK', - 'BTN_TASK', - 'BTN_JOYSTICK', - 'BTN_TRIGGER', - 'BTN_THUMB', - 'BTN_THUMB2', - 'BTN_TOP', - 'BTN_TOP2', - 'BTN_PINKIE', - 'BTN_BASE', - 'BTN_BASE2', - 'BTN_BASE3', - 'BTN_BASE4', - 'BTN_BASE5', - 'BTN_BASE6', - 'BTN_DEAD', - 'BTN_A', - 'BTN_GAMEPAD', - 'BTN_SOUTH', - 'BTN_B', - 'BTN_EAST', - 'BTN_C', - 'BTN_NORTH', - 'BTN_X', - 'BTN_WEST', - 'BTN_Y', - 'BTN_Z', - 'BTN_TL', - 'BTN_TR', - 'BTN_TL2', - 'BTN_TR2', - 'BTN_SELECT', - 'BTN_START', - 'BTN_MODE', - 'BTN_THUMBL', - 'BTN_THUMBR', - 'BTN_DIGI', - 'BTN_TOOL_PEN', - 'BTN_TOOL_RUBBER', - 'BTN_TOOL_BRUSH', - 'BTN_TOOL_PENCIL', - 'BTN_TOOL_AIRBRUSH', - 'BTN_TOOL_FINGER', - 'BTN_TOOL_MOUSE', - 'BTN_TOOL_LENS', - 'BTN_TOOL_QUINTTAP', - 'BTN_TOUCH', - 'BTN_STYLUS', - 'BTN_STYLUS2', - 'BTN_TOOL_DOUBLETAP', - 'BTN_TOOL_TRIPLETAP', - 'BTN_TOOL_QUADTAP', - 'BTN_GEAR_DOWN', - 'BTN_WHEEL', - 'BTN_GEAR_UP', - 'KEY_OK', - 'KEY_SELECT', - 'KEY_GOTO', - 'KEY_CLEAR', - 'KEY_POWER2', - 'KEY_OPTION', - 'KEY_INFO', - 'KEY_TIME', - 'KEY_VENDOR', - 'KEY_ARCHIVE', - 'KEY_PROGRAM', - 'KEY_CHANNEL', - 'KEY_FAVORITES', - 'KEY_EPG', - 'KEY_PVR', - 'KEY_MHP', - 'KEY_LANGUAGE', - 'KEY_TITLE', - 'KEY_SUBTITLE', - 'KEY_ANGLE', - 'KEY_ZOOM', - 'KEY_MODE', - 'KEY_KEYBOARD', - 'KEY_SCREEN', - 'KEY_PC', - 'KEY_TV', - 'KEY_TV2', - 'KEY_VCR', - 'KEY_VCR2', - 'KEY_SAT', - 'KEY_SAT2', - 'KEY_CD', - 'KEY_TAPE', - 'KEY_RADIO', - 'KEY_TUNER', - 'KEY_PLAYER', - 'KEY_TEXT', - 'KEY_DVD', - 'KEY_AUX', - 'KEY_MP3', - 'KEY_AUDIO', - 'KEY_VIDEO', - 'KEY_DIRECTORY', - 'KEY_LIST', - 'KEY_MEMO', - 'KEY_CALENDAR', - 'KEY_RED', - 'KEY_GREEN', - 'KEY_YELLOW', - 'KEY_BLUE', - 'KEY_CHANNELUP', - 'KEY_CHANNELDOWN', - 'KEY_FIRST', - 'KEY_LAST', - 'KEY_AB', - 'KEY_NEXT', - 'KEY_RESTART', - 'KEY_SLOW', - 'KEY_SHUFFLE', - 'KEY_BREAK', - 'KEY_PREVIOUS', - 'KEY_DIGITS', - 'KEY_TEEN', - 'KEY_TWEN', - 'KEY_VIDEOPHONE', - 'KEY_GAMES', - 'KEY_ZOOMIN', - 'KEY_ZOOMOUT', - 'KEY_ZOOMRESET', - 'KEY_WORDPROCESSOR', - 'KEY_EDITOR', - 'KEY_SPREADSHEET', - 'KEY_GRAPHICSEDITOR', - 'KEY_PRESENTATION', - 'KEY_DATABASE', - 'KEY_NEWS', - 'KEY_VOICEMAIL', - 'KEY_ADDRESSBOOK', - 'KEY_MESSENGER', - 'KEY_BRIGHTNESS_TOGGLE', - 'KEY_DISPLAYTOGGLE', - 'KEY_SPELLCHECK', - 'KEY_LOGOFF', - 'KEY_DOLLAR', - 'KEY_EURO', - 'KEY_FRAMEBACK', - 'KEY_FRAMEFORWARD', - 'KEY_CONTEXT_MENU', - 'KEY_MEDIA_REPEAT', - 'KEY_10CHANNELSUP', - 'KEY_10CHANNELSDOWN', - 'KEY_IMAGES', - 'KEY_DEL_EOL', - 'KEY_DEL_EOS', - 'KEY_INS_LINE', - 'KEY_DEL_LINE', - 'KEY_FN', - 'KEY_FN_ESC', - 'KEY_FN_F1', - 'KEY_FN_F2', - 'KEY_FN_F3', - 'KEY_FN_F4', - 'KEY_FN_F5', - 'KEY_FN_F6', - 'KEY_FN_F7', - 'KEY_FN_F8', - 'KEY_FN_F9', - 'KEY_FN_F10', - 'KEY_FN_F11', - 'KEY_FN_F12', - 'KEY_FN_1', - 'KEY_FN_2', - 'KEY_FN_D', - 'KEY_FN_E', - 'KEY_FN_F', - 'KEY_FN_S', - 'KEY_FN_B', - 'KEY_BRL_DOT1', - 'KEY_BRL_DOT2', - 'KEY_BRL_DOT3', - 'KEY_BRL_DOT4', - 'KEY_BRL_DOT5', - 'KEY_BRL_DOT6', - 'KEY_BRL_DOT7', - 'KEY_BRL_DOT8', - 'KEY_BRL_DOT9', - 'KEY_BRL_DOT10', - 'KEY_NUMERIC_0', - 'KEY_NUMERIC_1', - 'KEY_NUMERIC_2', - 'KEY_NUMERIC_3', - 'KEY_NUMERIC_4', - 'KEY_NUMERIC_5', - 'KEY_NUMERIC_6', - 'KEY_NUMERIC_7', - 'KEY_NUMERIC_8', - 'KEY_NUMERIC_9', - 'KEY_NUMERIC_STAR', - 'KEY_NUMERIC_POUND', - 'KEY_NUMERIC_A', - 'KEY_NUMERIC_B', - 'KEY_NUMERIC_C', - 'KEY_NUMERIC_D', - 'KEY_CAMERA_FOCUS', - 'KEY_WPS_BUTTON', - 'KEY_TOUCHPAD_TOGGLE', - 'KEY_TOUCHPAD_ON', - 'KEY_TOUCHPAD_OFF', - 'KEY_CAMERA_ZOOMIN', - 'KEY_CAMERA_ZOOMOUT', - 'KEY_CAMERA_UP', - 'KEY_CAMERA_DOWN', - 'KEY_CAMERA_LEFT', - 'KEY_CAMERA_RIGHT', - 'KEY_ATTENDANT_ON', - 'KEY_ATTENDANT_OFF', - 'KEY_ATTENDANT_TOGGLE', - 'KEY_LIGHTS_TOGGLE', - 'BTN_DPAD_UP', - 'BTN_DPAD_DOWN', - 'BTN_DPAD_LEFT', - 'BTN_DPAD_RIGHT', - 'KEY_ALS_TOGGLE', - 'KEY_BUTTONCONFIG', - 'KEY_TASKMANAGER', - 'KEY_JOURNAL', - 'KEY_CONTROLPANEL', - 'KEY_APPSELECT', - 'KEY_SCREENSAVER', - 'KEY_VOICECOMMAND', - 'KEY_BRIGHTNESS_MIN', - 'KEY_BRIGHTNESS_MAX', - 'KEY_KBDINPUTASSIST_PREV', - 'KEY_KBDINPUTASSIST_NEXT', - 'KEY_KBDINPUTASSIST_PREVGROUP', - 'KEY_KBDINPUTASSIST_NEXTGROUP', - 'KEY_KBDINPUTASSIST_ACCEPT', - 'KEY_KBDINPUTASSIST_CANCEL', - 'KEY_RIGHT_UP', - 'KEY_RIGHT_DOWN', - 'KEY_LEFT_UP', - 'KEY_LEFT_DOWN', - 'KEY_ROOT_MENU', - 'KEY_MEDIA_TOP_MENU', - 'KEY_NUMERIC_11', - 'KEY_NUMERIC_12', - 'KEY_AUDIO_DESC', - 'KEY_3D_MODE', - 'KEY_NEXT_FAVORITE', - 'KEY_STOP_RECORD', - 'KEY_PAUSE_RECORD', - 'KEY_VOD', - 'KEY_UNMUTE', - 'KEY_DATA', - 'KEY_FASTREVERSE', - 'KEY_SLOWREVERSE', - 'BTN_TRIGGER_HAPPY', - 'BTN_TRIGGER_HAPPY1', - 'BTN_TRIGGER_HAPPY2', - 'BTN_TRIGGER_HAPPY3', - 'BTN_TRIGGER_HAPPY4', - 'BTN_TRIGGER_HAPPY5', - 'BTN_TRIGGER_HAPPY6', - 'BTN_TRIGGER_HAPPY7', - 'BTN_TRIGGER_HAPPY8', - 'BTN_TRIGGER_HAPPY9', - 'BTN_TRIGGER_HAPPY10', - 'BTN_TRIGGER_HAPPY11', - 'BTN_TRIGGER_HAPPY12', - 'BTN_TRIGGER_HAPPY13', - 'BTN_TRIGGER_HAPPY14', - 'BTN_TRIGGER_HAPPY15', - 'BTN_TRIGGER_HAPPY16', - 'BTN_TRIGGER_HAPPY17', - 'BTN_TRIGGER_HAPPY18', - 'BTN_TRIGGER_HAPPY19', - 'BTN_TRIGGER_HAPPY20', - 'BTN_TRIGGER_HAPPY21', - 'BTN_TRIGGER_HAPPY22', - 'BTN_TRIGGER_HAPPY23', - 'BTN_TRIGGER_HAPPY24', - 'BTN_TRIGGER_HAPPY25', - 'BTN_TRIGGER_HAPPY26', - 'BTN_TRIGGER_HAPPY27', - 'BTN_TRIGGER_HAPPY28', - 'BTN_TRIGGER_HAPPY29', - 'BTN_TRIGGER_HAPPY30', - 'BTN_TRIGGER_HAPPY31', - 'BTN_TRIGGER_HAPPY32', - 'BTN_TRIGGER_HAPPY33', - 'BTN_TRIGGER_HAPPY34', - 'BTN_TRIGGER_HAPPY35', - 'BTN_TRIGGER_HAPPY36', - 'BTN_TRIGGER_HAPPY37', - 'BTN_TRIGGER_HAPPY38', - 'BTN_TRIGGER_HAPPY39', - 'BTN_TRIGGER_HAPPY40', - 'KEY_FENRIR', - 'KEY_SCRIPT', - 'KEY_ALT', - 'KEY_CTRL', - 'KEY_META', - 'KEY_SHIFT'] + "KEY_RESERVED", + "KEY_ESC", + "KEY_1", + "KEY_2", + "KEY_3", + "KEY_4", + "KEY_5", + "KEY_6", + "KEY_7", + "KEY_8", + "KEY_9", + "KEY_0", + "KEY_MINUS", + "KEY_EQUAL", + "KEY_BACKSPACE", + "KEY_TAB", + "KEY_Q", + "KEY_W", + "KEY_E", + "KEY_R", + "KEY_T", + "KEY_Y", + "KEY_U", + "KEY_I", + "KEY_O", + "KEY_P", + "KEY_LEFTBRACE", + "KEY_RIGHTBRACE", + "KEY_ENTER", + "KEY_LEFTCTRL", + "KEY_A", + "KEY_S", + "KEY_D", + "KEY_F", + "KEY_G", + "KEY_H", + "KEY_J", + "KEY_K", + "KEY_L", + "KEY_SEMICOLON", + "KEY_APOSTROPHE", + "KEY_GRAVE", + "KEY_LEFTSHIFT", + "KEY_BACKSLASH", + "KEY_Z", + "KEY_X", + "KEY_C", + "KEY_V", + "KEY_B", + "KEY_N", + "KEY_M", + "KEY_COMMA", + "KEY_DOT", + "KEY_SLASH", + "KEY_RIGHTSHIFT", + "KEY_KPASTERISK", + "KEY_LEFTALT", + "KEY_SPACE", + "KEY_CAPSLOCK", + "KEY_F1", + "KEY_F2", + "KEY_F3", + "KEY_F4", + "KEY_F5", + "KEY_F6", + "KEY_F7", + "KEY_F8", + "KEY_F9", + "KEY_F10", + "KEY_NUMLOCK", + "KEY_SCROLLLOCK", + "KEY_KP7", + "KEY_KP8", + "KEY_KP9", + "KEY_KPMINUS", + "KEY_KP4", + "KEY_KP5", + "KEY_KP6", + "KEY_KPPLUS", + "KEY_KP1", + "KEY_KP2", + "KEY_KP3", + "KEY_KP0", + "KEY_KPDOT", + "KEY_ZENKAKUHANKAKU", + "KEY_102ND", + "KEY_F11", + "KEY_F12", + "KEY_RO", + "KEY_KATAKANA", + "KEY_HIRAGANA", + "KEY_HENKAN", + "KEY_KATAKANAHIRAGANA", + "KEY_MUHENKAN", + "KEY_KPJPCOMMA", + "KEY_KPENTER", + "KEY_RIGHTCTRL", + "KEY_KPSLASH", + "KEY_SYSRQ", + "KEY_RIGHTALT", + "KEY_LINEFEED", + "KEY_HOME", + "KEY_UP", + "KEY_PAGEUP", + "KEY_LEFT", + "KEY_RIGHT", + "KEY_END", + "KEY_DOWN", + "KEY_PAGEDOWN", + "KEY_INSERT", + "KEY_DELETE", + "KEY_MACRO", + "KEY_MIN_INTERESTING", + "KEY_MUTE", + "KEY_VOLUMEDOWN", + "KEY_VOLUMEUP", + "KEY_POWER", + "KEY_KPEQUAL", + "KEY_KPPLUSMINUS", + "KEY_PAUSE", + "KEY_SCALE", + "KEY_KPCOMMA", + "KEY_HANGEUL", + "KEY_HANGUEL", + "KEY_HANJA", + "KEY_YEN", + "KEY_LEFTMETA", + "KEY_RIGHTMETA", + "KEY_COMPOSE", + "KEY_STOP", + "KEY_AGAIN", + "KEY_PROPS", + "KEY_UNDO", + "KEY_FRONT", + "KEY_COPY", + "KEY_OPEN", + "KEY_PASTE", + "KEY_FIND", + "KEY_CUT", + "KEY_HELP", + "KEY_MENU", + "KEY_CALC", + "KEY_SETUP", + "KEY_SLEEP", + "KEY_WAKEUP", + "KEY_FILE", + "KEY_SENDFILE", + "KEY_DELETEFILE", + "KEY_XFER", + "KEY_PROG1", + "KEY_PROG2", + "KEY_WWW", + "KEY_MSDOS", + "KEY_COFFEE", + "KEY_SCREENLOCK", + "KEY_DIRECTION", + "KEY_ROTATE_DISPLAY", + "KEY_CYCLEWINDOWS", + "KEY_MAIL", + "KEY_BOOKMARKS", + "KEY_COMPUTER", + "KEY_BACK", + "KEY_FORWARD", + "KEY_CLOSECD", + "KEY_EJECTCD", + "KEY_EJECTCLOSECD", + "KEY_NEXTSONG", + "KEY_PLAYPAUSE", + "KEY_PREVIOUSSONG", + "KEY_STOPCD", + "KEY_RECORD", + "KEY_REWIND", + "KEY_PHONE", + "KEY_ISO", + "KEY_CONFIG", + "KEY_HOMEPAGE", + "KEY_REFRESH", + "KEY_EXIT", + "KEY_MOVE", + "KEY_EDIT", + "KEY_SCROLLUP", + "KEY_SCROLLDOWN", + "KEY_KPLEFTPAREN", + "KEY_KPRIGHTPAREN", + "KEY_NEW", + "KEY_REDO", + "KEY_F13", + "KEY_F14", + "KEY_F15", + "KEY_F16", + "KEY_F17", + "KEY_F18", + "KEY_F19", + "KEY_F20", + "KEY_F21", + "KEY_F22", + "KEY_F23", + "KEY_F24", + "KEY_PLAYCD", + "KEY_PAUSECD", + "KEY_PROG3", + "KEY_PROG4", + "KEY_DASHBOARD", + "KEY_SUSPEND", + "KEY_CLOSE", + "KEY_PLAY", + "KEY_FASTFORWARD", + "KEY_BASSBOOST", + "KEY_PRINT", + "KEY_HP", + "KEY_CAMERA", + "KEY_SOUND", + "KEY_QUESTION", + "KEY_EMAIL", + "KEY_CHAT", + "KEY_SEARCH", + "KEY_CONNECT", + "KEY_FINANCE", + "KEY_SPORT", + "KEY_SHOP", + "KEY_ALTERASE", + "KEY_CANCEL", + "KEY_BRIGHTNESSDOWN", + "KEY_BRIGHTNESSUP", + "KEY_MEDIA", + "KEY_SWITCHVIDEOMODE", + "KEY_KBDILLUMTOGGLE", + "KEY_KBDILLUMDOWN", + "KEY_KBDILLUMUP", + "KEY_SEND", + "KEY_REPLY", + "KEY_FORWARDMAIL", + "KEY_SAVE", + "KEY_DOCUMENTS", + "KEY_BATTERY", + "KEY_BLUETOOTH", + "KEY_WLAN", + "KEY_UWB", + "KEY_UNKNOWN", + "KEY_VIDEO_NEXT", + "KEY_VIDEO_PREV", + "KEY_BRIGHTNESS_CYCLE", + "KEY_BRIGHTNESS_AUTO", + "KEY_BRIGHTNESS_ZERO", + "KEY_DISPLAY_OFF", + "KEY_WIMAX", + "KEY_WWAN", + "KEY_RFKILL", + "KEY_MICMUTE", + "BTN_0", + "BTN_MISC", + "BTN_1", + "BTN_2", + "BTN_3", + "BTN_4", + "BTN_5", + "BTN_6", + "BTN_7", + "BTN_8", + "BTN_9", + "BTN_LEFT", + "BTN_MOUSE", + "BTN_RIGHT", + "BTN_MIDDLE", + "BTN_SIDE", + "BTN_EXTRA", + "BTN_FORWARD", + "BTN_BACK", + "BTN_TASK", + "BTN_JOYSTICK", + "BTN_TRIGGER", + "BTN_THUMB", + "BTN_THUMB2", + "BTN_TOP", + "BTN_TOP2", + "BTN_PINKIE", + "BTN_BASE", + "BTN_BASE2", + "BTN_BASE3", + "BTN_BASE4", + "BTN_BASE5", + "BTN_BASE6", + "BTN_DEAD", + "BTN_A", + "BTN_GAMEPAD", + "BTN_SOUTH", + "BTN_B", + "BTN_EAST", + "BTN_C", + "BTN_NORTH", + "BTN_X", + "BTN_WEST", + "BTN_Y", + "BTN_Z", + "BTN_TL", + "BTN_TR", + "BTN_TL2", + "BTN_TR2", + "BTN_SELECT", + "BTN_START", + "BTN_MODE", + "BTN_THUMBL", + "BTN_THUMBR", + "BTN_DIGI", + "BTN_TOOL_PEN", + "BTN_TOOL_RUBBER", + "BTN_TOOL_BRUSH", + "BTN_TOOL_PENCIL", + "BTN_TOOL_AIRBRUSH", + "BTN_TOOL_FINGER", + "BTN_TOOL_MOUSE", + "BTN_TOOL_LENS", + "BTN_TOOL_QUINTTAP", + "BTN_TOUCH", + "BTN_STYLUS", + "BTN_STYLUS2", + "BTN_TOOL_DOUBLETAP", + "BTN_TOOL_TRIPLETAP", + "BTN_TOOL_QUADTAP", + "BTN_GEAR_DOWN", + "BTN_WHEEL", + "BTN_GEAR_UP", + "KEY_OK", + "KEY_SELECT", + "KEY_GOTO", + "KEY_CLEAR", + "KEY_POWER2", + "KEY_OPTION", + "KEY_INFO", + "KEY_TIME", + "KEY_VENDOR", + "KEY_ARCHIVE", + "KEY_PROGRAM", + "KEY_CHANNEL", + "KEY_FAVORITES", + "KEY_EPG", + "KEY_PVR", + "KEY_MHP", + "KEY_LANGUAGE", + "KEY_TITLE", + "KEY_SUBTITLE", + "KEY_ANGLE", + "KEY_ZOOM", + "KEY_MODE", + "KEY_KEYBOARD", + "KEY_SCREEN", + "KEY_PC", + "KEY_TV", + "KEY_TV2", + "KEY_VCR", + "KEY_VCR2", + "KEY_SAT", + "KEY_SAT2", + "KEY_CD", + "KEY_TAPE", + "KEY_RADIO", + "KEY_TUNER", + "KEY_PLAYER", + "KEY_TEXT", + "KEY_DVD", + "KEY_AUX", + "KEY_MP3", + "KEY_AUDIO", + "KEY_VIDEO", + "KEY_DIRECTORY", + "KEY_LIST", + "KEY_MEMO", + "KEY_CALENDAR", + "KEY_RED", + "KEY_GREEN", + "KEY_YELLOW", + "KEY_BLUE", + "KEY_CHANNELUP", + "KEY_CHANNELDOWN", + "KEY_FIRST", + "KEY_LAST", + "KEY_AB", + "KEY_NEXT", + "KEY_RESTART", + "KEY_SLOW", + "KEY_SHUFFLE", + "KEY_BREAK", + "KEY_PREVIOUS", + "KEY_DIGITS", + "KEY_TEEN", + "KEY_TWEN", + "KEY_VIDEOPHONE", + "KEY_GAMES", + "KEY_ZOOMIN", + "KEY_ZOOMOUT", + "KEY_ZOOMRESET", + "KEY_WORDPROCESSOR", + "KEY_EDITOR", + "KEY_SPREADSHEET", + "KEY_GRAPHICSEDITOR", + "KEY_PRESENTATION", + "KEY_DATABASE", + "KEY_NEWS", + "KEY_VOICEMAIL", + "KEY_ADDRESSBOOK", + "KEY_MESSENGER", + "KEY_BRIGHTNESS_TOGGLE", + "KEY_DISPLAYTOGGLE", + "KEY_SPELLCHECK", + "KEY_LOGOFF", + "KEY_DOLLAR", + "KEY_EURO", + "KEY_FRAMEBACK", + "KEY_FRAMEFORWARD", + "KEY_CONTEXT_MENU", + "KEY_MEDIA_REPEAT", + "KEY_10CHANNELSUP", + "KEY_10CHANNELSDOWN", + "KEY_IMAGES", + "KEY_DEL_EOL", + "KEY_DEL_EOS", + "KEY_INS_LINE", + "KEY_DEL_LINE", + "KEY_FN", + "KEY_FN_ESC", + "KEY_FN_F1", + "KEY_FN_F2", + "KEY_FN_F3", + "KEY_FN_F4", + "KEY_FN_F5", + "KEY_FN_F6", + "KEY_FN_F7", + "KEY_FN_F8", + "KEY_FN_F9", + "KEY_FN_F10", + "KEY_FN_F11", + "KEY_FN_F12", + "KEY_FN_1", + "KEY_FN_2", + "KEY_FN_D", + "KEY_FN_E", + "KEY_FN_F", + "KEY_FN_S", + "KEY_FN_B", + "KEY_BRL_DOT1", + "KEY_BRL_DOT2", + "KEY_BRL_DOT3", + "KEY_BRL_DOT4", + "KEY_BRL_DOT5", + "KEY_BRL_DOT6", + "KEY_BRL_DOT7", + "KEY_BRL_DOT8", + "KEY_BRL_DOT9", + "KEY_BRL_DOT10", + "KEY_NUMERIC_0", + "KEY_NUMERIC_1", + "KEY_NUMERIC_2", + "KEY_NUMERIC_3", + "KEY_NUMERIC_4", + "KEY_NUMERIC_5", + "KEY_NUMERIC_6", + "KEY_NUMERIC_7", + "KEY_NUMERIC_8", + "KEY_NUMERIC_9", + "KEY_NUMERIC_STAR", + "KEY_NUMERIC_POUND", + "KEY_NUMERIC_A", + "KEY_NUMERIC_B", + "KEY_NUMERIC_C", + "KEY_NUMERIC_D", + "KEY_CAMERA_FOCUS", + "KEY_WPS_BUTTON", + "KEY_TOUCHPAD_TOGGLE", + "KEY_TOUCHPAD_ON", + "KEY_TOUCHPAD_OFF", + "KEY_CAMERA_ZOOMIN", + "KEY_CAMERA_ZOOMOUT", + "KEY_CAMERA_UP", + "KEY_CAMERA_DOWN", + "KEY_CAMERA_LEFT", + "KEY_CAMERA_RIGHT", + "KEY_ATTENDANT_ON", + "KEY_ATTENDANT_OFF", + "KEY_ATTENDANT_TOGGLE", + "KEY_LIGHTS_TOGGLE", + "BTN_DPAD_UP", + "BTN_DPAD_DOWN", + "BTN_DPAD_LEFT", + "BTN_DPAD_RIGHT", + "KEY_ALS_TOGGLE", + "KEY_BUTTONCONFIG", + "KEY_TASKMANAGER", + "KEY_JOURNAL", + "KEY_CONTROLPANEL", + "KEY_APPSELECT", + "KEY_SCREENSAVER", + "KEY_VOICECOMMAND", + "KEY_BRIGHTNESS_MIN", + "KEY_BRIGHTNESS_MAX", + "KEY_KBDINPUTASSIST_PREV", + "KEY_KBDINPUTASSIST_NEXT", + "KEY_KBDINPUTASSIST_PREVGROUP", + "KEY_KBDINPUTASSIST_NEXTGROUP", + "KEY_KBDINPUTASSIST_ACCEPT", + "KEY_KBDINPUTASSIST_CANCEL", + "KEY_RIGHT_UP", + "KEY_RIGHT_DOWN", + "KEY_LEFT_UP", + "KEY_LEFT_DOWN", + "KEY_ROOT_MENU", + "KEY_MEDIA_TOP_MENU", + "KEY_NUMERIC_11", + "KEY_NUMERIC_12", + "KEY_AUDIO_DESC", + "KEY_3D_MODE", + "KEY_NEXT_FAVORITE", + "KEY_STOP_RECORD", + "KEY_PAUSE_RECORD", + "KEY_VOD", + "KEY_UNMUTE", + "KEY_DATA", + "KEY_FASTREVERSE", + "KEY_SLOWREVERSE", + "BTN_TRIGGER_HAPPY", + "BTN_TRIGGER_HAPPY1", + "BTN_TRIGGER_HAPPY2", + "BTN_TRIGGER_HAPPY3", + "BTN_TRIGGER_HAPPY4", + "BTN_TRIGGER_HAPPY5", + "BTN_TRIGGER_HAPPY6", + "BTN_TRIGGER_HAPPY7", + "BTN_TRIGGER_HAPPY8", + "BTN_TRIGGER_HAPPY9", + "BTN_TRIGGER_HAPPY10", + "BTN_TRIGGER_HAPPY11", + "BTN_TRIGGER_HAPPY12", + "BTN_TRIGGER_HAPPY13", + "BTN_TRIGGER_HAPPY14", + "BTN_TRIGGER_HAPPY15", + "BTN_TRIGGER_HAPPY16", + "BTN_TRIGGER_HAPPY17", + "BTN_TRIGGER_HAPPY18", + "BTN_TRIGGER_HAPPY19", + "BTN_TRIGGER_HAPPY20", + "BTN_TRIGGER_HAPPY21", + "BTN_TRIGGER_HAPPY22", + "BTN_TRIGGER_HAPPY23", + "BTN_TRIGGER_HAPPY24", + "BTN_TRIGGER_HAPPY25", + "BTN_TRIGGER_HAPPY26", + "BTN_TRIGGER_HAPPY27", + "BTN_TRIGGER_HAPPY28", + "BTN_TRIGGER_HAPPY29", + "BTN_TRIGGER_HAPPY30", + "BTN_TRIGGER_HAPPY31", + "BTN_TRIGGER_HAPPY32", + "BTN_TRIGGER_HAPPY33", + "BTN_TRIGGER_HAPPY34", + "BTN_TRIGGER_HAPPY35", + "BTN_TRIGGER_HAPPY36", + "BTN_TRIGGER_HAPPY37", + "BTN_TRIGGER_HAPPY38", + "BTN_TRIGGER_HAPPY39", + "BTN_TRIGGER_HAPPY40", + "KEY_FENRIR", + "KEY_SCRIPT", + "KEY_ALT", + "KEY_CTRL", + "KEY_META", + "KEY_SHIFT", +] diff --git a/src/fenrirscreenreader/core/inputDriver.py b/src/fenrirscreenreader/core/inputDriver.py index 99abf814..9ca961b9 100644 --- a/src/fenrirscreenreader/core/inputDriver.py +++ b/src/fenrirscreenreader/core/inputDriver.py @@ -2,19 +2,20 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug -class InputDriver(): +class InputDriver: def __init__(self): self._initialized = False def initialize(self, environment): self.env = environment - self.env['runtime']['InputManager'].set_shortcut_type('KEY') + self.env["runtime"]["InputManager"].set_shortcut_type("KEY") self._is_initialized = True def shutdown(self): @@ -29,7 +30,7 @@ class InputDriver(): def clear_event_buffer(self): if not self._initialized: return - del self.env['input']['eventBuffer'][:] + del self.env["input"]["eventBuffer"][:] def update_input_devices(self, new_devices=None, init=False): if not self._initialized: @@ -63,12 +64,14 @@ class InputDriver(): return self.ungrab_all_devices() except Exception as e: # Just log the failure and inform the user - if hasattr( - self, - 'env') and 'runtime' in self.env and 'DebugManager' in self.env['runtime']: - self.env['runtime']['DebugManager'].write_debug_out( + if ( + hasattr(self, "env") + and "runtime" in self.env + and "DebugManager" in self.env["runtime"] + ): + self.env["runtime"]["DebugManager"].write_debug_out( f"Emergency device release failed: {str(e)}", - debug.DebugLevel.ERROR + debug.DebugLevel.ERROR, ) else: print(f"Emergency device release failed: {str(e)}") @@ -93,4 +96,4 @@ class InputDriver(): try: self.remove_all_devices() except Exception as e: - print(f'InputDriver __del__: Error removing devices: {str(e)}') + print(f"InputDriver __del__: Error removing devices: {str(e)}") diff --git a/src/fenrirscreenreader/core/inputManager.py b/src/fenrirscreenreader/core/inputManager.py index f32a8227..7325a55e 100644 --- a/src/fenrirscreenreader/core/inputManager.py +++ b/src/fenrirscreenreader/core/inputManager.py @@ -2,31 +2,31 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug -from fenrirscreenreader.core.i18n import _ -from fenrirscreenreader.core import inputData -import os import inspect +import os import time import traceback + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core import inputData +from fenrirscreenreader.core.i18n import _ + currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class InputManager(): +class InputManager: def __init__(self): - self.shortcutType = 'KEY' + self.shortcutType = "KEY" self.executeDeviceGrab = False self.lastDetectedDevices = None - def set_shortcut_type(self, shortcutType='KEY'): - if shortcutType in ['KEY', 'BYTE']: + def set_shortcut_type(self, shortcutType="KEY"): + if shortcutType in ["KEY", "BYTE"]: self.shortcutType = shortcutType def get_shortcut_type(self): @@ -34,37 +34,46 @@ class InputManager(): def initialize(self, environment): self.env = environment - self.env['runtime']['SettingsManager'].load_driver( - self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'driver'), 'InputDriver') + self.env["runtime"]["SettingsManager"].load_driver( + self.env["runtime"]["SettingsManager"].get_setting( + "keyboard", "driver" + ), + "InputDriver", + ) self.update_input_devices() # init LEDs with current state - self.env['input']['newNumLock'] = self.env['runtime']['InputDriver'].get_led_state() - self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] - self.env['input']['newCapsLock'] = self.env['runtime']['InputDriver'].get_led_state( - 1) - self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] - self.env['input']['newScrollLock'] = self.env['runtime']['InputDriver'].get_led_state( - 2) - self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] + self.env["input"]["newNumLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state() + self.env["input"]["oldNumLock"] = self.env["input"]["newNumLock"] + self.env["input"]["newCapsLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state(1) + self.env["input"]["oldCapsLock"] = self.env["input"]["newCapsLock"] + self.env["input"]["newScrollLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state(2) + self.env["input"]["oldScrollLock"] = self.env["input"]["newScrollLock"] self.lastDeepestInput = [] self.lastEvent = None - self.env['input']['shortcut_repeat'] = 1 + self.env["input"]["shortcut_repeat"] = 1 self.lastInputTime = time.time() def shutdown(self): self.remove_all_devices() - self.env['runtime']['SettingsManager'].shutdown_driver('InputDriver') + self.env["runtime"]["SettingsManager"].shutdown_driver("InputDriver") def get_input_event(self): event = None try: - event = self.env['runtime']['InputDriver'].get_input_event() + event = self.env["runtime"]["InputDriver"].get_input_event() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager get_input_event: Error getting input event: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager get_input_event: Error getting input event: " + + str(e), + debug.DebugLevel.ERROR, + ) return event def set_execute_device_grab(self, newExecuteDeviceGrab=True): @@ -75,12 +84,13 @@ class InputManager(): self.set_execute_device_grab() if not self.executeDeviceGrab: return - if self.env['input']['eventBuffer'] != []: + if self.env["input"]["eventBuffer"] != []: return if not self.no_key_pressed(): return - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): self.executeDeviceGrab = False return @@ -90,44 +100,58 @@ class InputManager(): grab_timeout = 3 # Timeout in seconds start_time = time.time() - if self.env['runtime']['ScreenManager'].get_curr_screen_ignored(): + if self.env["runtime"]["ScreenManager"].get_curr_screen_ignored(): while not self.ungrab_all_devices(): retry_count += 1 - if retry_count >= max_retries or ( - time.time() - start_time) > grab_timeout: - self.env['runtime']['DebugManager'].write_debug_out( - "Failed to ungrab devices after multiple attempts", debug.DebugLevel.ERROR) + if ( + retry_count >= max_retries + or (time.time() - start_time) > grab_timeout + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Failed to ungrab devices after multiple attempts", + debug.DebugLevel.ERROR, + ) # Force a release of devices if possible through # alternative means try: - self.env['runtime']['InputDriver'].force_ungrab() + self.env["runtime"]["InputDriver"].force_ungrab() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager handle_device_grab: Error forcing ungrab: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager handle_device_grab: Error forcing ungrab: " + + str(e), + debug.DebugLevel.ERROR, + ) break time.sleep(0.25) - self.env['runtime']['DebugManager'].write_debug_out( - f"retry ungrab_all_devices {retry_count}/{max_retries}", debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + f"retry ungrab_all_devices {retry_count}/{max_retries}", + debug.DebugLevel.WARNING, + ) else: while not self.grab_all_devices(): retry_count += 1 - if retry_count >= max_retries or ( - time.time() - start_time) > grab_timeout: - self.env['runtime']['DebugManager'].write_debug_out( - "Failed to grab devices after multiple attempts", debug.DebugLevel.ERROR) + if ( + retry_count >= max_retries + or (time.time() - start_time) > grab_timeout + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Failed to grab devices after multiple attempts", + debug.DebugLevel.ERROR, + ) # Continue without grabbing input - limited functionality # but not locked break time.sleep(0.25) - self.env['runtime']['DebugManager'].write_debug_out( - f"retry grab_all_devices {retry_count}/{max_retries}", debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + f"retry grab_all_devices {retry_count}/{max_retries}", + debug.DebugLevel.WARNING, + ) self.executeDeviceGrab = False def send_keys(self, keyMacro): for e in keyMacro: - key = '' + key = "" value = 0 if len(e) != 2: continue @@ -139,10 +163,10 @@ class InputManager(): value = e[1] else: continue - if key.upper() == 'SLEEP': + if key.upper() == "SLEEP": time.sleep(value) else: - self.env['runtime']['InputDriver'].send_key(key, value) + self.env["runtime"]["InputDriver"].send_key(key, value) def get_last_event(self): return self.lastEvent @@ -152,147 +176,167 @@ class InputManager(): return self.lastEvent = event_data # a hang apears.. try to fix - if self.env['input']['eventBuffer'] == []: - if self.env['input']['currInput'] != []: - self.env['input']['currInput'] = [] - self.env['input']['shortcut_repeat'] = 1 + if self.env["input"]["eventBuffer"] == []: + if self.env["input"]["currInput"] != []: + self.env["input"]["currInput"] = [] + self.env["input"]["shortcut_repeat"] = 1 - self.env['input']['prevInput'] = self.env['input']['currInput'].copy() - if event_data['EventState'] == 0: - if event_data['EventName'] in self.env['input']['currInput']: - self.env['input']['currInput'].remove(event_data['EventName']) - if len(self.env['input']['currInput']) > 1: - self.env['input']['currInput'] = sorted( - self.env['input']['currInput']) - elif len(self.env['input']['currInput']) == 0: - self.env['input']['shortcut_repeat'] = 1 + self.env["input"]["prevInput"] = self.env["input"]["currInput"].copy() + if event_data["EventState"] == 0: + if event_data["EventName"] in self.env["input"]["currInput"]: + self.env["input"]["currInput"].remove(event_data["EventName"]) + if len(self.env["input"]["currInput"]) > 1: + self.env["input"]["currInput"] = sorted( + self.env["input"]["currInput"] + ) + elif len(self.env["input"]["currInput"]) == 0: + self.env["input"]["shortcut_repeat"] = 1 self.lastInputTime = time.time() - elif event_data['EventState'] == 1: - if not event_data['EventName'] in self.env['input']['currInput']: - self.env['input']['currInput'].append(event_data['EventName']) - if len(self.env['input']['currInput']) > 1: - self.env['input']['currInput'] = sorted( - self.env['input']['currInput']) - if len( - self.lastDeepestInput) < len( - self.env['input']['currInput']): + elif event_data["EventState"] == 1: + if not event_data["EventName"] in self.env["input"]["currInput"]: + self.env["input"]["currInput"].append(event_data["EventName"]) + if len(self.env["input"]["currInput"]) > 1: + self.env["input"]["currInput"] = sorted( + self.env["input"]["currInput"] + ) + if len(self.lastDeepestInput) < len( + self.env["input"]["currInput"] + ): self.set_last_deepest_input( - self.env['input']['currInput'].copy()) - elif self.lastDeepestInput == self.env['input']['currInput']: - if time.time() - self.lastInputTime <= self.env['runtime']['SettingsManager'].get_setting_as_float( - 'keyboard', 'doubleTapTimeout'): - self.env['input']['shortcut_repeat'] += 1 + self.env["input"]["currInput"].copy() + ) + elif self.lastDeepestInput == self.env["input"]["currInput"]: + if time.time() - self.lastInputTime <= self.env["runtime"][ + "SettingsManager" + ].get_setting_as_float("keyboard", "doubleTapTimeout"): + self.env["input"]["shortcut_repeat"] += 1 else: - self.env['input']['shortcut_repeat'] = 1 + self.env["input"]["shortcut_repeat"] = 1 self.handle_led_states(event_data) self.lastInputTime = time.time() - elif event_data['EventState'] == 2: + elif event_data["EventState"] == 2: self.lastInputTime = time.time() - self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] - self.env['input']['newNumLock'] = self.env['runtime']['InputDriver'].get_led_state() - self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] - self.env['input']['newCapsLock'] = self.env['runtime']['InputDriver'].get_led_state( - 1) - self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] - self.env['input']['newScrollLock'] = self.env['runtime']['InputDriver'].get_led_state( - 2) - self.env['runtime']['DebugManager'].write_debug_out( - "currInput " + str(self.env['input']['currInput']), debug.DebugLevel.INFO) + self.env["input"]["oldNumLock"] = self.env["input"]["newNumLock"] + self.env["input"]["newNumLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state() + self.env["input"]["oldCapsLock"] = self.env["input"]["newCapsLock"] + self.env["input"]["newCapsLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state(1) + self.env["input"]["oldScrollLock"] = self.env["input"]["newScrollLock"] + self.env["input"]["newScrollLock"] = self.env["runtime"][ + "InputDriver" + ].get_led_state(2) + self.env["runtime"]["DebugManager"].write_debug_out( + "currInput " + str(self.env["input"]["currInput"]), + debug.DebugLevel.INFO, + ) if self.no_key_pressed(): - self.env['input']['prevInput'] = [] + self.env["input"]["prevInput"] = [] def handle_led_states(self, m_event): if self.curr_key_is_modifier(): return try: - if m_event['EventName'] == 'KEY_NUMLOCK': - self.env['runtime']['InputDriver'].toggle_led_state() - elif m_event['EventName'] == 'KEY_CAPSLOCK': - self.env['runtime']['InputDriver'].toggle_led_state(1) - elif m_event['EventName'] == 'KEY_SCROLLLOCK': - self.env['runtime']['InputDriver'].toggle_led_state(2) + if m_event["EventName"] == "KEY_NUMLOCK": + self.env["runtime"]["InputDriver"].toggle_led_state() + elif m_event["EventName"] == "KEY_CAPSLOCK": + self.env["runtime"]["InputDriver"].toggle_led_state(1) + elif m_event["EventName"] == "KEY_SCROLLLOCK": + self.env["runtime"]["InputDriver"].toggle_led_state(2) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager handle_led_states: Error toggling LED state: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager handle_led_states: Error toggling LED state: " + + str(e), + debug.DebugLevel.ERROR, + ) def grab_all_devices(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): try: - return self.env['runtime']['InputDriver'].grab_all_devices() + return self.env["runtime"]["InputDriver"].grab_all_devices() except Exception as e: return False return True def ungrab_all_devices(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): try: - return self.env['runtime']['InputDriver'].ungrab_all_devices() + return self.env["runtime"]["InputDriver"].ungrab_all_devices() except Exception as e: return False return True def handle_plug_input_device(self, event_data): for deviceEntry in event_data: - self.update_input_devices(deviceEntry['device']) + self.update_input_devices(deviceEntry["device"]) def update_input_devices(self, newDevice=None): try: - self.env['runtime']['InputDriver'].update_input_devices(newDevice) + self.env["runtime"]["InputDriver"].update_input_devices(newDevice) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager update_input_devices: Error updating input devices: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager update_input_devices: Error updating input devices: " + + str(e), + debug.DebugLevel.ERROR, + ) try: - if self.env['runtime']['ScreenManager']: + if self.env["runtime"]["ScreenManager"]: self.handle_device_grab(force=True) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager update_input_devices: Error handling device grab: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager update_input_devices: Error handling device grab: " + + str(e), + debug.DebugLevel.ERROR, + ) def remove_all_devices(self): try: - self.env['runtime']['InputDriver'].remove_all_devices() + self.env["runtime"]["InputDriver"].remove_all_devices() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputManager remove_all_devices: Error removing devices: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputManager remove_all_devices: Error removing devices: " + + str(e), + debug.DebugLevel.ERROR, + ) def convert_event_name(self, event_name): if not event_name: - return '' - if event_name == '': - return '' + return "" + if event_name == "": + return "" event_name = event_name.upper() - if event_name == 'KEY_LEFTCTRL': - event_name = 'KEY_CTRL' - elif event_name == 'KEY_RIGHTCTRL': - event_name = 'KEY_CTRL' - elif event_name == 'KEY_LEFTSHIFT': - event_name = 'KEY_SHIFT' - elif event_name == 'KEY_RIGHTSHIFT': - event_name = 'KEY_SHIFT' - elif event_name == 'KEY_LEFTALT': - event_name = 'KEY_ALT' - elif event_name == 'KEY_RIGHTALT': - event_name = 'KEY_ALT' - elif event_name == 'KEY_LEFTMETA': - event_name = 'KEY_META' - elif event_name == 'KEY_RIGHTMETA': - event_name = 'KEY_META' + if event_name == "KEY_LEFTCTRL": + event_name = "KEY_CTRL" + elif event_name == "KEY_RIGHTCTRL": + event_name = "KEY_CTRL" + elif event_name == "KEY_LEFTSHIFT": + event_name = "KEY_SHIFT" + elif event_name == "KEY_RIGHTSHIFT": + event_name = "KEY_SHIFT" + elif event_name == "KEY_LEFTALT": + event_name = "KEY_ALT" + elif event_name == "KEY_RIGHTALT": + event_name = "KEY_ALT" + elif event_name == "KEY_LEFTMETA": + event_name = "KEY_META" + elif event_name == "KEY_RIGHTMETA": + event_name = "KEY_META" if self.is_fenrir_key(event_name): - event_name = 'KEY_FENRIR' + event_name = "KEY_FENRIR" if self.is_script_key(event_name): - event_name = 'KEY_SCRIPT' + event_name = "KEY_SCRIPT" return event_name def clear_event_buffer(self): try: - self.env['runtime']['InputDriver'].clear_event_buffer() + self.env["runtime"]["InputDriver"].clear_event_buffer() except Exception as e: pass @@ -310,64 +354,69 @@ class InputManager(): def write_event_buffer(self): try: - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): - self.env['runtime']['InputDriver'].write_event_buffer() + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): + self.env["runtime"]["InputDriver"].write_event_buffer() self.clear_event_buffer() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "Error while write_u_input", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Error while write_u_input", debug.DebugLevel.ERROR + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) def no_key_pressed(self): - return self.env['input']['currInput'] == [] + return self.env["input"]["currInput"] == [] def is_key_press(self): - return ( - self.env['input']['prevInput'] == []) and ( - self.env['input']['currInput'] != []) + return (self.env["input"]["prevInput"] == []) and ( + self.env["input"]["currInput"] != [] + ) def get_prev_deepest_shortcut(self): shortcut = [] - shortcut.append(self.env['input']['shortcut_repeat']) + shortcut.append(self.env["input"]["shortcut_repeat"]) shortcut.append(self.get_last_deepest_input()) return str(shortcut) def get_prev_shortcut(self): shortcut = [] - shortcut.append(self.env['input']['shortcut_repeat']) - shortcut.append(self.env['input']['prevInput']) + shortcut.append(self.env["input"]["shortcut_repeat"]) + shortcut.append(self.env["input"]["prevInput"]) return str(shortcut) def get_curr_shortcut(self, inputSequence=None): shortcut = [] - shortcut.append(self.env['input']['shortcut_repeat']) + shortcut.append(self.env["input"]["shortcut_repeat"]) numpad_keys = [ - 'KEY_KP0', - 'KEY_KP1', - 'KEY_KP2', - 'KEY_KP3', - 'KEY_KP4', - 'KEY_KP5', - 'KEY_KP6', - 'KEY_KP7', - 'KEY_KP8', - 'KEY_KP9', - 'KEY_KPDOT', - 'KEY_KPPLUS', - 'KEY_KPMINUS', - 'KEY_KPASTERISK', - 'KEY_KPSLASH', - 'KEY_KPENTER', - 'KEY_KPEQUAL'] + "KEY_KP0", + "KEY_KP1", + "KEY_KP2", + "KEY_KP3", + "KEY_KP4", + "KEY_KP5", + "KEY_KP6", + "KEY_KP7", + "KEY_KP8", + "KEY_KP9", + "KEY_KPDOT", + "KEY_KPPLUS", + "KEY_KPMINUS", + "KEY_KPASTERISK", + "KEY_KPSLASH", + "KEY_KPENTER", + "KEY_KPEQUAL", + ] if inputSequence: # Check if any key in the sequence is a numpad key and numlock is ON # If numlock is ON and any key in the sequence is a numpad key, # return an empty shortcut - if not self.env['runtime']['CursorManager'].should_process_numpad_commands( - ): + if not self.env["runtime"][ + "CursorManager" + ].should_process_numpad_commands(): for key in inputSequence: if key in numpad_keys: # Return an empty/invalid shortcut that won't match any @@ -378,83 +427,90 @@ class InputManager(): else: # Same check for current input - if not self.env['runtime']['CursorManager'].should_process_numpad_commands( - ): - for key in self.env['input']['currInput']: + if not self.env["runtime"][ + "CursorManager" + ].should_process_numpad_commands(): + for key in self.env["input"]["currInput"]: if key in numpad_keys: # Return an empty/invalid shortcut that won't match any # command return "[]" - shortcut.append(self.env['input']['currInput']) + shortcut.append(self.env["input"]["currInput"]) - if len( - self.env['input']['prevInput']) < len( - self.env['input']['currInput']): - if self.env['input']['shortcut_repeat'] > 1 and not self.shortcut_exists( - str(shortcut)): + if len(self.env["input"]["prevInput"]) < len( + self.env["input"]["currInput"] + ): + if self.env["input"][ + "shortcut_repeat" + ] > 1 and not self.shortcut_exists(str(shortcut)): shortcut = [] - self.env['input']['shortcut_repeat'] = 1 - shortcut.append(self.env['input']['shortcut_repeat']) - shortcut.append(self.env['input']['currInput']) - self.env['runtime']['DebugManager'].write_debug_out( - "curr_shortcut " + str(shortcut), debug.DebugLevel.INFO) + self.env["input"]["shortcut_repeat"] = 1 + shortcut.append(self.env["input"]["shortcut_repeat"]) + shortcut.append(self.env["input"]["currInput"]) + self.env["runtime"]["DebugManager"].write_debug_out( + "curr_shortcut " + str(shortcut), debug.DebugLevel.INFO + ) return str(shortcut) def curr_key_is_modifier(self): if len(self.get_last_deepest_input()) != 1: return False - return (self.env['input']['currInput'][0] == 'KEY_FENRIR') or ( - self.env['input']['currInput'][0] == 'KEY_SCRIPT') + return (self.env["input"]["currInput"][0] == "KEY_FENRIR") or ( + self.env["input"]["currInput"][0] == "KEY_SCRIPT" + ) def is_fenrir_key(self, event_name): - return event_name in self.env['input']['fenrirKey'] + return event_name in self.env["input"]["fenrirKey"] def is_script_key(self, event_name): - return event_name in self.env['input']['scriptKey'] + return event_name in self.env["input"]["scriptKey"] def get_command_for_shortcut(self, shortcut): if not self.shortcut_exists(shortcut): - return '' - return self.env['bindings'][shortcut] + return "" + return self.env["bindings"][shortcut] def key_echo(self, event_data=None): if not event_data: event_data = self.get_last_event() if not event_data: return - key_name = '' - if event_data['EventState'] == 1: - key_name = event_data['EventName'].lower() - if key_name.startswith('key_'): + key_name = "" + if event_data["EventState"] == 1: + key_name = event_data["EventName"].lower() + if key_name.startswith("key_"): key_name = key_name[4:] - self.env['runtime']['OutputManager'].present_text( - _(key_name), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _(key_name), interrupt=True + ) def shortcut_exists(self, shortcut): - return (shortcut in self.env['bindings']) + return shortcut in self.env["bindings"] - def load_shortcuts(self, kb_config_path=fenrir_path + - '/../../config/keyboard/desktop.conf'): + def load_shortcuts( + self, + kb_config_path=fenrir_path + "/../../config/keyboard/desktop.conf", + ): kb_config = open(kb_config_path, "r") - while (True): + while True: invalid = False line = kb_config.readline() if not line: break - line = line.replace('\n', '') - if line.replace(" ", "") == '': + line = line.replace("\n", "") + if line.replace(" ", "") == "": continue if line.replace(" ", "").startswith("#"): continue if line.count("=") != 1: continue - sep_line = line.split('=') + sep_line = line.split("=") command_name = sep_line[1].upper() sep_line[0] = sep_line[0].replace(" ", "") sep_line[0] = sep_line[0].replace("'", "") sep_line[0] = sep_line[0].replace('"', "") - keys = sep_line[0].split(',') + keys = sep_line[0].split(",") shortcut_keys = [] shortcut_repeat = 1 shortcut = [] @@ -463,9 +519,13 @@ class InputManager(): shortcut_repeat = int(key) except Exception as e: if not self.is_valid_key(key.upper()): - self.env['runtime']['DebugManager'].write_debug_out( - "invalid key : " + key.upper() + ' command:' + command_name, - debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "invalid key : " + + key.upper() + + " command:" + + command_name, + debug.DebugLevel.WARNING, + ) invalid = True break shortcut_keys.append(key.upper()) @@ -473,27 +533,27 @@ class InputManager(): continue shortcut.append(shortcut_repeat) shortcut.append(sorted(shortcut_keys)) - if len(shortcut_keys) != 1 and 'KEY_FENRIR' not in shortcut_keys: - self.env['runtime']['DebugManager'].write_debug_out( - "invalid shortcut (missing KEY_FENRIR): " + - str(shortcut) + - ' command:' + - command_name, - debug.DebugLevel.ERROR) + if len(shortcut_keys) != 1 and "KEY_FENRIR" not in shortcut_keys: + self.env["runtime"]["DebugManager"].write_debug_out( + "invalid shortcut (missing KEY_FENRIR): " + + str(shortcut) + + " command:" + + command_name, + debug.DebugLevel.ERROR, + ) continue - self.env['runtime']['DebugManager'].write_debug_out( - "Shortcut: " + - str(shortcut) + - ' command:' + - command_name, + self.env["runtime"]["DebugManager"].write_debug_out( + "Shortcut: " + str(shortcut) + " command:" + command_name, debug.DebugLevel.INFO, - on_any_level=True) - self.env['bindings'][str(shortcut)] = command_name - self.env['rawBindings'][str(shortcut)] = shortcut + on_any_level=True, + ) + self.env["bindings"][str(shortcut)] = command_name + self.env["rawBindings"][str(shortcut)] = shortcut kb_config.close() # fix bindings - self.env['bindings'][str( - [1, ['KEY_F1', 'KEY_FENRIR']])] = 'TOGGLE_TUTORIAL_MODE' + self.env["bindings"][ + str([1, ["KEY_F1", "KEY_FENRIR"]]) + ] = "TOGGLE_TUTORIAL_MODE" def is_valid_key(self, key): return key in inputData.key_names @@ -507,33 +567,37 @@ class InputManager(): def reload_shortcuts(self): """Reload keyboard shortcuts from current layout setting""" # Clear existing bindings - self.env['bindings'].clear() - self.env['rawBindings'].clear() + self.env["bindings"].clear() + self.env["rawBindings"].clear() # Get current layout path - layout_setting = self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'keyboardLayout') + layout_setting = self.env["runtime"]["SettingsManager"].get_setting( + "keyboard", "keyboardLayout" + ) # Resolve full path if needed if not os.path.exists(layout_setting): - settings_root = '/etc/fenrirscreenreader/' + settings_root = "/etc/fenrirscreenreader/" if not os.path.exists(settings_root): import fenrirscreenreader - fenrir_path = os.path.dirname(fenrirscreenreader.__file__) - settings_root = fenrir_path + '/../../config/' - layout_path = settings_root + 'keyboard/' + layout_setting + '.conf' + fenrir_path = os.path.dirname(fenrirscreenreader.__file__) + settings_root = fenrir_path + "/../../config/" + + layout_path = ( + settings_root + "keyboard/" + layout_setting + ".conf" + ) if not os.path.exists(layout_path): # Fallback to default if layout not found - layout_path = settings_root + 'keyboard/desktop.conf' + layout_path = settings_root + "keyboard/desktop.conf" else: layout_path = layout_setting # Reload shortcuts self.load_shortcuts(layout_path) - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "Reloaded shortcuts from: " + layout_path, debug.DebugLevel.INFO, - on_any_level=True + on_any_level=True, ) diff --git a/src/fenrirscreenreader/core/memoryManager.py b/src/fenrirscreenreader/core/memoryManager.py index a53d74e7..23df4ff7 100644 --- a/src/fenrirscreenreader/core/memoryManager.py +++ b/src/fenrirscreenreader/core/memoryManager.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug -class MemoryManager(): +class MemoryManager: def __init__(self): self.listStorage = {} @@ -21,86 +22,95 @@ class MemoryManager(): def list_storage_valid(self, name, checkIndex=False): try: if checkIndex: - index = self.listStorage[name]['index'] + index = self.listStorage[name]["index"] if index == -1: - return self.listStorage[name]['list'] == [] - return self.listStorage[name]['list'][index] is not None + return self.listStorage[name]["list"] == [] + return self.listStorage[name]["list"][index] is not None else: - return isinstance(self.listStorage[name]['list'], list) + return isinstance(self.listStorage[name]["list"], list) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "list_storage_valid " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "list_storage_valid " + str(e), debug.DebugLevel.ERROR + ) return False def add_value_to_first_index(self, name, value): if not self.list_storage_valid(name): return - if self.listStorage[name]['maxLength'] is None: + if self.listStorage[name]["maxLength"] is None: # Fallback: if maxLength is still None, apply default limit of 1000 - self.listStorage[name]['list'] = [value] + \ - self.listStorage[name]['list'][:999] + self.listStorage[name]["list"] = [value] + self.listStorage[name][ + "list" + ][:999] else: - self.listStorage[name]['list'] = [ - value] + self.listStorage[name]['list'][:self.listStorage[name]['maxLength'] - 1] - self.listStorage[name]['index'] = 0 + self.listStorage[name]["list"] = [value] + self.listStorage[name][ + "list" + ][: self.listStorage[name]["maxLength"] - 1] + self.listStorage[name]["index"] = 0 def add_index_list(self, name, maxLength=1000, currList=[], curr_index=-1): if len(currList) != 0 and (curr_index == -1): curr_index = 0 self.listStorage[name] = { - 'list': currList, - 'index': curr_index, - 'maxLength': maxLength} + "list": currList, + "index": curr_index, + "maxLength": maxLength, + } def is_last_index(self, name): if not self.list_storage_valid(name): return False - return self.listStorage[name]['index'] == len( - self.listStorage[name]['list']) - 1 + return ( + self.listStorage[name]["index"] + == len(self.listStorage[name]["list"]) - 1 + ) def is_first_index(self, name): if not self.list_storage_valid(name): return False - return self.listStorage[name]['index'] == 0 + return self.listStorage[name]["index"] == 0 def get_next_index(self, name): if not self.list_storage_valid(name): return False if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return False - self.listStorage[name]['index'] += 1 - if self.listStorage[name]['index'] > len( - self.listStorage[name]['list']) - 1: - self.listStorage[name]['index'] = 0 + self.listStorage[name]["index"] += 1 + if ( + self.listStorage[name]["index"] + > len(self.listStorage[name]["list"]) - 1 + ): + self.listStorage[name]["index"] = 0 return True def set_pref_index(self, name): if not self.list_storage_valid(name): return False if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return False - self.listStorage[name]['index'] -= 1 - if self.listStorage[name]['index'] < 0: - self.listStorage[name]['index'] = len( - self.listStorage[name]['list']) - 1 + self.listStorage[name]["index"] -= 1 + if self.listStorage[name]["index"] < 0: + self.listStorage[name]["index"] = ( + len(self.listStorage[name]["list"]) - 1 + ) return True def set_first_index(self, name): if not self.list_storage_valid(name): return False if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return False - self.listStorage[name]['index'] = 0 + self.listStorage[name]["index"] = 0 return True def get_index_list_len(self, name): if not self.list_storage_valid(name): return 0 if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return 0 return len(self.listStorage[name]) @@ -108,50 +118,59 @@ class MemoryManager(): if not self.list_storage_valid(name): return False if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return False - self.listStorage[name]['index'] = len( - self.listStorage[name]['list']) - 1 + self.listStorage[name]["index"] = ( + len(self.listStorage[name]["list"]) - 1 + ) return True def clear_current_index_list(self, name): if not self.list_storage_valid(name): return False - self.listStorage[name]['list'] = [] - self.listStorage[name]['index'] = -1 + self.listStorage[name]["list"] = [] + self.listStorage[name]["index"] = -1 def get_current_index(self, name): if not self.list_storage_valid(name): return False if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return False try: - return self.listStorage[name]['index'] + return self.listStorage[name]["index"] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'MemoryManager get_current_index: Error accessing index for ' + name + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "MemoryManager get_current_index: Error accessing index for " + + name + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) return -1 def is_index_list_empty(self, name): if not self.list_storage_valid(name): return False - return len(self.listStorage[name]['list']) == 0 + return len(self.listStorage[name]["list"]) == 0 def get_index_list_element(self, name): if not self.list_storage_valid(name): return None if self.is_index_list_empty(name): - self.listStorage[name]['index'] = -1 + self.listStorage[name]["index"] = -1 return None curr_index = self.get_current_index(name) if curr_index == -1: return None try: - return self.listStorage[name]['list'][curr_index] + return self.listStorage[name]["list"][curr_index] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'MemoryManager get_index_list_element: Error accessing element for ' + name + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "MemoryManager get_index_list_element: Error accessing element for " + + name + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) return None diff --git a/src/fenrirscreenreader/core/outputData.py b/src/fenrirscreenreader/core/outputData.py index 6411d3cd..24f39846 100644 --- a/src/fenrirscreenreader/core/outputData.py +++ b/src/fenrirscreenreader/core/outputData.py @@ -2,14 +2,15 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug output_data = { - 'nextFlush': time.time(), - 'messageText': '', - 'messageOffset': None, - 'cursorOffset': None, + "nextFlush": time.time(), + "messageText": "", + "messageOffset": None, + "cursorOffset": None, } diff --git a/src/fenrirscreenreader/core/outputManager.py b/src/fenrirscreenreader/core/outputManager.py index a17735c6..44555e62 100644 --- a/src/fenrirscreenreader/core/outputManager.py +++ b/src/fenrirscreenreader/core/outputManager.py @@ -4,305 +4,404 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. +import re +import string +import time + from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ from fenrirscreenreader.utils import line_utils -import string -import time -import re -class OutputManager(): +class OutputManager: def __init__(self): - self.last_echo = '' + self.last_echo = "" def initialize(self, environment): self.env = environment - self.env['runtime']['SettingsManager'].load_driver( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'driver'), 'SpeechDriver') - self.env['runtime']['SettingsManager'].load_driver( - self.env['runtime']['SettingsManager'].get_setting( - 'sound', 'driver'), 'SoundDriver') + self.env["runtime"]["SettingsManager"].load_driver( + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "driver" + ), + "SpeechDriver", + ) + self.env["runtime"]["SettingsManager"].load_driver( + self.env["runtime"]["SettingsManager"].get_setting( + "sound", "driver" + ), + "SoundDriver", + ) def shutdown(self): - self.env['runtime']['SettingsManager'].shutdown_driver('SoundDriver') - self.env['runtime']['SettingsManager'].shutdown_driver('SpeechDriver') + self.env["runtime"]["SettingsManager"].shutdown_driver("SoundDriver") + self.env["runtime"]["SettingsManager"].shutdown_driver("SpeechDriver") def present_text( - self, - text, - interrupt=True, - sound_icon ='', - ignore_punctuation=False, - announce_capital=False, - flush=True): - if text == '': + self, + text, + interrupt=True, + sound_icon="", + ignore_punctuation=False, + announce_capital=False, + flush=True, + ): + if text == "": return - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'readNumbersAsDigits') and len(text.strip()) > 1: + if ( + self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "readNumbersAsDigits" + ) + and len(text.strip()) > 1 + ): text = re.sub(r"(\d)", r"\1 ", text).rstrip() - self.env['runtime']['DebugManager'].write_debug_out( - "present_text:\nsoundIcon:'" + - sound_icon + - "'\nText:\n" + - text, - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "present_text:\nsoundIcon:'" + sound_icon + "'\nText:\n" + text, + debug.DebugLevel.INFO, + ) if self.play_sound_icon(sound_icon, interrupt): - self.env['runtime']['DebugManager'].write_debug_out( - "sound_icon found", debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "sound_icon found", debug.DebugLevel.INFO + ) return - if (len(text) > 1) and (text.strip(string.whitespace) == ''): + if (len(text) > 1) and (text.strip(string.whitespace) == ""): return to_announce_capital = announce_capital and text[0].isupper() if to_announce_capital: - if self.play_sound_icon('capital', False): + if self.play_sound_icon("capital", False): to_announce_capital = False self.last_echo = text - self.speak_text(text, interrupt, ignore_punctuation, to_announce_capital) + self.speak_text( + text, interrupt, ignore_punctuation, to_announce_capital + ) def get_last_echo(self): return self.last_echo def speak_text( - self, - text, - interrupt=True, - ignore_punctuation=False, - announce_capital=False): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'): - self.env['runtime']['DebugManager'].write_debug_out( - "Speech disabled in OutputManager.speak_text", debug.DebugLevel.INFO) + self, + text, + interrupt=True, + ignore_punctuation=False, + announce_capital=False, + ): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Speech disabled in OutputManager.speak_text", + debug.DebugLevel.INFO, + ) return - if self.env['runtime']['SpeechDriver'] is None: - self.env['runtime']['DebugManager'].write_debug_out( - "No SpeechDriver in OutputManager.speak_text", debug.DebugLevel.ERROR) + if self.env["runtime"]["SpeechDriver"] is None: + self.env["runtime"]["DebugManager"].write_debug_out( + "No SpeechDriver in OutputManager.speak_text", + debug.DebugLevel.ERROR, + ) return if interrupt: self.interrupt_output() try: - self.env['runtime']['SpeechDriver'].set_language( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'language')) + self.env["runtime"]["SpeechDriver"].set_language( + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "language" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "setting speech language in OutputManager.speak_text", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "setting speech language in OutputManager.speak_text", + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: - self.env['runtime']['SpeechDriver'].set_voice( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'voice')) + self.env["runtime"]["SpeechDriver"].set_voice( + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "voice" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "Error while setting speech voice in OutputManager.speak_text", - debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: if announce_capital: - self.env['runtime']['SpeechDriver'].set_pitch( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'speech', 'capitalPitch')) + self.env["runtime"]["SpeechDriver"].set_pitch( + self.env["runtime"][ + "SettingsManager" + ].get_setting_as_float("speech", "capitalPitch") + ) else: - self.env['runtime']['SpeechDriver'].set_pitch( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'speech', 'pitch')) + self.env["runtime"]["SpeechDriver"].set_pitch( + self.env["runtime"][ + "SettingsManager" + ].get_setting_as_float("speech", "pitch") + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "setting speech pitch in OutputManager.speak_text", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "setting speech pitch in OutputManager.speak_text", + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: - self.env['runtime']['SpeechDriver'].set_rate( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'speech', 'rate')) + self.env["runtime"]["SpeechDriver"].set_rate( + self.env["runtime"]["SettingsManager"].get_setting_as_float( + "speech", "rate" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "setting speech rate in OutputManager.speak_text", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "setting speech rate in OutputManager.speak_text", + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: - self.env['runtime']['SpeechDriver'].set_module( - self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'module')) + self.env["runtime"]["SpeechDriver"].set_module( + self.env["runtime"]["SettingsManager"].get_setting( + "speech", "module" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "setting speech module in OutputManager.speak_text", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "setting speech module in OutputManager.speak_text", + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: - self.env['runtime']['SpeechDriver'].set_volume( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'speech', 'volume')) + self.env["runtime"]["SpeechDriver"].set_volume( + self.env["runtime"]["SettingsManager"].get_setting_as_float( + "speech", "volume" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "setting speech volume in OutputManager.speak_text ", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "setting speech volume in OutputManager.speak_text ", + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) try: - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'newLinePause'): - clean_text = text.replace('\n', ' , ') + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "newLinePause" + ): + clean_text = text.replace("\n", " , ") else: - clean_text = text.replace('\n', ' ') + clean_text = text.replace("\n", " ") - clean_text = self.env['runtime']['TextManager'].replace_head_lines( - clean_text) - clean_text = self.env['runtime']['PunctuationManager'].proceed_punctuation( - clean_text, ignore_punctuation) - clean_text = re.sub(' +$', ' ', clean_text) - self.env['runtime']['SpeechDriver'].speak( - clean_text, True, ignore_punctuation) - self.env['runtime']['DebugManager'].write_debug_out( - "Speak: " + clean_text, debug.DebugLevel.INFO) + clean_text = self.env["runtime"]["TextManager"].replace_head_lines( + clean_text + ) + clean_text = self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(clean_text, ignore_punctuation) + clean_text = re.sub(" +$", " ", clean_text) + self.env["runtime"]["SpeechDriver"].speak( + clean_text, True, ignore_punctuation + ) + self.env["runtime"]["DebugManager"].write_debug_out( + "Speak: " + clean_text, debug.DebugLevel.INFO + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "\"speak\" in OutputManager.speak_text ", debug.DebugLevel.ERROR) - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + '"speak" in OutputManager.speak_text ', debug.DebugLevel.ERROR + ) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) def interrupt_output(self): try: - self.env['runtime']['SpeechDriver'].cancel() - self.env['runtime']['DebugManager'].write_debug_out( - "Interrupt speech", debug.DebugLevel.INFO) + self.env["runtime"]["SpeechDriver"].cancel() + self.env["runtime"]["DebugManager"].write_debug_out( + "Interrupt speech", debug.DebugLevel.INFO + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'OutputManager interrupt_output: Error canceling speech: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager interrupt_output: Error canceling speech: " + + str(e), + debug.DebugLevel.ERROR, + ) - def play_sound_icon(self, sound_icon ='', interrupt=True): - if sound_icon == '': + def play_sound_icon(self, sound_icon="", interrupt=True): + if sound_icon == "": return False sound_icon = sound_icon.upper() - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'): - self.env['runtime']['DebugManager'].write_debug_out( - "Sound disabled in OutputManager.play_sound_icon", debug.DebugLevel.INFO) + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Sound disabled in OutputManager.play_sound_icon", + debug.DebugLevel.INFO, + ) return False try: - e = self.env['soundIcons'][sound_icon] + e = self.env["soundIcons"][sound_icon] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'OutputManager play_sound_icon: SoundIcon does not exist ' + sound_icon + ': ' + str(e), - debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager play_sound_icon: SoundIcon does not exist " + + sound_icon + + ": " + + str(e), + debug.DebugLevel.WARNING, + ) return False - if self.env['runtime']['SoundDriver'] is None: - self.env['runtime']['DebugManager'].write_debug_out( + if self.env["runtime"]["SoundDriver"] is None: + self.env["runtime"]["DebugManager"].write_debug_out( "No SoundDriver in OutputManager.play_sound_icon: SoundDriver not loaded", - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) return False try: - self.env['runtime']['SoundDriver'].set_volume( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'sound', 'volume')) + self.env["runtime"]["SoundDriver"].set_volume( + self.env["runtime"]["SettingsManager"].get_setting_as_float( + "sound", "volume" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "OutputManager.play_sound_icon::set_volume: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager.play_sound_icon::set_volume: " + str(e), + debug.DebugLevel.ERROR, + ) try: - self.env['runtime']['SoundDriver'].play_sound_file( - self.env['soundIcons'][sound_icon], interrupt) + self.env["runtime"]["SoundDriver"].play_sound_file( + self.env["soundIcons"][sound_icon], interrupt + ) return True except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "OutputManager.play_sound_icon::play_sound_file: " + str(e), - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) return False return False def play_frequence(self, frequence, duration, interrupt=True): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'sound', 'enabled'): - self.env['runtime']['DebugManager'].write_debug_out( - "Sound disabled in OutputManager.play_frequence", debug.DebugLevel.INFO) + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "sound", "enabled" + ): + self.env["runtime"]["DebugManager"].write_debug_out( + "Sound disabled in OutputManager.play_frequence", + debug.DebugLevel.INFO, + ) return False if frequence < 1 or frequence > 20000: - self.env['runtime']['DebugManager'].write_debug_out( - "OutputManager.play_frequence::Filefrequence is out of range:" + - str(frequence), - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager.play_frequence::Filefrequence is out of range:" + + str(frequence), + debug.DebugLevel.INFO, + ) return False - if self.env['runtime']['SoundDriver'] is None: - self.env['runtime']['DebugManager'].write_debug_out( + if self.env["runtime"]["SoundDriver"] is None: + self.env["runtime"]["DebugManager"].write_debug_out( "No SoundDriver in OutputManager.play_frequence: SoundDriver not loaded", - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) return False try: - self.env['runtime']['SoundDriver'].set_volume( - self.env['runtime']['SettingsManager'].get_setting_as_float( - 'sound', 'volume')) + self.env["runtime"]["SoundDriver"].set_volume( + self.env["runtime"]["SettingsManager"].get_setting_as_float( + "sound", "volume" + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "OutputManager.play_sound_icon::set_volume: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager.play_sound_icon::set_volume: " + str(e), + debug.DebugLevel.ERROR, + ) adjust_volume = 0.0 try: adjust_volume = 1.0 - (frequence / 20000) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'OutputManager play_frequence: Error calculating adjust volume: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "OutputManager play_frequence: Error calculating adjust volume: " + + str(e), + debug.DebugLevel.ERROR, + ) if adjust_volume > 9.0: adjust_volume = 9.0 try: - self.env['runtime']['SoundDriver'].play_frequence( - frequence, duration, adjust_volume, interrupt) + self.env["runtime"]["SoundDriver"].play_frequence( + frequence, duration, adjust_volume, interrupt + ) return True except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( + self.env["runtime"]["DebugManager"].write_debug_out( "OutputManager.play_sound_icon::play_sound_file: " + str(e), - debug.DebugLevel.ERROR) + debug.DebugLevel.ERROR, + ) return False return False def temp_disable_speech(self): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'): + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "speech", "enabled" + ): self.present_text( _("speech temporary disabled"), - sound_icon ='SpeechOff', - interrupt=True) - self.env['commandBuffer']['enableSpeechOnKeypress'] = True + sound_icon="SpeechOff", + interrupt=True, + ) + self.env["commandBuffer"]["enableSpeechOnKeypress"] = True # Also enable prompt watching for automatic speech restoration - if 'silenceUntilPrompt' not in self.env['commandBuffer']: - self.env['commandBuffer']['silenceUntilPrompt'] = False - self.env['commandBuffer']['silenceUntilPrompt'] = True - self.env['runtime']['SettingsManager'].set_setting( - 'speech', 'enabled', str( - not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'speech', 'enabled'))) + if "silenceUntilPrompt" not in self.env["commandBuffer"]: + self.env["commandBuffer"]["silenceUntilPrompt"] = False + self.env["commandBuffer"]["silenceUntilPrompt"] = True + self.env["runtime"]["SettingsManager"].set_setting( + "speech", + "enabled", + str( + not self.env["runtime"][ + "SettingsManager" + ].get_setting_as_bool("speech", "enabled") + ), + ) self.interrupt_output() def announce_active_cursor(self, interrupt_p=False): - if self.env['runtime']['CursorManager'].is_review_mode(): - self.present_text(' review cursor ', interrupt=interrupt_p) + if self.env["runtime"]["CursorManager"].is_review_mode(): + self.present_text(" review cursor ", interrupt=interrupt_p) else: - self.present_text(' text cursor ', interrupt=interrupt_p) + self.present_text(" text cursor ", interrupt=interrupt_p) def reset_SpeechDriver(self): """Reset speech driver to clean state - called by settings_manager""" - if 'SpeechDriver' in self.env['runtime'] and self.env['runtime']['SpeechDriver']: + if ( + "SpeechDriver" in self.env["runtime"] + and self.env["runtime"]["SpeechDriver"] + ): try: - self.env['runtime']['SpeechDriver'].reset() - self.env['runtime']['DebugManager'].write_debug_out( - "Speech driver reset successfully", debug.DebugLevel.INFO) + self.env["runtime"]["SpeechDriver"].reset() + self.env["runtime"]["DebugManager"].write_debug_out( + "Speech driver reset successfully", debug.DebugLevel.INFO + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - f"reset_SpeechDriver error: {e}", debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + f"reset_SpeechDriver error: {e}", debug.DebugLevel.ERROR + ) diff --git a/src/fenrirscreenreader/core/processManager.py b/src/fenrirscreenreader/core/processManager.py index 6d3df919..7ea0385c 100644 --- a/src/fenrirscreenreader/core/processManager.py +++ b/src/fenrirscreenreader/core/processManager.py @@ -2,28 +2,30 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import signal +import time +from multiprocessing import Process +from threading import Thread from fenrirscreenreader.core import debug from fenrirscreenreader.core.eventData import FenrirEventType -import time -import signal -from threading import Thread -from multiprocessing import Process -class ProcessManager(): +class ProcessManager: def __init__(self): self._Processes = [] self._Threads = [] def initialize(self, environment): self.env = environment - self.running = self.env['runtime']['EventManager'].get_running() + self.running = self.env["runtime"]["EventManager"].get_running() self.add_simple_event_thread( FenrirEventType.heart_beat, self.heart_beat_timer, - multiprocess=True) + multiprocess=True, + ) def shutdown(self): self.terminate_all_processes() @@ -44,63 +46,55 @@ class ProcessManager(): try: time.sleep(0.5) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ProcessManager heart_beat_timer: Error during sleep: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ProcessManager heart_beat_timer: Error during sleep: " + + str(e), + debug.DebugLevel.ERROR, + ) return time.time() def add_custom_event_thread( - self, - function, - pargs=None, - multiprocess=False, - run_once=False): - event_queue = self.env['runtime']['EventManager'].get_event_queue() + self, function, pargs=None, multiprocess=False, run_once=False + ): + event_queue = self.env["runtime"]["EventManager"].get_event_queue() original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) if multiprocess: t = Process( - target=self.custom_event_worker_thread, args=( - event_queue, function, pargs, run_once)) + target=self.custom_event_worker_thread, + args=(event_queue, function, pargs, run_once), + ) self._Processes.append(t) else: # thread not implemented yet t = Thread( target=self.custom_event_worker_thread, - args=( - event_queue, - function, - pargs, - run_once)) + args=(event_queue, function, pargs, run_once), + ) self._Threads.append(t) t.start() signal.signal(signal.SIGINT, original_sigint_handler) def add_simple_event_thread( - self, - event, - function, - pargs=None, - multiprocess=False, - run_once=False): + self, event, function, pargs=None, multiprocess=False, run_once=False + ): original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) if multiprocess: t = Process( - target=self.simple_event_worker_thread, args=( - event, function, pargs, run_once)) + target=self.simple_event_worker_thread, + args=(event, function, pargs, run_once), + ) self._Processes.append(t) else: t = Thread( - target=self.simple_event_worker_thread, args=( - event, function, pargs, run_once)) + target=self.simple_event_worker_thread, + args=(event, function, pargs, run_once), + ) self._Threads.append(t) t.start() signal.signal(signal.SIGINT, original_sigint_handler) def custom_event_worker_thread( - self, - event_queue, - function, - pargs=None, - run_once=False): + self, event_queue, function, pargs=None, run_once=False + ): # if not isinstance(event_queue, Queue): # return if not callable(function): @@ -112,21 +106,19 @@ class ProcessManager(): else: function(self.running, event_queue) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ProcessManager:custom_event_worker_thread:function(' + - str(function) + - '):' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ProcessManager:custom_event_worker_thread:function(" + + str(function) + + "):" + + str(e), + debug.DebugLevel.ERROR, + ) if run_once: break def simple_event_worker_thread( - self, - event, - function, - pargs=None, - run_once=False): + self, event, function, pargs=None, run_once=False + ): if not isinstance(event, FenrirEventType): return if not callable(function): @@ -139,12 +131,13 @@ class ProcessManager(): else: data = function(self.running) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ProcessManager:simple_event_worker_thread:function(' + - str(function) + - '):' + - str(e), - debug.DebugLevel.ERROR) - self.env['runtime']['EventManager'].put_to_event_queue(event, data) + self.env["runtime"]["DebugManager"].write_debug_out( + "ProcessManager:simple_event_worker_thread:function(" + + str(function) + + "):" + + str(e), + debug.DebugLevel.ERROR, + ) + self.env["runtime"]["EventManager"].put_to_event_queue(event, data) if run_once: break diff --git a/src/fenrirscreenreader/core/punctuationData.py b/src/fenrirscreenreader/core/punctuationData.py index 319a5896..5bde4dc1 100644 --- a/src/fenrirscreenreader/core/punctuationData.py +++ b/src/fenrirscreenreader/core/punctuationData.py @@ -2,21 +2,21 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import string from collections import OrderedDict +from fenrirscreenreader.core import debug + punctuation_data = { - 'LEVELDICT': { - 'none': '', - 'some': '#-$~+*-/\\@', - 'most': '.,:-$~ +*-/\\@!#%^&*()[]}{<>;', - 'all': string.punctuation + ' §', + "LEVELDICT": { + "none": "", + "some": "#-$~+*-/\\@", + "most": ".,:-$~ +*-/\\@!#%^&*()[]}{<>;", + "all": string.punctuation + " §", }, - 'PUNCTDICT': { - }, - 'CUSTOMDICT': OrderedDict(), - 'EMOTICONDICT': OrderedDict(), + "PUNCTDICT": {}, + "CUSTOMDICT": OrderedDict(), + "EMOTICONDICT": OrderedDict(), } diff --git a/src/fenrirscreenreader/core/punctuationManager.py b/src/fenrirscreenreader/core/punctuationManager.py index 3cb53fc4..4501b650 100644 --- a/src/fenrirscreenreader/core/punctuationManager.py +++ b/src/fenrirscreenreader/core/punctuationManager.py @@ -2,49 +2,51 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -import string -from fenrirscreenreader.core import debug -import os import inspect +import os import re +import string + +from fenrirscreenreader.core import debug + currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class PunctuationManager(): +class PunctuationManager: def __init__(self): pass def initialize(self, environment): self.env = environment self.allPunctNone = dict.fromkeys( - map(ord, string.punctuation + "§ "), ' ') + map(ord, string.punctuation + "§ "), " " + ) # replace with None: # dot, comma, grave, apostrophe # for char in [ord('`'),ord("'")]: # self.allPunctNone[char] = None # dont restore the following (for announce correct pause) for char in [ - ord("'"), - ord('.'), - ord(','), - ord(';'), - ord(':'), - ord('?'), - ord('!'), - ord('-')]: + ord("'"), + ord("."), + ord(","), + ord(";"), + ord(":"), + ord("?"), + ord("!"), + ord("-"), + ]: self.allPunctNone[char] = chr(char) def shutdown(self): pass - def remove_unused(self, text, curr_level=''): + def remove_unused(self, text, curr_level=""): # dont translate dot and comma because they create a pause curr_all_punct_none = self.allPunctNone.copy() for char in curr_level: @@ -54,123 +56,165 @@ class PunctuationManager(): pass return text.translate(curr_all_punct_none) - def use_custom_dict(self, text, customDict, seperator=''): + def use_custom_dict(self, text, customDict, seperator=""): result_text = str(text) if customDict: for key, item in customDict.items(): try: - regex_lbl = 'REGEX;' - if key.upper().startswith(regex_lbl) and (len(key) > len(regex_lbl)): + regex_lbl = "REGEX;" + if key.upper().startswith(regex_lbl) and ( + len(key) > len(regex_lbl) + ): result_text = re.sub( - str(key[len(regex_lbl):]), seperator + str(item) + seperator, result_text) + str(key[len(regex_lbl) :]), + seperator + str(item) + seperator, + result_text, + ) else: result_text = result_text.replace( - str(key), seperator + str(item) + seperator) + str(key), seperator + str(item) + seperator + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "use_custom_dict replace:'" + - key + - "' with '" + - item + - "' failed:" + - str(e), + self.env["runtime"]["DebugManager"].write_debug_out( + "use_custom_dict replace:'" + + key + + "' with '" + + item + + "' failed:" + + str(e), debug.DebugLevel.ERROR, - on_any_level=False) + on_any_level=False, + ) return result_text def use_punctuation_dict(self, text, punctuationDict, punctuation): result_text = str(text) - if punctuationDict and punctuation and punctuation != '': - if ' ' in punctuation: + if punctuationDict and punctuation and punctuation != "": + if " " in punctuation: result_text = result_text.replace( - ' ', ' ' + punctuationDict[' '] + ' ') + " ", " " + punctuationDict[" "] + " " + ) for key, item in punctuationDict.items(): - if (punctuation != '' and key in punctuation) and key not in ' ': - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'respectPunctuationPause') and len(key) == 1 and key in "',.;:?!": + if ( + punctuation != "" and key in punctuation + ) and key not in " ": + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "general", "respectPunctuationPause" + ) + and len(key) == 1 + and key in "',.;:?!" + ): result_text = result_text.replace( - str(key), ' ' + str(item) + str(key) + ' ') + str(key), " " + str(item) + str(key) + " " + ) else: result_text = result_text.replace( - str(key), ' ' + str(item) + ' ') + str(key), " " + str(item) + " " + ) return result_text def is_puctuation(self, char): - return char in self.env['punctuation']['PUNCTDICT'] + return char in self.env["punctuation"]["PUNCTDICT"] def proceed_punctuation(self, text, ignore_punctuation=False): if ignore_punctuation: return text result_text = text result_text = self.use_custom_dict( - result_text, self.env['punctuation']['CUSTOMDICT']) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'general', 'emoticons'): + result_text, self.env["punctuation"]["CUSTOMDICT"] + ) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "general", "emoticons" + ): result_text = self.use_custom_dict( - result_text, self.env['punctuation']['EMOTICONDICT'], ' ') - curr_punct_level = '' - if self.env['runtime']['SettingsManager'].get_setting( - 'general', 'punctuationLevel').lower() in self.env['punctuation']['LEVELDICT']: - curr_punct_level = self.env['punctuation']['LEVELDICT'][self.env['runtime'][ - 'SettingsManager'].get_setting('general', 'punctuationLevel').lower()] + result_text, self.env["punctuation"]["EMOTICONDICT"], " " + ) + curr_punct_level = "" + if ( + self.env["runtime"]["SettingsManager"] + .get_setting("general", "punctuationLevel") + .lower() + in self.env["punctuation"]["LEVELDICT"] + ): + curr_punct_level = self.env["punctuation"]["LEVELDICT"][ + self.env["runtime"]["SettingsManager"] + .get_setting("general", "punctuationLevel") + .lower() + ] else: - curr_punct_level = string.punctuation + ' §' + curr_punct_level = string.punctuation + " §" result_text = self.use_punctuation_dict( - result_text, self.env['punctuation']['PUNCTDICT'], curr_punct_level) + result_text, self.env["punctuation"]["PUNCTDICT"], curr_punct_level + ) result_text = self.remove_unused(result_text, curr_punct_level) return result_text def cycle_punctuation(self): - punct_list = list(self.env['punctuation']['LEVELDICT'].keys()) + punct_list = list(self.env["punctuation"]["LEVELDICT"].keys()) try: curr_index = punct_list.index( - self.env['runtime']['SettingsManager'].get_setting( - 'general', 'punctuationLevel').lower()) # curr punctuation + self.env["runtime"]["SettingsManager"] + .get_setting("general", "punctuationLevel") + .lower() + ) # curr punctuation except Exception as e: return False curr_index += 1 if curr_index >= len(punct_list): curr_index = 0 curr_level = punct_list[curr_index] - self.env['runtime']['SettingsManager'].set_setting( - 'general', 'punctuationLevel', curr_level.lower()) + self.env["runtime"]["SettingsManager"].set_setting( + "general", "punctuationLevel", curr_level.lower() + ) return True - def load_dicts(self, dictConfigPath=fenrir_path + - '/../../config/punctuation/default.conf'): + def load_dicts( + self, + dictConfigPath=fenrir_path + "/../../config/punctuation/default.conf", + ): dict_config = open(dictConfigPath, "r") - curr_dict_name = '' - while (True): + curr_dict_name = "" + while True: line = dict_config.readline() if not line: break - line = line.replace('\n', '') - if line.replace(" ", "") == '': + line = line.replace("\n", "") + if line.replace(" ", "") == "": continue if line.replace(" ", "").startswith("#"): if not line.replace(" ", "").startswith("#:===:"): continue - if line.replace(" ", "").upper().startswith("[") and \ - line.replace(" ", "").upper().endswith("DICT]"): - curr_dict_name = line[line.find( - '[') + 1:line.upper().find('DICT]') + 4].upper() + if line.replace(" ", "").upper().startswith("[") and line.replace( + " ", "" + ).upper().endswith("DICT]"): + curr_dict_name = line[ + line.find("[") + 1 : line.upper().find("DICT]") + 4 + ].upper() else: - if curr_dict_name == '': + if curr_dict_name == "": continue if ":===:" not in line: continue - sep_line = line.split(':===:') + sep_line = line.split(":===:") if len(sep_line) == 1: - sep_line.append('') + sep_line.append("") elif len(sep_line) < 1: continue elif len(sep_line) > 2: - sep_line[1] = ':===:' - self.env['punctuation'][curr_dict_name][sep_line[0]] = sep_line[1] - self.env['runtime']['DebugManager'].write_debug_out( - "Punctuation: " + curr_dict_name + '.' + str( - sep_line[0]) + ' :' + sep_line[1], + sep_line[1] = ":===:" + self.env["punctuation"][curr_dict_name][sep_line[0]] = ( + sep_line[1] + ) + self.env["runtime"]["DebugManager"].write_debug_out( + "Punctuation: " + + curr_dict_name + + "." + + str(sep_line[0]) + + " :" + + sep_line[1], debug.DebugLevel.INFO, - on_any_level=True) + on_any_level=True, + ) dict_config.close() diff --git a/src/fenrirscreenreader/core/quickMenuManager.py b/src/fenrirscreenreader/core/quickMenuManager.py index d755de8a..f29b53d3 100644 --- a/src/fenrirscreenreader/core/quickMenuManager.py +++ b/src/fenrirscreenreader/core/quickMenuManager.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ from fenrirscreenreader.core.settingsData import settings_data -class QuickMenuManager(): +class QuickMenuManager: def __init__(self): self.position = 0 self.quickMenu = [] @@ -18,8 +18,10 @@ class QuickMenuManager(): def initialize(self, environment): self.env = environment self.load_menu( - self.env['runtime']['SettingsManager'].get_setting( - 'menu', 'quickMenu')) + self.env["runtime"]["SettingsManager"].get_setting( + "menu", "quickMenu" + ) + ) def shutdown(self): pass @@ -27,22 +29,26 @@ class QuickMenuManager(): def load_menu(self, menuString): self.position = 0 self.quickMenu = [] - if menuString == '': + if menuString == "": return - entrys = menuString.split(';') + entrys = menuString.split(";") for e in entrys: - entry = e.split('#') + entry = e.split("#") if len(entry) != 2: continue try: t = self.settings[entry[0]][entry[1]] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'QuickMenuManager load_menu: Setting not found ' + str(entry) + ': ' + str(e), - debug.DebugLevel.ERROR) - print(entry[0], entry[1], 'not found') + self.env["runtime"]["DebugManager"].write_debug_out( + "QuickMenuManager load_menu: Setting not found " + + str(entry) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) + print(entry[0], entry[1], "not found") continue - self.quickMenu.append({'section': entry[0], 'setting': entry[1]}) + self.quickMenu.append({"section": entry[0], "setting": entry[1]}) def next_entry(self): if len(self.quickMenu) == 0: @@ -63,16 +69,19 @@ class QuickMenuManager(): def next_value(self): if len(self.quickMenu) == 0: return False - section = self.quickMenu[self.position]['section'] - setting = self.quickMenu[self.position]['setting'] - value_string = '' + section = self.quickMenu[self.position]["section"] + setting = self.quickMenu[self.position]["setting"] + value_string = "" try: - value_string = self.env['runtime']['SettingsManager'].get_setting( - section, setting) + value_string = self.env["runtime"]["SettingsManager"].get_setting( + section, setting + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'QuickMenuManager next_value: Error getting setting value: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "QuickMenuManager next_value: Error getting setting value: " + + str(e), + debug.DebugLevel.ERROR, + ) return False try: @@ -80,23 +89,26 @@ class QuickMenuManager(): value = str(value_string) return False elif isinstance(self.settings[section][setting], bool): - if value_string not in ['True', 'False']: + if value_string not in ["True", "False"]: return False value = not value - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value) + ) elif isinstance(self.settings[section][setting], int): value = int(value_string) value += 1 - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value) + ) elif isinstance(self.settings[section][setting], float): value = float(value_string) value += 0.05 if value > 1.0: value = 1.0 - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)[:4]) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value)[:4] + ) except Exception as e: return False return True @@ -104,65 +116,80 @@ class QuickMenuManager(): def prev_value(self): if len(self.quickMenu) == 0: return False - section = self.quickMenu[self.position]['section'] - setting = self.quickMenu[self.position]['setting'] - value_string = '' + section = self.quickMenu[self.position]["section"] + setting = self.quickMenu[self.position]["setting"] + value_string = "" try: - value_string = self.env['runtime']['SettingsManager'].get_setting( - section, setting) + value_string = self.env["runtime"]["SettingsManager"].get_setting( + section, setting + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'QuickMenuManager prev_value: Error getting setting value: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "QuickMenuManager prev_value: Error getting setting value: " + + str(e), + debug.DebugLevel.ERROR, + ) return False try: if isinstance(self.settings[section][setting], str): value = str(value_string) return False elif isinstance(self.settings[section][setting], bool): - if value_string not in ['True', 'False']: + if value_string not in ["True", "False"]: return False value = not value - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value) + ) elif isinstance(self.settings[section][setting], int): value = int(value_string) value -= 1 if value < 0: value = 0 - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value) + ) elif isinstance(self.settings[section][setting], float): value = float(value_string) value -= 0.05 if value < 0.0: value = 0.0 - self.env['runtime']['SettingsManager'].set_setting( - section, setting, str(value)[:4]) + self.env["runtime"]["SettingsManager"].set_setting( + section, setting, str(value)[:4] + ) except Exception as e: return False return True def get_current_entry(self): if len(self.quickMenu) == 0: - return '' + return "" try: - return _(self.quickMenu[self.position]['section']) + \ - ' ' + _(self.quickMenu[self.position]['setting']) + return ( + _(self.quickMenu[self.position]["section"]) + + " " + + _(self.quickMenu[self.position]["setting"]) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'QuickMenuManager get_current_entry: Error formatting entry: ' + str(e), - debug.DebugLevel.ERROR) - return _('setting invalid') + self.env["runtime"]["DebugManager"].write_debug_out( + "QuickMenuManager get_current_entry: Error formatting entry: " + + str(e), + debug.DebugLevel.ERROR, + ) + return _("setting invalid") def get_current_value(self): if len(self.quickMenu) == 0: - return '' + return "" try: - return self.env['runtime']['SettingsManager'].get_setting( - self.quickMenu[self.position]['section'], self.quickMenu[self.position]['setting']) + return self.env["runtime"]["SettingsManager"].get_setting( + self.quickMenu[self.position]["section"], + self.quickMenu[self.position]["setting"], + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'QuickMenuManager get_current_value: Error getting setting value: ' + str(e), - debug.DebugLevel.ERROR) - return _('setting value invalid') + self.env["runtime"]["DebugManager"].write_debug_out( + "QuickMenuManager get_current_value: Error getting setting value: " + + str(e), + debug.DebugLevel.ERROR, + ) + return _("setting value invalid") diff --git a/src/fenrirscreenreader/core/remoteDriver.py b/src/fenrirscreenreader/core/remoteDriver.py index 4e7c54d2..b582f39c 100644 --- a/src/fenrirscreenreader/core/remoteDriver.py +++ b/src/fenrirscreenreader/core/remoteDriver.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class RemoteDriver(): +class RemoteDriver: def __init__(self): self._is_initialized = False diff --git a/src/fenrirscreenreader/core/remoteManager.py b/src/fenrirscreenreader/core/remoteManager.py index ce0654ea..4265c62e 100644 --- a/src/fenrirscreenreader/core/remoteManager.py +++ b/src/fenrirscreenreader/core/remoteManager.py @@ -2,9 +2,9 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -''' +""" Remote controll: sectioncommandparameters sections:command,setting @@ -23,69 +23,77 @@ setting save /path/settings.conf command: command say this is a test command interrupt -''' +""" +import os +import time + from fenrirscreenreader.core import debug -from fenrirscreenreader.core.i18n import _ from fenrirscreenreader.core.eventData import FenrirEventType -import time -import os +from fenrirscreenreader.core.i18n import _ -class RemoteManager(): +class RemoteManager: def __init__(self): # command controll - self.commandConst = 'COMMAND ' - self.sayConst = 'SAY ' - self.vmenuConst = 'VMENU ' - self.resetVmenuConst = 'RESETVMENU' - self.interruptConst = 'INTERRUPT' - self.quitAppConst = 'QUITAPPLICATION' - self.tempDisableSpeechConst = 'TEMPDISABLESPEECH' - self.defineWindowConst = 'WINDOW ' - self.resetWindowConst = 'RESETWINDOW' - self.setClipboardConst = 'CLIPBOARD ' - self.exportClipboardConst = 'EXPORTCLIPBOARD' + self.commandConst = "COMMAND " + self.sayConst = "SAY " + self.vmenuConst = "VMENU " + self.resetVmenuConst = "RESETVMENU" + self.interruptConst = "INTERRUPT" + self.quitAppConst = "QUITAPPLICATION" + self.tempDisableSpeechConst = "TEMPDISABLESPEECH" + self.defineWindowConst = "WINDOW " + self.resetWindowConst = "RESETWINDOW" + self.setClipboardConst = "CLIPBOARD " + self.exportClipboardConst = "EXPORTCLIPBOARD" # setting controll - self.settingConst = 'SETTING ' - self.setSettingConst = 'SET ' - self.saveAsSettingConst = 'SAVEAS ' - self.saveSettingConst = 'SAVE' - self.resetSettingConst = 'RESET' + self.settingConst = "SETTING " + self.setSettingConst = "SET " + self.saveAsSettingConst = "SAVEAS " + self.saveSettingConst = "SAVE" + self.resetSettingConst = "RESET" def initialize(self, environment): self.env = environment - self.env['runtime']['SettingsManager'].load_driver( - self.env['runtime']['SettingsManager'].get_setting( - 'remote', 'driver'), 'RemoteDriver') + self.env["runtime"]["SettingsManager"].load_driver( + self.env["runtime"]["SettingsManager"].get_setting( + "remote", "driver" + ), + "RemoteDriver", + ) def shutdown(self): - self.env['runtime']['SettingsManager'].shutdown_driver('RemoteDriver') + self.env["runtime"]["SettingsManager"].shutdown_driver("RemoteDriver") def handle_settings_change_with_response(self, settings_text): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'remote', 'enableSettingsRemote'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "remote", "enableSettingsRemote" + ): return { "success": False, - "message": "Settings remote control is disabled"} + "message": "Settings remote control is disabled", + } upper_settings_text = settings_text.upper() try: # set setting if upper_settings_text.startswith(self.setSettingConst): - parameter_text = settings_text[len(self.setSettingConst):] + parameter_text = settings_text[len(self.setSettingConst) :] self.set_settings(parameter_text) return { "success": True, - "message": f"Setting applied: {parameter_text}"} + "message": f"Setting applied: {parameter_text}", + } # save as setting elif upper_settings_text.startswith(self.saveAsSettingConst): - parameter_text = settings_text[len(self.saveAsSettingConst):] + parameter_text = settings_text[len(self.saveAsSettingConst) :] self.save_settings(parameter_text) return { "success": True, - "message": f"Settings saved to: {parameter_text}"} + "message": f"Settings saved to: {parameter_text}", + } # save setting elif upper_settings_text == self.saveSettingConst: self.save_settings() @@ -95,27 +103,30 @@ class RemoteManager(): self.reset_settings() return { "success": True, - "message": "Settings reset to defaults"} + "message": "Settings reset to defaults", + } else: return { "success": False, - "message": f"Unknown settings command: {settings_text}"} + "message": f"Unknown settings command: {settings_text}", + } except Exception as e: return {"success": False, "message": f"Settings error: {str(e)}"} def handle_settings_change(self, settings_text): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'remote', 'enableSettingsRemote'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "remote", "enableSettingsRemote" + ): return upper_settings_text = settings_text.upper() # set setting if upper_settings_text.startswith(self.setSettingConst): - parameter_text = settings_text[len(self.setSettingConst):] + parameter_text = settings_text[len(self.setSettingConst) :] self.set_settings(parameter_text) # save as setting elif upper_settings_text.startswith(self.saveAsSettingConst): - parameter_text = settings_text[len(self.saveAsSettingConst):] + parameter_text = settings_text[len(self.saveAsSettingConst) :] self.save_settings(parameter_text) # save setting elif upper_settings_text == self.saveSettingConst: @@ -125,21 +136,25 @@ class RemoteManager(): self.reset_settings() def handle_command_execution_with_response(self, command_text): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'remote', 'enableCommandRemote'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "remote", "enableCommandRemote" + ): return { "success": False, - "message": "Command remote control is disabled"} + "message": "Command remote control is disabled", + } upper_command_text = command_text.upper() try: # say if upper_command_text.startswith(self.sayConst): - parameter_text = command_text[len(self.sayConst):] + parameter_text = command_text[len(self.sayConst) :] self.say(parameter_text) - return {"success": True, - "message": f"Speaking: {parameter_text[:50]}{'...' if len(parameter_text) > 50 else ''}"} + return { + "success": True, + "message": f"Speaking: {parameter_text[:50]}{'...' if len(parameter_text) > 50 else ''}", + } # interrupt elif upper_command_text == self.interruptConst: self.interrupt_speech() @@ -149,14 +164,16 @@ class RemoteManager(): self.temp_disable_speech() return { "success": True, - "message": "Speech temporarily disabled"} + "message": "Speech temporarily disabled", + } # set vmenu elif upper_command_text.startswith(self.vmenuConst): - parameter_text = command_text[len(self.vmenuConst):] + parameter_text = command_text[len(self.vmenuConst) :] self.set_vmenu(parameter_text) return { "success": True, - "message": f"VMenu set to: {parameter_text}"} + "message": f"VMenu set to: {parameter_text}", + } # reset vmenu elif upper_command_text == self.resetVmenuConst: self.reset_vmenu() @@ -167,43 +184,49 @@ class RemoteManager(): return {"success": True, "message": "Fenrir shutting down"} # define window elif upper_command_text.startswith(self.defineWindowConst): - parameter_text = command_text[len(self.defineWindowConst):] + parameter_text = command_text[len(self.defineWindowConst) :] self.define_window(parameter_text) return { "success": True, - "message": f"Window defined: {parameter_text}"} + "message": f"Window defined: {parameter_text}", + } # reset window elif upper_command_text == self.resetWindowConst: self.reset_window() return {"success": True, "message": "Window reset"} # set clipboard elif upper_command_text.startswith(self.setClipboardConst): - parameter_text = command_text[len(self.setClipboardConst):] + parameter_text = command_text[len(self.setClipboardConst) :] self.set_clipboard(parameter_text) - return {"success": True, - "message": f"Clipboard set: {parameter_text[:50]}{'...' if len(parameter_text) > 50 else ''}"} + return { + "success": True, + "message": f"Clipboard set: {parameter_text[:50]}{'...' if len(parameter_text) > 50 else ''}", + } elif upper_command_text.startswith(self.exportClipboardConst): self.export_clipboard() return { "success": True, - "message": "Clipboard exported to file"} + "message": "Clipboard exported to file", + } else: return { "success": False, - "message": f"Unknown command: {command_text}"} + "message": f"Unknown command: {command_text}", + } except Exception as e: return {"success": False, "message": f"Command error: {str(e)}"} def handle_command_execution(self, command_text): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'remote', 'enableCommandRemote'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "remote", "enableCommandRemote" + ): return upper_command_text = command_text.upper() # say if upper_command_text.startswith(self.sayConst): - parameter_text = command_text[len(self.sayConst):] + parameter_text = command_text[len(self.sayConst) :] self.say(parameter_text) # interrupt elif upper_command_text == self.interruptConst: @@ -213,7 +236,7 @@ class RemoteManager(): self.temp_disable_speech() # set vmenu elif upper_command_text.startswith(self.vmenuConst): - parameter_text = command_text[len(self.vmenuConst):] + parameter_text = command_text[len(self.vmenuConst) :] self.set_vmenu(parameter_text) # reset vmenu elif upper_command_text == self.resetVmenuConst: @@ -223,136 +246,154 @@ class RemoteManager(): self.quit_fenrir() # define window elif upper_command_text.startswith(self.defineWindowConst): - parameter_text = command_text[len(self.defineWindowConst):] + parameter_text = command_text[len(self.defineWindowConst) :] self.define_window(parameter_text) # reset window elif upper_command_text == self.resetWindowConst: self.reset_window() # set clipboard elif upper_command_text.startswith(self.setClipboardConst): - parameter_text = command_text[len(self.setClipboardConst):] + parameter_text = command_text[len(self.setClipboardConst) :] self.set_clipboard(parameter_text) elif upper_command_text.startswith(self.exportClipboardConst): self.export_clipboard() def temp_disable_speech(self): - self.env['runtime']['OutputManager'].temp_disable_speech() + self.env["runtime"]["OutputManager"].temp_disable_speech() - def set_vmenu(self, vmenu=''): - self.env['runtime']['VmenuManager'].set_curr_menu(vmenu) + def set_vmenu(self, vmenu=""): + self.env["runtime"]["VmenuManager"].set_curr_menu(vmenu) def reset_vmenu(self): - self.env['runtime']['VmenuManager'].set_curr_menu() + self.env["runtime"]["VmenuManager"].set_curr_menu() - def set_clipboard(self, text=''): - self.env['runtime']['MemoryManager'].add_value_to_first_index( - 'clipboardHistory', text) + def set_clipboard(self, text=""): + self.env["runtime"]["MemoryManager"].add_value_to_first_index( + "clipboardHistory", text + ) def quit_fenrir(self): - self.env['runtime']['EventManager'].stop_main_event_loop() + self.env["runtime"]["EventManager"].stop_main_event_loop() def define_window(self, window_text): start = {} end = {} try: - window_list = window_text.split(' ') + window_list = window_text.split(" ") if len(window_list) < 4: return - start['x'] = int(window_list[0]) - start['y'] = int(window_list[1]) - end['x'] = int(window_list[2]) - end['y'] = int(window_list[3]) + start["x"] = int(window_list[0]) + start["y"] = int(window_list[1]) + end["x"] = int(window_list[2]) + end["y"] = int(window_list[3]) - self.env['runtime']['CursorManager'].set_window_for_application( - start, end) + self.env["runtime"]["CursorManager"].set_window_for_application( + start, end + ) except Exception as e: pass def reset_window(self): - self.env['runtime']['CursorManager'].clear_window_for_application() + self.env["runtime"]["CursorManager"].clear_window_for_application() def say(self, text): if not text: return - if text == '': + if text == "": return - self.env['runtime']['OutputManager'].speak_text(text) + self.env["runtime"]["OutputManager"].speak_text(text) def interrupt_speech(self): - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def export_clipboard(self): - clipboard_file_path = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'clipboardExportPath') + clipboard_file_path = self.env["runtime"][ + "SettingsManager" + ].get_setting("general", "clipboardExportPath") clipboard_file_path = clipboard_file_path.replace( - '$user', self.env['general']['curr_user']) + "$user", self.env["general"]["curr_user"] + ) clipboard_file_path = clipboard_file_path.replace( - '$USER', self.env['general']['curr_user']) + "$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') + "$User", self.env["general"]["curr_user"] + ) + clipboard_file = open(clipboard_file_path, "w") try: - 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"].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 = self.env["runtime"][ + "MemoryManager" + ].get_index_list_element("clipboardHistory") # Fenrir will crash if the clipboard variable is type None if clipboard is not None: clipboard_file.write(clipboard) else: - clipboard_file.write('') + clipboard_file.write("") clipboard_file.close() os.chmod(clipboard_file_path, 0o644) - self.env['runtime']['OutputManager'].present_text( - _('clipboard exported to file'), interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + _("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) + self.env["runtime"]["DebugManager"].write_debug_out( + "export_clipboard_to_file:run: Filepath:" + + clipboard_file + + " trace:" + + str(e), + debug.DebugLevel.ERROR, + ) def save_settings(self, setting_config_path=None): if not setting_config_path: - setting_config_path = self.env['runtime']['SettingsManager'].get_settings_file( - ) - if setting_config_path == '': + setting_config_path = self.env["runtime"][ + "SettingsManager" + ].get_settings_file() + if setting_config_path == "": return - self.env['runtime']['SettingsManager'].save_settings(setting_config_path) + self.env["runtime"]["SettingsManager"].save_settings( + setting_config_path + ) def reset_settings(self): - self.env['runtime']['SettingsManager'].reset_setting_arg_dict() + self.env["runtime"]["SettingsManager"].reset_setting_arg_dict() def set_settings(self, settingsArgs): - self.env['runtime']['SettingsManager'].parse_setting_args(settingsArgs) - self.env['runtime']['ScreenManager'].update_screen_ignored() - self.env['runtime']['InputManager'].handle_device_grab(force=True) + self.env["runtime"]["SettingsManager"].parse_setting_args(settingsArgs) + self.env["runtime"]["ScreenManager"].update_screen_ignored() + self.env["runtime"]["InputManager"].handle_device_grab(force=True) def handle_remote_incomming_with_response(self, event_data): if not event_data: return {"success": False, "message": "No data received"} upper_event_data = event_data.upper() - self.env['runtime']['DebugManager'].write_debug_out( - 'RemoteManager:handle_remote_incomming_with_response: event: ' + - str(event_data), - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "RemoteManager:handle_remote_incomming_with_response: event: " + + str(event_data), + debug.DebugLevel.INFO, + ) try: if upper_event_data.startswith(self.settingConst): - settings_text = event_data[len(self.settingConst):] + settings_text = event_data[len(self.settingConst) :] return self.handle_settings_change_with_response(settings_text) elif upper_event_data.startswith(self.commandConst): - command_text = event_data[len(self.commandConst):] - return self.handle_command_execution_with_response(command_text) + command_text = event_data[len(self.commandConst) :] + return self.handle_command_execution_with_response( + command_text + ) else: return { "success": False, - "message": "Unknown command format. Use 'COMMAND ...' or 'SETTING ...'"} + "message": "Unknown command format. Use 'COMMAND ...' or 'SETTING ...'", + } except Exception as e: return {"success": False, "message": f"Exception: {str(e)}"} @@ -360,14 +401,14 @@ class RemoteManager(): if not event_data: return upper_event_data = event_data.upper() - self.env['runtime']['DebugManager'].write_debug_out( - 'RemoteManager:handle_remote_incomming: event: ' + - str(event_data), - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "RemoteManager:handle_remote_incomming: event: " + str(event_data), + debug.DebugLevel.INFO, + ) if upper_event_data.startswith(self.settingConst): - settings_text = event_data[len(self.settingConst):] + settings_text = event_data[len(self.settingConst) :] self.handle_settings_change(settings_text) elif upper_event_data.startswith(self.commandConst): - command_text = event_data[len(self.commandConst):] + command_text = event_data[len(self.commandConst) :] self.handle_command_execution(command_text) diff --git a/src/fenrirscreenreader/core/runtimeData.py b/src/fenrirscreenreader/core/runtimeData.py index 9d2d26cb..a78ce85e 100644 --- a/src/fenrirscreenreader/core/runtimeData.py +++ b/src/fenrirscreenreader/core/runtimeData.py @@ -2,23 +2,23 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug runtime_data = { - 'SpeechDriver': None, - 'ScreenDriver': None, - 'SoundDriver': None, - 'InputDriver': None, - 'RemoteDriver': None, - 'InputManager': None, - 'CommandManager': None, - 'ScreenManager': None, - 'OutputManager': None, - 'DebugManager': None, - 'SettingsManager': None, - 'FenrirManager': None, - 'EventManager': None, - 'ProcessManager': None, + "SpeechDriver": None, + "ScreenDriver": None, + "SoundDriver": None, + "InputDriver": None, + "RemoteDriver": None, + "InputManager": None, + "CommandManager": None, + "ScreenManager": None, + "OutputManager": None, + "DebugManager": None, + "SettingsManager": None, + "FenrirManager": None, + "EventManager": None, + "ProcessManager": None, } diff --git a/src/fenrirscreenreader/core/sayAllManager.py b/src/fenrirscreenreader/core/sayAllManager.py index 95dc63d0..ebf75fd1 100644 --- a/src/fenrirscreenreader/core/sayAllManager.py +++ b/src/fenrirscreenreader/core/sayAllManager.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class SayAllManager(): +class SayAllManager: def __init__(self): self.isActive = False self.isActiveLock = None diff --git a/src/fenrirscreenreader/core/screenData.py b/src/fenrirscreenreader/core/screenData.py index 86fef3ca..6ba8339c 100644 --- a/src/fenrirscreenreader/core/screenData.py +++ b/src/fenrirscreenreader/core/screenData.py @@ -2,36 +2,37 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import time +from fenrirscreenreader.core import debug + screen_data = { - 'columns': 0, - 'lines': 0, - 'oldDelta': '', - 'oldAttribDelta': '', - 'oldNegativeDelta': '', - 'oldCursorReview': None, - 'oldCursorAttrib': None, - 'old_cursor': {'x': 0, 'y': 0}, - 'oldContentBytes': b'', - 'old_content_text': '', - 'oldContentAttrib': None, - 'oldApplication': '', - 'oldTTY': None, - 'new_delta': '', - 'newNegativeDelta': '', - 'newAttribDelta': '', - 'newCursorReview': None, - 'newCursorAttrib': None, - 'new_cursor': {'x': 0, 'y': 0}, - 'newContentBytes': b'', - 'new_content_text': '', - 'newContentAttrib': None, - 'newTTY': '0', - 'new_application': '', - 'lastScreenUpdate': time.time(), - 'autoIgnoreScreens': [], + "columns": 0, + "lines": 0, + "oldDelta": "", + "oldAttribDelta": "", + "oldNegativeDelta": "", + "oldCursorReview": None, + "oldCursorAttrib": None, + "old_cursor": {"x": 0, "y": 0}, + "oldContentBytes": b"", + "old_content_text": "", + "oldContentAttrib": None, + "oldApplication": "", + "oldTTY": None, + "new_delta": "", + "newNegativeDelta": "", + "newAttribDelta": "", + "newCursorReview": None, + "newCursorAttrib": None, + "new_cursor": {"x": 0, "y": 0}, + "newContentBytes": b"", + "new_content_text": "", + "newContentAttrib": None, + "newTTY": "0", + "new_application": "", + "lastScreenUpdate": time.time(), + "autoIgnoreScreens": [], } diff --git a/src/fenrirscreenreader/core/screenDriver.py b/src/fenrirscreenreader/core/screenDriver.py index 71f3ee68..04708e1d 100644 --- a/src/fenrirscreenreader/core/screenDriver.py +++ b/src/fenrirscreenreader/core/screenDriver.py @@ -2,41 +2,43 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ -class ScreenDriver(): +class ScreenDriver: def __init__(self): self._is_initialized = False self.bgColorNames = { - 0: _('black'), - 1: _('blue'), - 2: _('green'), - 3: _('cyan'), - 4: _('red'), - 5: _('Magenta'), - 6: _('brown/yellow'), - 7: _('white')} + 0: _("black"), + 1: _("blue"), + 2: _("green"), + 3: _("cyan"), + 4: _("red"), + 5: _("Magenta"), + 6: _("brown/yellow"), + 7: _("white"), + } self.fgColorNames = { - 0: _('Black'), - 1: _('Blue'), - 2: _('Green'), - 3: _('Cyan'), - 4: _('Red'), - 5: _('Magenta'), - 6: _('brown/yellow'), - 7: _('Light gray'), - 8: _('Dark gray'), - 9: _('Light blue'), - 10: ('Light green'), - 11: _('Light cyan'), - 12: _('Light red'), - 13: _('Light magenta'), - 14: _('Light yellow'), - 15: _('White')} + 0: _("Black"), + 1: _("Blue"), + 2: _("Green"), + 3: _("Cyan"), + 4: _("Red"), + 5: _("Magenta"), + 6: _("brown/yellow"), + 7: _("Light gray"), + 8: _("Dark gray"), + 9: _("Light blue"), + 10: ("Light green"), + 11: _("Light cyan"), + 12: _("Light red"), + 13: _("Light magenta"), + 14: _("Light yellow"), + 15: _("White"), + } def initialize(self, environment): self.env = environment diff --git a/src/fenrirscreenreader/core/screenManager.py b/src/fenrirscreenreader/core/screenManager.py index d40d0f92..8ceca438 100644 --- a/src/fenrirscreenreader/core/screenManager.py +++ b/src/fenrirscreenreader/core/screenManager.py @@ -2,27 +2,28 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import difflib +import os +import re +import time from fenrirscreenreader.core import debug from fenrirscreenreader.utils import screen_utils -import time -import os -import re -import difflib -class ScreenManager(): +class ScreenManager: def __init__(self): self.differ = difflib.Differ() self.currScreenIgnored = False self.prevScreenIgnored = False - self.prevScreenText = '' - self.currScreenText = '' + self.prevScreenText = "" + self.currScreenText = "" self.colums = None self.rows = None # Compile regex once for better performance - self._space_normalize_regex = re.compile(' +') + self._space_normalize_regex = re.compile(" +") def get_rows(self): return self.rows @@ -32,9 +33,12 @@ class ScreenManager(): def initialize(self, environment): self.env = environment - self.env['runtime']['SettingsManager'].load_driver( - self.env['runtime']['SettingsManager'].get_setting( - 'screen', 'driver'), 'ScreenDriver') + self.env["runtime"]["SettingsManager"].load_driver( + self.env["runtime"]["SettingsManager"].get_setting( + "screen", "driver" + ), + "ScreenDriver", + ) self.get_curr_screen() self.get_curr_screen() self.get_session_information() @@ -42,7 +46,7 @@ class ScreenManager(): self.update_screen_ignored() def reset_screen_text(self, screen_text): - self.prevScreenText = '' + self.prevScreenText = "" self.currScreenText = screen_text def set_screen_text(self, screen_text): @@ -54,22 +58,26 @@ class ScreenManager(): def get_curr_screen(self): try: - self.env['runtime']['ScreenDriver'].get_curr_screen() + self.env["runtime"]["ScreenDriver"].get_curr_screen() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenManager get_curr_screen: Error getting current screen: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenManager get_curr_screen: Error getting current screen: " + + str(e), + debug.DebugLevel.ERROR, + ) def get_session_information(self): try: - self.env['runtime']['ScreenDriver'].get_session_information() + self.env["runtime"]["ScreenDriver"].get_session_information() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenManager get_session_information: Error getting session info: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenManager get_session_information: Error getting session info: " + + str(e), + debug.DebugLevel.ERROR, + ) def shutdown(self): - self.env['runtime']['SettingsManager'].shutdown_driver('ScreenDriver') + self.env["runtime"]["SettingsManager"].shutdown_driver("ScreenDriver") def is_curr_screen_ignored_changed(self): return self.get_curr_screen_ignored() != self.get_prev_screen_ignored() @@ -79,25 +87,27 @@ class ScreenManager(): self.get_session_information() self.update_screen_ignored() if self.is_curr_screen_ignored_changed(): - self.env['runtime']['InputManager'].set_execute_device_grab() - self.env['runtime']['InputManager'].handle_device_grab() - if not self.is_ignored_screen(self.env['screen']['newTTY']): - self.update(event_data, 'onScreenChange') - self.env['screen']['lastScreenUpdate'] = time.time() + self.env["runtime"]["InputManager"].set_execute_device_grab() + self.env["runtime"]["InputManager"].handle_device_grab() + if not self.is_ignored_screen(self.env["screen"]["newTTY"]): + self.update(event_data, "onScreenChange") + self.env["screen"]["lastScreenUpdate"] = time.time() else: - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def handle_screen_update(self, event_data): - self.env['screen']['oldApplication'] = self.env['screen']['new_application'] + self.env["screen"]["oldApplication"] = self.env["screen"][ + "new_application" + ] self.update_screen_ignored() if self.is_curr_screen_ignored_changed(): - self.env['runtime']['InputManager'].set_execute_device_grab() - self.env['runtime']['InputManager'].handle_device_grab() + self.env["runtime"]["InputManager"].set_execute_device_grab() + self.env["runtime"]["InputManager"].handle_device_grab() if not self.get_curr_screen_ignored(): - self.update(event_data, 'onScreenUpdate') - self.env['screen']['lastScreenUpdate'] = time.time() + self.update(event_data, "onScreenUpdate") + self.env["screen"]["lastScreenUpdate"] = time.time() elif self.is_curr_screen_ignored_changed(): - self.env['runtime']['OutputManager'].interrupt_output() + self.env["runtime"]["OutputManager"].interrupt_output() def get_curr_screen_ignored(self): return self.currScreenIgnored @@ -108,49 +118,62 @@ class ScreenManager(): def update_screen_ignored(self): self.prevScreenIgnored = self.currScreenIgnored self.currScreenIgnored = self.is_ignored_screen( - self.env['screen']['newTTY']) + self.env["screen"]["newTTY"] + ) - def update(self, event_data, trigger='onUpdate'): + def update(self, event_data, trigger="onUpdate"): # set new "old" values - self.env['screen']['oldContentBytes'] = self.env['screen']['newContentBytes'] - self.env['screen']['old_content_text'] = self.env['screen']['new_content_text'] - self.env['screen']['old_cursor'] = self.env['screen']['new_cursor'].copy() - self.env['screen']['oldDelta'] = self.env['screen']['new_delta'] - self.env['screen']['oldNegativeDelta'] = self.env['screen']['newNegativeDelta'] - self.env['screen']['newContentBytes'] = event_data['bytes'] + self.env["screen"]["oldContentBytes"] = self.env["screen"][ + "newContentBytes" + ] + self.env["screen"]["old_content_text"] = self.env["screen"][ + "new_content_text" + ] + self.env["screen"]["old_cursor"] = self.env["screen"][ + "new_cursor" + ].copy() + self.env["screen"]["oldDelta"] = self.env["screen"]["new_delta"] + self.env["screen"]["oldNegativeDelta"] = self.env["screen"][ + "newNegativeDelta" + ] + self.env["screen"]["newContentBytes"] = event_data["bytes"] # get metadata like cursor or screensize - self.env['screen']['lines'] = int(event_data['lines']) - self.env['screen']['columns'] = int(event_data['columns']) - self.colums = int(event_data['columns']) - self.rows = int(event_data['lines']) - self.env['screen']['new_cursor']['x'] = int( - event_data['textCursor']['x']) - self.env['screen']['new_cursor']['y'] = int( - event_data['textCursor']['y']) - self.env['screen']['newTTY'] = event_data['screen'] - self.env['screen']['new_content_text'] = event_data['text'] + self.env["screen"]["lines"] = int(event_data["lines"]) + self.env["screen"]["columns"] = int(event_data["columns"]) + self.colums = int(event_data["columns"]) + self.rows = int(event_data["lines"]) + self.env["screen"]["new_cursor"]["x"] = int( + event_data["textCursor"]["x"] + ) + self.env["screen"]["new_cursor"]["y"] = int( + event_data["textCursor"]["y"] + ) + self.env["screen"]["newTTY"] = event_data["screen"] + self.env["screen"]["new_content_text"] = event_data["text"] # screen change if self.is_screen_change(): - self.env['screen']['oldContentBytes'] = b'' - self.reset_screen_text(event_data['text']) - self.env['runtime']['AttributeManager'].reset_attributes( - event_data['attributes']) - self.env['runtime']['AttributeManager'].reset_attribute_cursor() - self.env['screen']['old_content_text'] = '' - self.env['screen']['old_cursor']['x'] = 0 - self.env['screen']['old_cursor']['y'] = 0 - self.env['screen']['oldDelta'] = '' - self.env['screen']['oldNegativeDelta'] = '' + self.env["screen"]["oldContentBytes"] = b"" + self.reset_screen_text(event_data["text"]) + self.env["runtime"]["AttributeManager"].reset_attributes( + event_data["attributes"] + ) + self.env["runtime"]["AttributeManager"].reset_attribute_cursor() + self.env["screen"]["old_content_text"] = "" + self.env["screen"]["old_cursor"]["x"] = 0 + self.env["screen"]["old_cursor"]["y"] = 0 + self.env["screen"]["oldDelta"] = "" + self.env["screen"]["oldNegativeDelta"] = "" else: - self.set_screen_text(event_data['text']) - self.env['runtime']['AttributeManager'].set_attributes( - event_data['attributes']) + self.set_screen_text(event_data["text"]) + self.env["runtime"]["AttributeManager"].set_attributes( + event_data["attributes"] + ) # initialize current deltas - self.env['screen']['newNegativeDelta'] = '' - self.env['screen']['new_delta'] = '' - self.env['runtime']['AttributeManager'].reset_attribute_delta() + self.env["screen"]["newNegativeDelta"] = "" + self.env["screen"]["new_delta"] = "" + self.env["runtime"]["AttributeManager"].reset_attribute_delta() # Diff generation - critical for screen reader functionality # This code detects and categorizes screen content changes to provide appropriate @@ -161,38 +184,72 @@ class ScreenManager(): typing = False diff_list = [] - if (self.env['screen']['old_content_text'] != - self.env['screen']['new_content_text']): + if ( + self.env["screen"]["old_content_text"] + != self.env["screen"]["new_content_text"] + ): # Special case: Initial screen content (going from empty to populated) # This handles first screen load or TTY switch scenarios - if self.env['screen']['new_content_text'] != '' and self.env['screen']['old_content_text'] == '': + if ( + self.env["screen"]["new_content_text"] != "" + and self.env["screen"]["old_content_text"] == "" + ): # Pre-process screen text for comparison - collapse multiple spaces to single space # This normalization prevents spurious diffs from spacing # inconsistencies old_screen_text = self._space_normalize_regex.sub( - ' ', self.env['runtime']['ScreenManager'].get_window_area_in_text( - self.env['screen']['old_content_text'])) + " ", + self.env["runtime"][ + "ScreenManager" + ].get_window_area_in_text( + self.env["screen"]["old_content_text"] + ), + ) new_screen_text = self._space_normalize_regex.sub( - ' ', self.env['runtime']['ScreenManager'].get_window_area_in_text( - self.env['screen']['new_content_text'])) - if old_screen_text == '' and\ - new_screen_text != '': - self.env['screen']['new_delta'] = new_screen_text + " ", + self.env["runtime"][ + "ScreenManager" + ].get_window_area_in_text( + self.env["screen"]["new_content_text"] + ), + ) + if old_screen_text == "" and new_screen_text != "": + self.env["screen"]["new_delta"] = new_screen_text else: # Calculate byte positions for the current cursor's line in the flat text buffer # Formula: (line_number * columns) + line_number accounts for newlines # Each line contributes 'columns' chars + 1 newline char - cursor_line_start = self.env['screen']['new_cursor']['y'] * \ - self.env['screen']['columns'] + self.env['screen']['new_cursor']['y'] - cursor_line_end = cursor_line_start + self.env['screen']['columns'] + cursor_line_start = ( + self.env["screen"]["new_cursor"]["y"] + * self.env["screen"]["columns"] + + self.env["screen"]["new_cursor"]["y"] + ) + cursor_line_end = ( + cursor_line_start + self.env["screen"]["columns"] + ) # TYPING DETECTION ALGORITHM # Determines if this screen change is likely user typing vs other content changes # All conditions must be met for typing detection: - if abs(self.env['screen']['old_cursor']['x'] - self.env['screen']['new_cursor']['x']) >= 1 and \ - self.env['screen']['old_cursor']['y'] == self.env['screen']['new_cursor']['y'] and \ - self.env['screen']['new_content_text'][:cursor_line_start] == self.env['screen']['old_content_text'][:cursor_line_start] and \ - self.env['screen']['new_content_text'][cursor_line_end:] == self.env['screen']['old_content_text'][cursor_line_end:]: + if ( + abs( + self.env["screen"]["old_cursor"]["x"] + - self.env["screen"]["new_cursor"]["x"] + ) + >= 1 + and self.env["screen"]["old_cursor"]["y"] + == self.env["screen"]["new_cursor"]["y"] + and self.env["screen"]["new_content_text"][ + :cursor_line_start + ] + == self.env["screen"]["old_content_text"][ + :cursor_line_start + ] + and self.env["screen"]["new_content_text"][ + cursor_line_end: + ] + == self.env["screen"]["old_content_text"][cursor_line_end:] + ): # Condition 1: Cursor moved horizontally by at least 1 position (typical of typing) # Condition 2: Cursor stayed on same line (typing doesn't usually change lines) # Condition 3: Content BEFORE cursor line is unchanged (text above typing area) @@ -207,32 +264,51 @@ class ScreenManager(): # Limit analysis window to avoid processing entire long lines # +3 provides safety buffer beyond cursor position to catch edge cases - if cursor_line_end > cursor_line_start + \ - self.env['screen']['new_cursor']['x'] + 3: - cursor_line_end_offset = cursor_line_start + \ - self.env['screen']['new_cursor']['x'] + 3 + if ( + cursor_line_end + > cursor_line_start + + self.env["screen"]["new_cursor"]["x"] + + 3 + ): + cursor_line_end_offset = ( + cursor_line_start + + self.env["screen"]["new_cursor"]["x"] + + 3 + ) # Extract just the relevant text sections for # character-level diff - old_screen_text = self.env['screen']['old_content_text'][cursor_line_start_offset:cursor_line_end_offset] - new_screen_text = self.env['screen']['new_content_text'][cursor_line_start_offset:cursor_line_end_offset] + old_screen_text = self.env["screen"]["old_content_text"][ + cursor_line_start_offset:cursor_line_end_offset + ] + new_screen_text = self.env["screen"]["new_content_text"][ + cursor_line_start_offset:cursor_line_end_offset + ] # Character-level diff for typing detection (not # line-level) - diff = self.differ.compare(old_screen_text, new_screen_text) + diff = self.differ.compare( + old_screen_text, new_screen_text + ) diff_list = list(diff) typing = True # Validate typing assumption by checking if detected # changes match cursor movement - temp_new_delta = ''.join(x[2:] - for x in diff_list if x[0] == '+') - if temp_new_delta.strip() != '': + temp_new_delta = "".join( + x[2:] for x in diff_list if x[0] == "+" + ) + if temp_new_delta.strip() != "": # Compare diff result against expected typing pattern # Expected: characters between old and new cursor # positions - expected_typing = ''.join( - new_screen_text[self.env['screen']['old_cursor']['x']:self.env['screen']['new_cursor']['x']].rstrip()) + expected_typing = "".join( + new_screen_text[ + self.env["screen"]["old_cursor"][ + "x" + ] : self.env["screen"]["new_cursor"]["x"] + ].rstrip() + ) # If diff doesn't match expected typing pattern, treat # as general screen change @@ -240,10 +316,12 @@ class ScreenManager(): # Fallback: treat entire current line as new # content diff_list = [ - '+ ' + - self.env['screen']['new_content_text'].split('\n')[ - self.env['screen']['new_cursor']['y']] + - '\n'] + "+ " + + self.env["screen"]["new_content_text"].split( + "\n" + )[self.env["screen"]["new_cursor"]["y"]] + + "\n" + ] typing = False else: # GENERAL SCREEN CHANGE DETECTION @@ -255,14 +333,26 @@ class ScreenManager(): # This normalization prevents spurious diffs from spacing # inconsistencies old_screen_text = self._space_normalize_regex.sub( - ' ', self.env['runtime']['ScreenManager'].get_window_area_in_text( - self.env['screen']['old_content_text'])) + " ", + self.env["runtime"][ + "ScreenManager" + ].get_window_area_in_text( + self.env["screen"]["old_content_text"] + ), + ) new_screen_text = self._space_normalize_regex.sub( - ' ', self.env['runtime']['ScreenManager'].get_window_area_in_text( - self.env['screen']['new_content_text'])) + " ", + self.env["runtime"][ + "ScreenManager" + ].get_window_area_in_text( + self.env["screen"]["new_content_text"] + ), + ) - diff = self.differ.compare(old_screen_text.split('\n'), - new_screen_text.split('\n')) + diff = self.differ.compare( + old_screen_text.split("\n"), + new_screen_text.split("\n"), + ) diff_list = list(diff) # Extract added and removed content from diff results @@ -271,88 +361,120 @@ class ScreenManager(): if not typing: # Line-based changes: join with newlines for proper speech # cadence - self.env['screen']['new_delta'] = '\n'.join( - x[2:] for x in diff_list if x[0] == '+') + self.env["screen"]["new_delta"] = "\n".join( + x[2:] for x in diff_list if x[0] == "+" + ) else: # Character-based changes: no newlines for smooth typing # echo - self.env['screen']['new_delta'] = ''.join( - x[2:] for x in diff_list if x[0] == '+') + self.env["screen"]["new_delta"] = "".join( + x[2:] for x in diff_list if x[0] == "+" + ) # Negative delta (removed content) - used for backspace/delete # detection - self.env['screen']['newNegativeDelta'] = ''.join( - x[2:] for x in diff_list if x[0] == '-') + self.env["screen"]["newNegativeDelta"] = "".join( + x[2:] for x in diff_list if x[0] == "-" + ) # track highlighted try: - if self.env['runtime']['AttributeManager'].is_attribute_change(): - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'focus', 'highlight'): - attribute_delta, attributeCursor = self.env['runtime']['AttributeManager'].track_highlights( - ) + if self.env["runtime"]["AttributeManager"].is_attribute_change(): + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "focus", "highlight" + ): + attribute_delta, attributeCursor = self.env["runtime"][ + "AttributeManager" + ].track_highlights() if attributeCursor: - self.env['runtime']['AttributeManager'].set_attribute_cursor( - attributeCursor) - self.env['runtime']['AttributeManager'].set_attribute_delta( - attribute_delta) + self.env["runtime"][ + "AttributeManager" + ].set_attribute_cursor(attributeCursor) + self.env["runtime"][ + "AttributeManager" + ].set_attribute_delta(attribute_delta) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenManager:update:highlight: ' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenManager:update:highlight: " + str(e), + debug.DebugLevel.ERROR, + ) def is_ignored_screen(self, screen=None): if screen is None: - screen = self.env['screen']['newTTY'] + screen = self.env["screen"]["newTTY"] # Check if force all screens flag is set - if self.env['runtime'].get('force_all_screens', False): + if self.env["runtime"].get("force_all_screens", False): return False ignore_screens = [] - fix_ignore_screens = self.env['runtime']['SettingsManager'].get_setting( - 'screen', 'ignoreScreen') - if fix_ignore_screens != '': - ignore_screens.extend(fix_ignore_screens.split(',')) - if self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'screen', 'autodetectIgnoreScreen'): - ignore_screens.extend(self.env['screen']['autoIgnoreScreens']) - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenManager:is_ignored_screen ignore:' + - str(ignore_screens) + - ' current:' + - str(screen), - debug.DebugLevel.INFO) - return (screen in ignore_screens) + fix_ignore_screens = self.env["runtime"][ + "SettingsManager" + ].get_setting("screen", "ignoreScreen") + if fix_ignore_screens != "": + ignore_screens.extend(fix_ignore_screens.split(",")) + if self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "screen", "autodetectIgnoreScreen" + ): + ignore_screens.extend(self.env["screen"]["autoIgnoreScreens"]) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenManager:is_ignored_screen ignore:" + + str(ignore_screens) + + " current:" + + str(screen), + debug.DebugLevel.INFO, + ) + return screen in ignore_screens def is_screen_change(self): - if not self.env['screen']['oldTTY']: + if not self.env["screen"]["oldTTY"]: return False - return self.env['screen']['newTTY'] != self.env['screen']['oldTTY'] + return self.env["screen"]["newTTY"] != self.env["screen"]["oldTTY"] def is_delta(self, ignoreSpace=False): - new_delta = self.env['screen']['new_delta'] + new_delta = self.env["screen"]["new_delta"] if ignoreSpace: new_delta = new_delta.strip() - return new_delta != '' + return new_delta != "" def is_negative_delta(self): - return self.env['screen']['newNegativeDelta'] != '' + return self.env["screen"]["newNegativeDelta"] != "" def get_window_area_in_text(self, text): - if not self.env['runtime']['CursorManager'].is_application_window_set(): + if not self.env["runtime"][ + "CursorManager" + ].is_application_window_set(): return text - window_text = '' - window_list = text.split('\n') - curr_app = self.env['runtime']['ApplicationManager'].get_current_application() - window_list = window_list[self.env['commandBuffer']['windowArea'][curr_app][ - '1']['y']:self.env['commandBuffer']['windowArea'][curr_app]['2']['y'] + 1] + window_text = "" + window_list = text.split("\n") + curr_app = self.env["runtime"][ + "ApplicationManager" + ].get_current_application() + window_list = window_list[ + self.env["commandBuffer"]["windowArea"][curr_app]["1"][ + "y" + ] : self.env["commandBuffer"]["windowArea"][curr_app]["2"]["y"] + + 1 + ] for line in window_list: - window_text += line[self.env['commandBuffer']['windowArea'][curr_app]['1']['x'] - :self.env['commandBuffer']['windowArea'][curr_app]['2']['x'] + 1] + '\n' + window_text += ( + line[ + self.env["commandBuffer"]["windowArea"][curr_app]["1"][ + "x" + ] : self.env["commandBuffer"]["windowArea"][curr_app]["2"][ + "x" + ] + + 1 + ] + + "\n" + ) return window_text def inject_text_to_screen(self, text, screen=None): try: - self.env['runtime']['ScreenDriver'].inject_text_to_screen( - text, screen) + self.env["runtime"]["ScreenDriver"].inject_text_to_screen( + text, screen + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenManager:inject_text_to_screen ' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenManager:inject_text_to_screen " + str(e), + debug.DebugLevel.ERROR, + ) diff --git a/src/fenrirscreenreader/core/settingsData.py b/src/fenrirscreenreader/core/settingsData.py index 7cbc8b3c..944775f8 100644 --- a/src/fenrirscreenreader/core/settingsData.py +++ b/src/fenrirscreenreader/core/settingsData.py @@ -2,123 +2,123 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug settings_data = { - 'sound': { - 'enabled': True, - 'driver': 'genericDriver', - 'theme': 'default', - 'volume': 1.0, - 'genericPlayFileCommand': 'play -q -v fenrirVolume fenrirSoundFile', - 'genericFrequencyCommand': 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' + "sound": { + "enabled": True, + "driver": "genericDriver", + "theme": "default", + "volume": 1.0, + "genericPlayFileCommand": "play -q -v fenrirVolume fenrirSoundFile", + "genericFrequencyCommand": "play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence", }, - 'speech': { - 'enabled': True, - 'driver': 'genericDriver', - 'serverPath': '', - 'rate': 0.75, - 'pitch': 0.5, - 'capitalPitch': 0.8, - 'volume': 1.0, - 'module': '', - 'voice': 'en-us', - 'language': '', - 'autoReadIncoming': True, - 'readNumbersAsDigits': False, - 'genericSpeechCommand': 'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"', - 'fenrirMinVolume': 0, - 'fenrirMaxVolume': 200, - 'fenrirMinPitch': 0, - 'fenrirMaxPitch': 99, - 'fenrirMinRate': 80, - 'fenrirMaxRate': 450, + "speech": { + "enabled": True, + "driver": "genericDriver", + "serverPath": "", + "rate": 0.75, + "pitch": 0.5, + "capitalPitch": 0.8, + "volume": 1.0, + "module": "", + "voice": "en-us", + "language": "", + "autoReadIncoming": True, + "readNumbersAsDigits": False, + "genericSpeechCommand": 'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"', + "fenrirMinVolume": 0, + "fenrirMaxVolume": 200, + "fenrirMinPitch": 0, + "fenrirMaxPitch": 99, + "fenrirMinRate": 80, + "fenrirMaxRate": 450, }, - 'screen': { - 'driver': 'vcsaDriver', - 'encoding': 'auto', - 'screenUpdateDelay': 0.1, - 'ignoreScreen': '', - 'autodetectIgnoreScreen': False, + "screen": { + "driver": "vcsaDriver", + "encoding": "auto", + "screenUpdateDelay": 0.1, + "ignoreScreen": "", + "autodetectIgnoreScreen": False, }, - 'general': { - 'debug_level': debug.DebugLevel.DEACTIVE, - 'debug_mode': 'FILE', - 'debugFile': '', - 'punctuationProfile': 'default', - 'punctuationLevel': 'some', - 'respectPunctuationPause': True, - 'newLinePause': True, - 'numberOfClipboards': 10, - 'emoticons': True, - 'fenrirKeys': 'KEY_KP0,KEY_META', - 'scriptKeys': 'KEY_COMPOSE', - 'time_format': '%I:%M%P', - 'date_format': '%A, %B %d, %Y', - 'autoSpellCheck': False, - 'spellCheckLanguage': 'en_US', - 'script_path': '/usr/share/fenrirscreenreader/scripts', - 'command_path': '/usr/share/fenrirscreenreader/commands', - 'attribute_format_string': 'Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize', - 'autoPresentIndent': False, - 'autoPresentIndentMode': 1, - 'has_attributes': True, - 'shell': '', + "general": { + "debug_level": debug.DebugLevel.DEACTIVE, + "debug_mode": "FILE", + "debugFile": "", + "punctuationProfile": "default", + "punctuationLevel": "some", + "respectPunctuationPause": True, + "newLinePause": True, + "numberOfClipboards": 10, + "emoticons": True, + "fenrirKeys": "KEY_KP0,KEY_META", + "scriptKeys": "KEY_COMPOSE", + "time_format": "%I:%M%P", + "date_format": "%A, %B %d, %Y", + "autoSpellCheck": False, + "spellCheckLanguage": "en_US", + "script_path": "/usr/share/fenrirscreenreader/scripts", + "command_path": "/usr/share/fenrirscreenreader/commands", + "attribute_format_string": "Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize", + "autoPresentIndent": False, + "autoPresentIndentMode": 1, + "has_attributes": True, + "shell": "", }, - 'focus': { - 'cursor': True, - 'highlight': False, + "focus": { + "cursor": True, + "highlight": False, }, - 'remote': { - 'enabled': True, - 'driver': 'unixDriver', - 'port': 22447, - 'socket_file': '', - 'enableSettingsRemote': True, - 'enableCommandRemote': True, + "remote": { + "enabled": True, + "driver": "unixDriver", + "port": 22447, + "socket_file": "", + "enableSettingsRemote": True, + "enableCommandRemote": True, }, - 'barrier': { - 'enabled': True, - 'left_barriers': '│└┌─', - 'right_barriers': '│┘┐─', + "barrier": { + "enabled": True, + "left_barriers": "│└┌─", + "right_barriers": "│┘┐─", }, - 'review': { - 'line_break': True, - 'end_of_screen': True, - 'leaveReviewOnCursorChange': True, - 'leaveReviewOnScreenChange': True, + "review": { + "line_break": True, + "end_of_screen": True, + "leaveReviewOnCursorChange": True, + "leaveReviewOnScreenChange": True, }, - 'menu': { - 'vmenuPath': '', - 'quickMenu': 'speech#rate;speech#pitch;speech#volume', + "menu": { + "vmenuPath": "", + "quickMenu": "speech#rate;speech#pitch;speech#volume", }, - 'promote': { - 'enabled': True, - 'inactiveTimeoutSec': 120, - 'list': '', + "promote": { + "enabled": True, + "inactiveTimeoutSec": 120, + "list": "", }, - 'time': { - 'enabled': False, - 'present_time': True, - 'present_date': True, - 'delay_sec': 0, - 'on_minutes': '00,30', - 'announce': True, - 'interrupt': False, + "time": { + "enabled": False, + "present_time": True, + "present_date": True, + "delay_sec": 0, + "on_minutes": "00,30", + "announce": True, + "interrupt": False, + }, + "keyboard": { + "driver": "evdev", + "device": "all", + "grabDevices": True, + "ignoreShortcuts": False, + "keyboardLayout": "desktop", + "charEchoMode": 2, # while capslock + "charDeleteEcho": True, + "wordEcho": True, + "interruptOnKeyPress": True, + "interruptOnKeyPressFilter": "", + "doubleTapTimeout": 0.2, }, - 'keyboard': { - 'driver': 'evdev', - 'device': 'all', - 'grabDevices': True, - 'ignoreShortcuts': False, - 'keyboardLayout': "desktop", - 'charEchoMode': 2, # while capslock - 'charDeleteEcho': True, - 'wordEcho': True, - 'interruptOnKeyPress': True, - 'interruptOnKeyPressFilter': '', - 'doubleTapTimeout': 0.2, - } } diff --git a/src/fenrirscreenreader/core/settingsManager.py b/src/fenrirscreenreader/core/settingsManager.py index ef422dee..8d9ceb5a 100644 --- a/src/fenrirscreenreader/core/settingsManager.py +++ b/src/fenrirscreenreader/core/settingsManager.py @@ -2,51 +2,50 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import environment -from fenrirscreenreader.utils import module_utils -from fenrirscreenreader.core import debug -from fenrirscreenreader.core.settingsData import settings_data -from fenrirscreenreader.core import quickMenuManager -from fenrirscreenreader.core import sayAllManager -from fenrirscreenreader.core import remoteManager -from fenrirscreenreader.core import barrierManager +import inspect +import os +from configparser import ConfigParser + +from fenrirscreenreader.core import applicationManager from fenrirscreenreader.core import attributeManager +from fenrirscreenreader.core import barrierManager from fenrirscreenreader.core import byteManager +from fenrirscreenreader.core import commandManager +from fenrirscreenreader.core import cursorManager +from fenrirscreenreader.core import debug +from fenrirscreenreader.core import debugManager +from fenrirscreenreader.core import environment +from fenrirscreenreader.core import eventManager +from fenrirscreenreader.core import helpManager +from fenrirscreenreader.core import inputManager +from fenrirscreenreader.core import memoryManager +from fenrirscreenreader.core import outputManager +from fenrirscreenreader.core import processManager +from fenrirscreenreader.core import punctuationManager +from fenrirscreenreader.core import quickMenuManager +from fenrirscreenreader.core import remoteManager +from fenrirscreenreader.core import sayAllManager +from fenrirscreenreader.core import screenManager from fenrirscreenreader.core import tableManager from fenrirscreenreader.core import textManager from fenrirscreenreader.core import vmenuManager -from fenrirscreenreader.core import helpManager -from fenrirscreenreader.core import applicationManager -from fenrirscreenreader.core import cursorManager -from fenrirscreenreader.core import punctuationManager -from fenrirscreenreader.core import screenManager -from fenrirscreenreader.core import commandManager -from fenrirscreenreader.core import outputManager -from fenrirscreenreader.core import inputManager -from fenrirscreenreader.core import eventManager -from fenrirscreenreader.core import processManager -from fenrirscreenreader.core import memoryManager -from fenrirscreenreader.core import debugManager -from configparser import ConfigParser -import os -import inspect +from fenrirscreenreader.core.settingsData import settings_data +from fenrirscreenreader.utils import module_utils currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class SettingsManager(): +class SettingsManager: def __init__(self): self.settings = settings_data self.settingArgDict = {} self.bindingsBackup = None - self.settings_file = '' + self.settings_file = "" def initialize(self, environment): self.env = environment @@ -61,42 +60,44 @@ class SettingsManager(): # Use passed environment or fall back to self.env env = environment if environment is not None else self.env try: - with open(soundIconPath + '/soundicons.conf', "r") as siConfig: - while (True): + with open(soundIconPath + "/soundicons.conf", "r") as siConfig: + while True: line = siConfig.readline() if not line: break - line = line.replace('\n', '') - if line.replace(" ", "") == '': + line = line.replace("\n", "") + if line.replace(" ", "") == "": continue if line.replace(" ", "").startswith("#"): continue if line.count("=") != 1: continue - values = line.split('=') + values = line.split("=") sound_icon = values[0].upper() values[1] = values[1].replace("'", "") values[1] = values[1].replace('"', "") - sound_icon_file = '' + sound_icon_file = "" if os.path.exists(values[1]): sound_icon_file = values[1] else: if not soundIconPath.endswith("/"): - soundIconPath += '/' + soundIconPath += "/" if os.path.exists(soundIconPath + values[1]): sound_icon_file = soundIconPath + values[1] - env['soundIcons'][sound_icon] = sound_icon_file - env['runtime']['DebugManager'].write_debug_out( - "SoundIcon: " + sound_icon + '.' + sound_icon_file, + env["soundIcons"][sound_icon] = sound_icon_file + env["runtime"]["DebugManager"].write_debug_out( + "SoundIcon: " + sound_icon + "." + sound_icon_file, debug.DebugLevel.INFO, - on_any_level=True) + on_any_level=True, + ) except (IOError, OSError) as e: - env['runtime']['DebugManager'].write_debug_out( - 'load_sound_icons: failed to load sound icons from ' + - soundIconPath + - '. Error: ' + - str(e), - debug.DebugLevel.ERROR) + env["runtime"]["DebugManager"].write_debug_out( + "load_sound_icons: failed to load sound icons from " + + soundIconPath + + ". Error: " + + str(e), + debug.DebugLevel.ERROR, + ) def get_settings_file(self): return self.settings_file @@ -113,13 +114,15 @@ class SettingsManager(): return False if not os.access(setting_config_path, os.R_OK): return False - self.env['settings'] = ConfigParser() + self.env["settings"] = ConfigParser() try: - self.env['settings'].read(setting_config_path) + self.env["settings"].read(setting_config_path) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'settings_manager load_settings: Error reading config file: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "settings_manager load_settings: Error reading config file: " + + str(e), + debug.DebugLevel.ERROR, + ) return False self.set_settings_file(setting_config_path) return True @@ -132,34 +135,35 @@ class SettingsManager(): for section, settings in self.settingArgDict.items(): for setting, value in settings.items(): # print(section, setting, value) - self.env['settings'].set(section, setting, value) + self.env["settings"].set(section, setting, value) # print('full',self.env['settings']) - config_file = open(setting_config_path, 'w') - self.env['settings'].write(config_file) + config_file = open(setting_config_path, "w") + self.env["settings"].write(config_file) config_file.close() os.chmod(setting_config_path, 0o644) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'save_settings: save settingsfile:' + - setting_config_path + - 'failed. Error:' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "save_settings: save settingsfile:" + + setting_config_path + + "failed. Error:" + + str(e), + debug.DebugLevel.ERROR, + ) def set_setting(self, section, setting, value): self.set_option_arg_dict(section, setting, value) # self.env['settings'].set(section, setting, value) def get_setting(self, section, setting): - value = '' + value = "" try: value = self.settingArgDict[section][setting] return value except Exception as e: pass try: - value = self.env['settings'].get(section, setting) + value = self.env["settings"].get(section, setting) except Exception as e: value = str(self.settings[section][setting]) return value @@ -172,7 +176,7 @@ class SettingsManager(): except Exception as e: pass try: - value = self.env['settings'].getint(section, setting) + value = self.env["settings"].getint(section, setting) except Exception as e: value = self.settings[section][setting] return value @@ -185,7 +189,7 @@ class SettingsManager(): except Exception as e: pass try: - value = self.env['settings'].getfloat(section, setting) + value = self.env["settings"].getfloat(section, setting) except Exception as e: value = self.settings[section][setting] return value @@ -194,12 +198,16 @@ class SettingsManager(): value = False try: value = self.settingArgDict[section][setting].upper() in [ - '1', 'YES', 'JA', 'TRUE'] + "1", + "YES", + "JA", + "TRUE", + ] return value except Exception as e: pass try: - value = self.env['settings'].getboolean(section, setting) + value = self.env["settings"].getboolean(section, setting) except Exception as e: value = self.settings[section][setting] return value @@ -207,71 +215,85 @@ class SettingsManager(): def load_driver(self, driverName, driverType): # Map runtime keys to actual directory names driver_dir_map = { - 'InputDriver': 'inputDriver', - 'ScreenDriver': 'screenDriver', - 'SpeechDriver': 'speechDriver', - 'SoundDriver': 'soundDriver', - 'RemoteDriver': 'remoteDriver' + "InputDriver": "inputDriver", + "ScreenDriver": "screenDriver", + "SpeechDriver": "speechDriver", + "SoundDriver": "soundDriver", + "RemoteDriver": "remoteDriver", } driver_dir = driver_dir_map.get(driverType, driverType) - + try: - if self.env['runtime'][driverType] is not None: - self.env['runtime'][driverType].shutdown(self.env) + if self.env["runtime"][driverType] is not None: + self.env["runtime"][driverType].shutdown(self.env) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'settings_manager load_driver: Error shutting down driver: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "settings_manager load_driver: Error shutting down driver: " + + str(e), + debug.DebugLevel.ERROR, + ) try: driver_mod = module_utils.import_module( - driverName, fenrir_path + "/" + driver_dir + '/' + driverName + '.py') - self.env['runtime'][driverType] = driver_mod.driver() - self.env['runtime'][driverType].initialize(self.env) - self.env['runtime']['DebugManager'].write_debug_out( - 'Loading Driver ' + driverType + ' (' + driverName + ") OK", + driverName, + fenrir_path + "/" + driver_dir + "/" + driverName + ".py", + ) + self.env["runtime"][driverType] = driver_mod.driver() + self.env["runtime"][driverType].initialize(self.env) + self.env["runtime"]["DebugManager"].write_debug_out( + "Loading Driver " + driverType + " (" + driverName + ") OK", debug.DebugLevel.INFO, - on_any_level=True) + on_any_level=True, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'Loading Driver ' + driverType + ' (' + driverName + ") FAILED:" + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "Loading Driver " + + driverType + + " (" + + driverName + + ") FAILED:" + + str(e), + debug.DebugLevel.ERROR, + ) try: driver_mod = module_utils.import_module( - driverName, fenrir_path + "/" + driver_dir + '/dummyDriver.py') - self.env['runtime'][driverType] = driver_mod.driver() - self.env['runtime'][driverType].initialize(self.env) + driverName, + fenrir_path + "/" + driver_dir + "/dummyDriver.py", + ) + self.env["runtime"][driverType] = driver_mod.driver() + self.env["runtime"][driverType].initialize(self.env) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - '(fallback) Loading Driver ' + - driverType + - ' (dummyDriver) FAILED:' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "(fallback) Loading Driver " + + driverType + + " (dummyDriver) FAILED:" + + str(e), + debug.DebugLevel.ERROR, + ) def shutdown_driver(self, driverType): try: - self.env['runtime'][driverType].shutdown() + self.env["runtime"][driverType].shutdown() except Exception as e: pass - del self.env['runtime'][driverType] + del self.env["runtime"][driverType] def set_fenrir_keys(self, keys): keys = keys.upper() - key_list = keys.split(',') + key_list = keys.split(",") for key in key_list: - if key not in self.env['input']['fenrirKey']: - self.env['input']['fenrirKey'].append(key) + if key not in self.env["input"]["fenrirKey"]: + self.env["input"]["fenrirKey"].append(key) def set_script_keys(self, keys): keys = keys.upper() - key_list = keys.split(',') + key_list = keys.split(",") for key in key_list: - if key not in self.env['input']['scriptKey']: - self.env['input']['scriptKey'].append(key) + if key not in self.env["input"]["scriptKey"]: + self.env["input"]["scriptKey"].append(key) def reset_setting_arg_dict(self): self.settingArgDict = {} - self.env['runtime']['OutputManager'].reset_SpeechDriver() + self.env["runtime"]["OutputManager"].reset_SpeechDriver() def set_option_arg_dict(self, section, setting, value): # section = section.lower() @@ -283,17 +305,18 @@ class SettingsManager(): try: t = self.settings[section][setting] except Exception as e: - print(section, setting, 'not found') + print(section, setting, "not found") return try: v = value # Initialize v with the original value if isinstance(self.settings[section][setting], str): v = str(value) elif isinstance(self.settings[section][setting], bool): - if value not in ['True', 'False']: + if value not in ["True", "False"]: raise ValueError( - 'could not convert string to bool: ' + value) - v = value == 'True' + "could not convert string to bool: " + value + ) + v = value == "True" elif isinstance(self.settings[section][setting], int): v = int(value) elif isinstance(self.settings[section][setting], float): @@ -304,8 +327,16 @@ class SettingsManager(): self.settingArgDict[section][setting] = str(value) except Exception as e: - print('settings_manager:set_option_arg_dict:Datatype missmatch: ' + - section + '#' + setting + '=' + str(value) + ' Error:' + str(e)) + print( + "settings_manager:set_option_arg_dict:Datatype missmatch: " + + section + + "#" + + setting + + "=" + + str(value) + + " Error:" + + str(e) + ) # self.env['runtime']['DebugManager'].write_debug_out('settings_manager:set_option_arg_dict:Datatype # missmatch: '+ section + '#' + setting + '=' + value + ' Error:' # + str(e), debug.DebugLevel.ERROR) @@ -314,93 +345,106 @@ class SettingsManager(): def _validate_setting_value(self, section, setting, value): """Validate setting values for critical screen reader functionality. Only validates settings that could cause crashes or accessibility issues. - Invalid values raise ValueError which is caught by the calling method.""" + Invalid values raise ValueError which is caught by the calling method. + """ # Speech settings validation - critical for accessibility - if section == 'speech': - if setting == 'rate': + if section == "speech": + if setting == "rate": if not (0.0 <= value <= 3.0): raise ValueError( - f'Speech rate must be between 0.0 and 3.0, got {value}') - elif setting == 'pitch': + f"Speech rate must be between 0.0 and 3.0, got {value}" + ) + elif setting == "pitch": if not (0.0 <= value <= 2.0): raise ValueError( - f'Speech pitch must be between 0.0 and 2.0, got {value}') - elif setting == 'volume': + f"Speech pitch must be between 0.0 and 2.0, got {value}" + ) + elif setting == "volume": if not (0.0 <= value <= 1.5): raise ValueError( - f'Speech volume must be between 0.0 and 1.5, got {value}') - elif setting == 'driver': + f"Speech volume must be between 0.0 and 1.5, got {value}" + ) + elif setting == "driver": valid_drivers = [ - 'speechdDriver', - 'genericDriver', - 'dummyDriver'] + "speechdDriver", + "genericDriver", + "dummyDriver", + ] if value not in valid_drivers: raise ValueError( - f'Invalid speech driver: {value}. Valid options: {valid_drivers}') + f"Invalid speech driver: {value}. Valid options: {valid_drivers}" + ) # Sound settings validation - elif section == 'sound': - if setting == 'volume': + elif section == "sound": + if setting == "volume": if not (0.0 <= value <= 1.5): raise ValueError( - f'Sound volume must be between 0.0 and 1.5, got {value}') - elif setting == 'driver': + f"Sound volume must be between 0.0 and 1.5, got {value}" + ) + elif setting == "driver": valid_drivers = [ - 'genericDriver', - 'gstreamerDriver', - 'dummyDriver'] + "genericDriver", + "gstreamerDriver", + "dummyDriver", + ] if value not in valid_drivers: raise ValueError( - f'Invalid sound driver: {value}. Valid options: {valid_drivers}') + f"Invalid sound driver: {value}. Valid options: {valid_drivers}" + ) # Screen settings validation - elif section == 'screen': - if setting == 'driver': - valid_drivers = ['vcsaDriver', 'ptyDriver', 'dummyDriver'] + elif section == "screen": + if setting == "driver": + valid_drivers = ["vcsaDriver", "ptyDriver", "dummyDriver"] if value not in valid_drivers: raise ValueError( - f'Invalid screen driver: {value}. Valid options: {valid_drivers}') + f"Invalid screen driver: {value}. Valid options: {valid_drivers}" + ) # Input settings validation - elif section == 'keyboard': - if setting == 'driver': + elif section == "keyboard": + if setting == "driver": valid_drivers = [ - 'evdevDriver', - 'ptyDriver', - 'atspiDriver', - 'dummyDriver'] + "evdevDriver", + "ptyDriver", + "atspiDriver", + "dummyDriver", + ] if value not in valid_drivers: raise ValueError( - f'Invalid input driver: {value}. Valid options: {valid_drivers}') + f"Invalid input driver: {value}. Valid options: {valid_drivers}" + ) # General settings validation - elif section == 'general': - if setting == 'debug_level': + elif section == "general": + if setting == "debug_level": if not (0 <= value <= 3): raise ValueError( - f'Debug level must be between 0 and 3, got {value}') + f"Debug level must be between 0 and 3, got {value}" + ) def parse_setting_args(self, settingArgs): if settingArgs is None: return - for optionElem in settingArgs.split(';'): + for optionElem in settingArgs.split(";"): setting_val_list = [] section_option_list = [] - section = '' - option = '' - value = '' - setting_val_list = optionElem.split('=', 1) + section = "" + option = "" + value = "" + setting_val_list = optionElem.split("=", 1) if len(setting_val_list) != 2: continue - if '#' in setting_val_list[0]: - section_option_list = setting_val_list[0].split('#', 1) - elif '.' in setting_val_list[0]: - section_option_list = setting_val_list[0].split('.', 1) - elif ',' in setting_val_list[0]: - section_option_list = setting_val_list[0].split(',', 1) - elif '!' in setting_val_list[0]: - section_option_list = setting_val_list[0].split('!', 1) + if "#" in setting_val_list[0]: + section_option_list = setting_val_list[0].split("#", 1) + elif "." in setting_val_list[0]: + section_option_list = setting_val_list[0].split(".", 1) + elif "," in setting_val_list[0]: + section_option_list = setting_val_list[0].split(",", 1) + elif "!" in setting_val_list[0]: + section_option_list = setting_val_list[0].split("!", 1) else: continue if len(section_option_list) != 2: @@ -412,302 +456,326 @@ class SettingsManager(): self.set_option_arg_dict(section, option, value) def init_fenrir_config( - self, - cliArgs, - fenrir_manager=None, - environment=environment.environment): - settings_root = '/etc/fenrirscreenreader/' + self, cliArgs, fenrir_manager=None, environment=environment.environment + ): + settings_root = "/etc/fenrirscreenreader/" settings_file = cliArgs.setting - sound_root = '/usr/share/sounds/fenrirscreenreader/' + sound_root = "/usr/share/sounds/fenrirscreenreader/" # get fenrir settings root if not os.path.exists(settings_root): - if os.path.exists(fenrir_path + '/../../config/'): - settings_root = fenrir_path + '/../../config/' + if os.path.exists(fenrir_path + "/../../config/"): + settings_root = fenrir_path + "/../../config/" else: return None # get settings file if settings_file is None or not os.path.exists(settings_file): - if os.path.exists(settings_root + '/settings/settings.conf'): - settings_file = settings_root + '/settings/settings.conf' + if os.path.exists(settings_root + "/settings/settings.conf"): + settings_file = settings_root + "/settings/settings.conf" else: return None # get sound themes root if not os.path.exists(sound_root): - if os.path.exists(fenrir_path + '/../../config/sound/'): - sound_root = fenrir_path + '/../../config/sound/' + if os.path.exists(fenrir_path + "/../../config/sound/"): + sound_root = fenrir_path + "/../../config/sound/" - environment['runtime']['SettingsManager'] = self - environment['runtime']['SettingsManager'].initialize(environment) + environment["runtime"]["SettingsManager"] = self + environment["runtime"]["SettingsManager"].initialize(environment) - valid_config = environment['runtime']['SettingsManager'].load_settings( - settings_file) + valid_config = environment["runtime"]["SettingsManager"].load_settings( + settings_file + ) if not valid_config: return None - if cliArgs.options != '': + if cliArgs.options != "": self.parse_setting_args(cliArgs.options) if cliArgs.debug: - self.set_setting('general', 'debug_level', 3) + self.set_setting("general", "debug_level", 3) if cliArgs.print: - self.set_setting('general', 'debug_level', 3) - self.set_setting('general', 'debug_mode', 'PRINT') + self.set_setting("general", "debug_level", 3) + self.set_setting("general", "debug_mode", "PRINT") if cliArgs.emulated_pty: - self.set_setting('screen', 'driver', 'ptyDriver') - self.set_setting('keyboard', 'driver', 'ptyDriver') + self.set_setting("screen", "driver", "ptyDriver") + self.set_setting("keyboard", "driver", "ptyDriver") # TODO needs cleanup use dict # self.set_option_arg_dict('keyboard', 'keyboardLayout', 'pty') - self.set_setting('keyboard', 'keyboardLayout', 'pty') + self.set_setting("keyboard", "keyboardLayout", "pty") if cliArgs.emulated_evdev: - self.set_setting('screen', 'driver', 'ptyDriver') - self.set_setting('keyboard', 'driver', 'evdevDriver') + self.set_setting("screen", "driver", "ptyDriver") + self.set_setting("keyboard", "driver", "evdevDriver") - self.set_fenrir_keys(self.get_setting('general', 'fenrirKeys')) - self.set_script_keys(self.get_setting('general', 'scriptKeys')) + self.set_fenrir_keys(self.get_setting("general", "fenrirKeys")) + self.set_script_keys(self.get_setting("general", "scriptKeys")) - environment['runtime']['DebugManager'] = debugManager.DebugManager( - self.env['runtime']['SettingsManager'].get_setting('general', 'debugFile')) - environment['runtime']['DebugManager'].initialize(environment) + environment["runtime"]["DebugManager"] = debugManager.DebugManager( + self.env["runtime"]["SettingsManager"].get_setting( + "general", "debugFile" + ) + ) + environment["runtime"]["DebugManager"].initialize(environment) if cliArgs.force_all_screens: - environment['runtime']['force_all_screens'] = True + environment["runtime"]["force_all_screens"] = True if cliArgs.ignore_screen: - current_ignore_screen = self.get_setting('screen', 'ignoreScreen') + current_ignore_screen = self.get_setting("screen", "ignoreScreen") if current_ignore_screen: - ignore_screens = current_ignore_screen.split( - ',') + cliArgs.ignore_screen + ignore_screens = ( + current_ignore_screen.split(",") + cliArgs.ignore_screen + ) else: ignore_screens = cliArgs.ignore_screen - self.set_setting('screen', 'ignoreScreen', ','.join(ignore_screens)) + self.set_setting( + "screen", "ignoreScreen", ",".join(ignore_screens) + ) if not os.path.exists( - self.get_setting( - 'sound', - 'theme') + - '/soundicons.conf'): - if os.path.exists(sound_root + self.get_setting('sound', 'theme')): + self.get_setting("sound", "theme") + "/soundicons.conf" + ): + if os.path.exists(sound_root + self.get_setting("sound", "theme")): self.set_setting( - 'sound', - 'theme', - sound_root + - self.get_setting( - 'sound', - 'theme')) + "sound", + "theme", + sound_root + self.get_setting("sound", "theme"), + ) if os.path.exists( - self.get_setting( - 'sound', - 'theme') + - '/soundicons.conf'): - environment['runtime']['SettingsManager'].load_sound_icons( - self.get_setting('sound', 'theme'), environment) + self.get_setting("sound", "theme") + "/soundicons.conf" + ): + environment["runtime"]["SettingsManager"].load_sound_icons( + self.get_setting("sound", "theme"), environment + ) else: - environment['runtime']['SettingsManager'].load_sound_icons( - self.get_setting('sound', 'theme'), environment) + environment["runtime"]["SettingsManager"].load_sound_icons( + self.get_setting("sound", "theme"), environment + ) - environment['runtime']['PunctuationManager'] = punctuationManager.PunctuationManager() - environment['runtime']['PunctuationManager'].initialize(environment) + environment["runtime"][ + "PunctuationManager" + ] = punctuationManager.PunctuationManager() + environment["runtime"]["PunctuationManager"].initialize(environment) - environment['runtime']['TextManager'] = textManager.TextManager() - environment['runtime']['TextManager'].initialize(environment) + environment["runtime"]["TextManager"] = textManager.TextManager() + environment["runtime"]["TextManager"].initialize(environment) if not os.path.exists( - self.get_setting( - 'general', - 'punctuationProfile')): + self.get_setting("general", "punctuationProfile") + ): if os.path.exists( - settings_root + - 'punctuation/' + - self.get_setting( - 'general', - 'punctuationProfile')): + settings_root + + "punctuation/" + + self.get_setting("general", "punctuationProfile") + ): self.set_setting( - 'general', - 'punctuationProfile', - settings_root + - 'punctuation/' + - self.get_setting( - 'general', - 'punctuationProfile')) - environment['runtime']['PunctuationManager'].load_dicts( - self.get_setting('general', 'punctuationProfile')) + "general", + "punctuationProfile", + settings_root + + "punctuation/" + + self.get_setting("general", "punctuationProfile"), + ) + environment["runtime"]["PunctuationManager"].load_dicts( + self.get_setting("general", "punctuationProfile") + ) if os.path.exists( - settings_root + - 'punctuation/' + - self.get_setting( - 'general', - 'punctuationProfile') + - '.conf'): + settings_root + + "punctuation/" + + self.get_setting("general", "punctuationProfile") + + ".conf" + ): self.set_setting( - 'general', - 'punctuationProfile', - settings_root + - 'punctuation/' + - self.get_setting( - 'general', - 'punctuationProfile') + - '.conf') - environment['runtime']['PunctuationManager'].load_dicts( - self.get_setting('general', 'punctuationProfile')) + "general", + "punctuationProfile", + settings_root + + "punctuation/" + + self.get_setting("general", "punctuationProfile") + + ".conf", + ) + environment["runtime"]["PunctuationManager"].load_dicts( + self.get_setting("general", "punctuationProfile") + ) else: - environment['runtime']['PunctuationManager'].load_dicts( - self.get_setting('general', 'punctuationProfile')) + environment["runtime"]["PunctuationManager"].load_dicts( + self.get_setting("general", "punctuationProfile") + ) if fenrir_manager: - environment['runtime']['FenrirManager'] = fenrir_manager + environment["runtime"]["FenrirManager"] = fenrir_manager - environment['runtime']['MemoryManager'] = memoryManager.MemoryManager() - environment['runtime']['MemoryManager'].initialize(environment) + environment["runtime"]["MemoryManager"] = memoryManager.MemoryManager() + environment["runtime"]["MemoryManager"].initialize(environment) - environment['runtime']['AttributeManager'] = attributeManager.AttributeManager() - environment['runtime']['AttributeManager'].initialize(environment) + environment["runtime"][ + "AttributeManager" + ] = attributeManager.AttributeManager() + environment["runtime"]["AttributeManager"].initialize(environment) - environment['runtime']['EventManager'] = eventManager.EventManager() - environment['runtime']['EventManager'].initialize(environment) + environment["runtime"]["EventManager"] = eventManager.EventManager() + environment["runtime"]["EventManager"].initialize(environment) - environment['runtime']['ProcessManager'] = processManager.ProcessManager() - environment['runtime']['ProcessManager'].initialize(environment) + environment["runtime"][ + "ProcessManager" + ] = processManager.ProcessManager() + environment["runtime"]["ProcessManager"].initialize(environment) - environment['runtime']['OutputManager'] = outputManager.OutputManager() - environment['runtime']['OutputManager'].initialize(environment) + environment["runtime"]["OutputManager"] = outputManager.OutputManager() + environment["runtime"]["OutputManager"].initialize(environment) - environment['runtime']['ByteManager'] = byteManager.ByteManager() - environment['runtime']['ByteManager'].initialize(environment) + environment["runtime"]["ByteManager"] = byteManager.ByteManager() + environment["runtime"]["ByteManager"].initialize(environment) - environment['runtime']['InputManager'] = inputManager.InputManager() - environment['runtime']['InputManager'].initialize(environment) + environment["runtime"]["InputManager"] = inputManager.InputManager() + environment["runtime"]["InputManager"].initialize(environment) - environment['runtime']['ScreenManager'] = screenManager.ScreenManager() - environment['runtime']['ScreenManager'].initialize(environment) + environment["runtime"]["ScreenManager"] = screenManager.ScreenManager() + environment["runtime"]["ScreenManager"].initialize(environment) - environment['runtime']['CommandManager'] = commandManager.CommandManager() - environment['runtime']['CommandManager'].initialize(environment) + environment["runtime"][ + "CommandManager" + ] = commandManager.CommandManager() + environment["runtime"]["CommandManager"].initialize(environment) - environment['runtime']['HelpManager'] = helpManager.HelpManager() - environment['runtime']['HelpManager'].initialize(environment) + environment["runtime"]["HelpManager"] = helpManager.HelpManager() + environment["runtime"]["HelpManager"].initialize(environment) - environment['runtime']['RemoteManager'] = remoteManager.RemoteManager() - environment['runtime']['RemoteManager'].initialize(environment) + environment["runtime"]["RemoteManager"] = remoteManager.RemoteManager() + environment["runtime"]["RemoteManager"].initialize(environment) - if environment['runtime']['InputManager'].get_shortcut_type() == 'KEY': + if environment["runtime"]["InputManager"].get_shortcut_type() == "KEY": if not os.path.exists( - self.get_setting( - 'keyboard', - 'keyboardLayout')): + self.get_setting("keyboard", "keyboardLayout") + ): if os.path.exists( - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout')): + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + ): self.set_setting( - 'keyboard', - 'keyboardLayout', - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout')) - environment['runtime']['InputManager'].load_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) + "keyboard", + "keyboardLayout", + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout"), + ) + environment["runtime"]["InputManager"].load_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) if os.path.exists( - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout') + - '.conf'): + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + + ".conf" + ): self.set_setting( - 'keyboard', - 'keyboardLayout', - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout') + - '.conf') - environment['runtime']['InputManager'].load_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) + "keyboard", + "keyboardLayout", + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + + ".conf", + ) + environment["runtime"]["InputManager"].load_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) else: - environment['runtime']['InputManager'].load_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) - elif environment['runtime']['InputManager'].get_shortcut_type() == 'BYTE': + environment["runtime"]["InputManager"].load_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) + elif ( + environment["runtime"]["InputManager"].get_shortcut_type() + == "BYTE" + ): if not os.path.exists( - self.get_setting( - 'keyboard', - 'keyboardLayout')): + self.get_setting("keyboard", "keyboardLayout") + ): if os.path.exists( - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout')): + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + ): self.set_setting( - 'keyboard', - 'keyboardLayout', - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout')) - environment['runtime']['ByteManager'].load_byte_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) + "keyboard", + "keyboardLayout", + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout"), + ) + environment["runtime"]["ByteManager"].load_byte_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) if os.path.exists( - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout') + - '.conf'): + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + + ".conf" + ): self.set_setting( - 'keyboard', - 'keyboardLayout', - settings_root + - 'keyboard/' + - self.get_setting( - 'keyboard', - 'keyboardLayout') + - '.conf') - environment['runtime']['ByteManager'].load_byte_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) + "keyboard", + "keyboardLayout", + settings_root + + "keyboard/" + + self.get_setting("keyboard", "keyboardLayout") + + ".conf", + ) + environment["runtime"]["ByteManager"].load_byte_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) else: - environment['runtime']['ByteManager'].load_byte_shortcuts( - self.get_setting('keyboard', 'keyboardLayout')) + environment["runtime"]["ByteManager"].load_byte_shortcuts( + self.get_setting("keyboard", "keyboardLayout") + ) - environment['runtime']['CursorManager'] = cursorManager.CursorManager() - environment['runtime']['CursorManager'].initialize(environment) - environment['runtime']['ApplicationManager'] = applicationManager.ApplicationManager() - environment['runtime']['ApplicationManager'].initialize(environment) - environment['runtime']['TextManager'] = textManager.TextManager() - environment['runtime']['TextManager'].initialize(environment) - environment['runtime']['TableManager'] = tableManager.TableManager() - environment['runtime']['TableManager'].initialize(environment) - environment['runtime']['BarrierManager'] = barrierManager.BarrierManager() - environment['runtime']['BarrierManager'].initialize(environment) - environment['runtime']['SayAllManager'] = sayAllManager.SayAllManager() - environment['runtime']['SayAllManager'].initialize(environment) - environment['runtime']['VmenuManager'] = vmenuManager.VmenuManager() - environment['runtime']['VmenuManager'].initialize(environment) - environment['runtime']['QuickMenuManager'] = quickMenuManager.QuickMenuManager() - environment['runtime']['QuickMenuManager'].initialize(environment) + environment["runtime"]["CursorManager"] = cursorManager.CursorManager() + environment["runtime"]["CursorManager"].initialize(environment) + environment["runtime"][ + "ApplicationManager" + ] = applicationManager.ApplicationManager() + environment["runtime"]["ApplicationManager"].initialize(environment) + environment["runtime"]["TextManager"] = textManager.TextManager() + environment["runtime"]["TextManager"].initialize(environment) + environment["runtime"]["TableManager"] = tableManager.TableManager() + environment["runtime"]["TableManager"].initialize(environment) + environment["runtime"][ + "BarrierManager" + ] = barrierManager.BarrierManager() + environment["runtime"]["BarrierManager"].initialize(environment) + environment["runtime"]["SayAllManager"] = sayAllManager.SayAllManager() + environment["runtime"]["SayAllManager"].initialize(environment) + environment["runtime"]["VmenuManager"] = vmenuManager.VmenuManager() + environment["runtime"]["VmenuManager"].initialize(environment) + environment["runtime"][ + "QuickMenuManager" + ] = quickMenuManager.QuickMenuManager() + environment["runtime"]["QuickMenuManager"].initialize(environment) # only possible after having input and screen managers with clean # buffer - environment['runtime']['InputManager'].write_event_buffer() - environment['runtime']['InputManager'].handle_device_grab(force=True) + environment["runtime"]["InputManager"].write_event_buffer() + environment["runtime"]["InputManager"].handle_device_grab(force=True) - environment['runtime']['DebugManager'].write_debug_out( - r'/-------environment-------/', debug.DebugLevel.INFO, on_any_level=True) - environment['runtime']['DebugManager'].write_debug_out( - str(environment), debug.DebugLevel.INFO, on_any_level=True) - environment['runtime']['DebugManager'].write_debug_out( - r'/-------settings.conf-------/', debug.DebugLevel.INFO, on_any_level=True) - environment['runtime']['DebugManager'].write_debug_out( - str(environment['settings']._sections), debug.DebugLevel.INFO, on_any_level=True) - environment['runtime']['DebugManager'].write_debug_out( - r'/-------self.settingArgDict-------/', + environment["runtime"]["DebugManager"].write_debug_out( + r"/-------environment-------/", debug.DebugLevel.INFO, - on_any_level=True) - environment['runtime']['DebugManager'].write_debug_out( - str(self.settingArgDict), debug.DebugLevel.INFO, on_any_level=True) - self.bindingsBackup = environment['bindings'].copy() + on_any_level=True, + ) + environment["runtime"]["DebugManager"].write_debug_out( + str(environment), debug.DebugLevel.INFO, on_any_level=True + ) + environment["runtime"]["DebugManager"].write_debug_out( + r"/-------settings.conf-------/", + debug.DebugLevel.INFO, + on_any_level=True, + ) + environment["runtime"]["DebugManager"].write_debug_out( + str(environment["settings"]._sections), + debug.DebugLevel.INFO, + on_any_level=True, + ) + environment["runtime"]["DebugManager"].write_debug_out( + r"/-------self.settingArgDict-------/", + debug.DebugLevel.INFO, + on_any_level=True, + ) + environment["runtime"]["DebugManager"].write_debug_out( + str(self.settingArgDict), debug.DebugLevel.INFO, on_any_level=True + ) + self.bindingsBackup = environment["bindings"].copy() return environment diff --git a/src/fenrirscreenreader/core/soundDriver.py b/src/fenrirscreenreader/core/soundDriver.py index a88ce81c..fb0c2036 100644 --- a/src/fenrirscreenreader/core/soundDriver.py +++ b/src/fenrirscreenreader/core/soundDriver.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class sound_driver(): +class sound_driver: def __init__(self): self.volume = None self._initialized = False @@ -23,11 +23,8 @@ class sound_driver(): self._is_initialized = False def play_frequence( - self, - frequence, - duration, - adjust_volume=0.0, - interrupt=True): + self, frequence, duration, adjust_volume=0.0, interrupt=True + ): if not self._initialized: return if interrupt: diff --git a/src/fenrirscreenreader/core/speechDriver.py b/src/fenrirscreenreader/core/speechDriver.py index 9c54d04c..0ceba522 100644 --- a/src/fenrirscreenreader/core/speechDriver.py +++ b/src/fenrirscreenreader/core/speechDriver.py @@ -2,12 +2,12 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug -class speech_driver(): +class speech_driver: def __init__(self): pass @@ -50,7 +50,7 @@ class speech_driver(): def set_voice(self, voice): if not self._is_initialized: return - if voice == '': + if voice == "": return self.voice = voice @@ -81,7 +81,7 @@ class speech_driver(): return if not isinstance(module, str): return - if module == '': + if module == "": return self.module = module @@ -94,7 +94,7 @@ class speech_driver(): return if not isinstance(language, str): return - if language == '': + if language == "": return self.language = language diff --git a/src/fenrirscreenreader/core/tableManager.py b/src/fenrirscreenreader/core/tableManager.py index adde6e38..5e17c1a6 100644 --- a/src/fenrirscreenreader/core/tableManager.py +++ b/src/fenrirscreenreader/core/tableManager.py @@ -2,19 +2,20 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import re +from fenrirscreenreader.core import debug -class TableManager(): + +class TableManager: def __init__(self): - self.headLine = '' - self.defaultSeparators = ['+', ';', '|', ' '] + self.headLine = "" + self.defaultSeparators = ["+", ";", "|", " "] self.noOfHeadLineColumns = 0 - self.headColumnSep = '' - self.rowColumnSep = '' + self.headColumnSep = "" + self.rowColumnSep = "" def initialize(self, environment): self.env = environment @@ -25,9 +26,9 @@ class TableManager(): def reset_table_mode(self): self.set_head_line() - def set_head_column_sep(self, columnSep=''): + def set_head_column_sep(self, columnSep=""): self.headColumnSep = columnSep - if columnSep == '': + if columnSep == "": self.noOfHeadLineColumns = 0 else: self.coun_no_of_head_columns() @@ -36,18 +37,18 @@ class TableManager(): pass def search_for_head_column_sep(self, headLine): - if ' ' in headLine: - return ' ' - return '' + if " " in headLine: + return " " + return "" - def set_row_column_sep(self, columnSep=''): + def set_row_column_sep(self, columnSep=""): self.rowColumnSep = columnSep - def set_head_line(self, headLine=''): + def set_head_line(self, headLine=""): self.set_head_column_sep() self.set_row_column_sep() - if headLine != '': + if headLine != "": sep = self.search_for_head_column_sep(headLine) - if sep != '': + if sep != "": self.headLine = headLine self.set_head_column_sep(sep) diff --git a/src/fenrirscreenreader/core/textManager.py b/src/fenrirscreenreader/core/textManager.py index 8ed52c91..a80f781c 100644 --- a/src/fenrirscreenreader/core/textManager.py +++ b/src/fenrirscreenreader/core/textManager.py @@ -2,18 +2,19 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug import re import string +from fenrirscreenreader.core import debug -class TextManager(): + +class TextManager: def __init__(self): # https://regex101.com/ - self.regExSingle = re.compile(r'(([^\w\s])\2{5,})') - self.regExDouble = re.compile(r'([^\w\s]{2,}){5,}') + self.regExSingle = re.compile(r"(([^\w\s])\2{5,})") + self.regExDouble = re.compile(r"([^\w\s]{2,}){5,}") def initialize(self, environment): self.env = environment @@ -26,52 +27,93 @@ class TextManager(): if len(text) < 5: return text # more strong check, to not match if not needed: - if len( - text.strip( - string.ascii_letters + - string.digits + - string.whitespace)) < 5: + if ( + len( + text.strip( + string.ascii_letters + string.digits + string.whitespace + ) + ) + < 5 + ): return text - result = '' - new_text = '' + result = "" + new_text = "" last_pos = 0 for match in self.regExDouble.finditer(text): span = match.span() - new_text += text[last_pos:span[0]] - number_of_chars = len(text[span[0]:span[1]]) - name = text[span[0]:span[1]][:2] - if not self.env['runtime']['PunctuationManager'].is_puctuation( - name[0]): + new_text += text[last_pos : span[0]] + number_of_chars = len(text[span[0] : span[1]]) + name = text[span[0] : span[1]][:2] + if not self.env["runtime"]["PunctuationManager"].is_puctuation( + name[0] + ): last_pos = span[1] continue if name[0] == name[1]: - new_text += ' ' + \ - str(number_of_chars) + ' ' + self.env['runtime']['PunctuationManager'].proceed_punctuation(name[0], True) + ' ' + new_text += ( + " " + + str(number_of_chars) + + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[0], True) + + " " + ) else: - new_text += ' ' + self.env['runtime']['PunctuationManager'].proceed_punctuation(name[0], True) + ' ' + str(int( - number_of_chars / 2)) + ' ' + self.env['runtime']['PunctuationManager'].proceed_punctuation(name[1], True) + ' ' + new_text += ( + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[0], True) + + " " + + str(int(number_of_chars / 2)) + + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[1], True) + + " " + ) last_pos = span[1] if last_pos != 0: - new_text += ' ' + new_text += " " new_text += text[last_pos:] last_pos = 0 for match in self.regExSingle.finditer(new_text): span = match.span() - result += new_text[last_pos:span[0]] - number_of_chars = len(new_text[span[0]:span[1]]) - name = new_text[span[0]:span[1]][:2] - if not self.env['runtime']['PunctuationManager'].is_puctuation( - name[0]): + result += new_text[last_pos : span[0]] + number_of_chars = len(new_text[span[0] : span[1]]) + name = new_text[span[0] : span[1]][:2] + if not self.env["runtime"]["PunctuationManager"].is_puctuation( + name[0] + ): last_pos = span[1] continue if name[0] == name[1]: - result += ' ' + str(number_of_chars) + ' ' + \ - self.env['runtime']['PunctuationManager'].proceed_punctuation(name[0], True) + ' ' + result += ( + " " + + str(number_of_chars) + + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[0], True) + + " " + ) else: - result += ' ' + self.env['runtime']['PunctuationManager'].proceed_punctuation(name[0], True) + ' ' + str(int( - number_of_chars / 2)) + ' ' + self.env['runtime']['PunctuationManager'].proceed_punctuation(name[1], True) + ' ' + result += ( + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[0], True) + + " " + + str(int(number_of_chars / 2)) + + " " + + self.env["runtime"][ + "PunctuationManager" + ].proceed_punctuation(name[1], True) + + " " + ) last_pos = span[1] if last_pos != 0: - result += ' ' + result += " " result += new_text[last_pos:] return result diff --git a/src/fenrirscreenreader/core/vmenuManager.py b/src/fenrirscreenreader/core/vmenuManager.py index 047856a9..5b558e19 100755 --- a/src/fenrirscreenreader/core/vmenuManager.py +++ b/src/fenrirscreenreader/core/vmenuManager.py @@ -2,47 +2,56 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import inspect +import os +import time from fenrirscreenreader.core import debug from fenrirscreenreader.core.i18n import _ from fenrirscreenreader.utils import module_utils -import os -import inspect -import time currentdir = os.path.dirname( - os.path.realpath( - os.path.abspath( - inspect.getfile( - inspect.currentframe())))) + os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))) +) fenrir_path = os.path.dirname(currentdir) -class VmenuManager(): +class VmenuManager: def __init__(self): self.menuDict = {} self.curr_index = None - self.currMenu = '' + self.currMenu = "" self.active = False self.reset = True self.useTimeout = True - self.searchText = '' + self.searchText = "" self.lastSearchTime = time.time() def initialize(self, environment): self.env = environment # use default path - self.defaultVMenuPath = fenrir_path + "/commands/vmenu-profiles/" + \ - self.env['runtime']['InputManager'].get_shortcut_type() + self.defaultVMenuPath = ( + fenrir_path + + "/commands/vmenu-profiles/" + + self.env["runtime"]["InputManager"].get_shortcut_type() + ) # if there is no user configuration - if self.env['runtime']['SettingsManager'].get_setting( - 'menu', 'vmenuPath') != '': - self.defaultVMenuPath = self.env['runtime']['SettingsManager'].get_setting( - 'menu', 'vmenuPath') - if not self.defaultVMenuPath.endswith('/'): - self.defaultVMenuPath += '/' - self.defaultVMenuPath += self.env['runtime']['InputManager'].get_shortcut_type() + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "menu", "vmenuPath" + ) + != "" + ): + self.defaultVMenuPath = self.env["runtime"][ + "SettingsManager" + ].get_setting("menu", "vmenuPath") + if not self.defaultVMenuPath.endswith("/"): + self.defaultVMenuPath += "/" + self.defaultVMenuPath += self.env["runtime"][ + "InputManager" + ].get_shortcut_type() self.create_menu_tree() self.closeAfterAction = False @@ -51,11 +60,11 @@ class VmenuManager(): pass def clear_search_text(self): - self.searchText = '' + self.searchText = "" def search_entry(self, value, forceReset=False): if self.curr_index is None: - return '' + return "" if self.reset or forceReset: self.clear_search_text() else: @@ -67,31 +76,31 @@ class VmenuManager(): start_index = self.get_curr_index() while True: if not self.next_index(): - return '' + return "" entry = self.get_current_entry() if entry.upper().startswith(self.searchText): return entry if start_index == self.get_curr_index(): - return '' + return "" - def set_curr_menu(self, currMenu=''): + def set_curr_menu(self, currMenu=""): self.curr_index = None - self.currMenu = '' - if currMenu != '': - currMenu += ' ' + _('Menu') + self.currMenu = "" + if currMenu != "": + currMenu += " " + _("Menu") try: t = self.menuDict[currMenu] l = list(self.menuDict.keys()) self.curr_index = [l.index(currMenu)] except Exception as e: print(e) - self.currMenu = '' + self.currMenu = "" self.curr_index = None return if self.inc_level(): self.currMenu = currMenu else: - self.currMenu = '' + self.currMenu = "" self.curr_index = None def get_curr_menu(self): @@ -104,7 +113,7 @@ class VmenuManager(): self.set_active(not self.get_active(), closeAfterAction) def set_active(self, active, closeAfterAction=True): - if self.env['runtime']['HelpManager'].is_tutorial_mode(): + if self.env["runtime"]["HelpManager"].is_tutorial_mode(): return self.active = active if self.active: @@ -114,7 +123,7 @@ class VmenuManager(): except Exception as e: print(e) try: - if self.currMenu != '': + if self.currMenu != "": self.set_curr_menu(self.currMenu) if self.curr_index is None: if len(self.menuDict) > 0: @@ -123,62 +132,73 @@ class VmenuManager(): print(e) try: # navigation - self.env['bindings'][str( - [1, ['KEY_ESC']])] = 'TOGGLE_VMENU_MODE' - self.env['bindings'][str([1, ['KEY_UP']])] = 'PREV_VMENU_ENTRY' - self.env['bindings'][str( - [1, ['KEY_DOWN']])] = 'NEXT_VMENU_ENTRY' - self.env['bindings'][str( - [1, ['KEY_SPACE']])] = 'CURR_VMENU_ENTRY' - self.env['bindings'][str( - [1, ['KEY_LEFT']])] = 'DEC_LEVEL_VMENU' - self.env['bindings'][str( - [1, ['KEY_RIGHT']])] = 'INC_LEVEL_VMENU' - self.env['bindings'][str( - [1, ['KEY_ENTER']])] = 'EXEC_VMENU_ENTRY' + self.env["bindings"][ + str([1, ["KEY_ESC"]]) + ] = "TOGGLE_VMENU_MODE" + self.env["bindings"][str([1, ["KEY_UP"]])] = "PREV_VMENU_ENTRY" + self.env["bindings"][ + str([1, ["KEY_DOWN"]]) + ] = "NEXT_VMENU_ENTRY" + self.env["bindings"][ + str([1, ["KEY_SPACE"]]) + ] = "CURR_VMENU_ENTRY" + self.env["bindings"][ + str([1, ["KEY_LEFT"]]) + ] = "DEC_LEVEL_VMENU" + self.env["bindings"][ + str([1, ["KEY_RIGHT"]]) + ] = "INC_LEVEL_VMENU" + self.env["bindings"][ + str([1, ["KEY_ENTER"]]) + ] = "EXEC_VMENU_ENTRY" # search - self.env['bindings'][str([1, ['KEY_A']])] = 'SEARCH_A' - self.env['bindings'][str([1, ['KEY_B']])] = 'SEARCH_B' - self.env['bindings'][str([1, ['KEY_C']])] = 'SEARCH_C' - self.env['bindings'][str([1, ['KEY_D']])] = 'SEARCH_D' - self.env['bindings'][str([1, ['KEY_E']])] = 'SEARCH_E' - self.env['bindings'][str([1, ['KEY_F']])] = 'SEARCH_F' - self.env['bindings'][str([1, ['KEY_G']])] = 'SEARCH_G' - self.env['bindings'][str([1, ['KEY_H']])] = 'SEARCH_H' - self.env['bindings'][str([1, ['KEY_I']])] = 'SEARCH_I' - self.env['bindings'][str([1, ['KEY_J']])] = 'SEARCH_J' - self.env['bindings'][str([1, ['KEY_K']])] = 'SEARCH_K' - self.env['bindings'][str([1, ['KEY_L']])] = 'SEARCH_L' - self.env['bindings'][str([1, ['KEY_M']])] = 'SEARCH_M' - self.env['bindings'][str([1, ['KEY_N']])] = 'SEARCH_N' - self.env['bindings'][str([1, ['KEY_O']])] = 'SEARCH_O' - self.env['bindings'][str([1, ['KEY_P']])] = 'SEARCH_P' - self.env['bindings'][str([1, ['KEY_Q']])] = 'SEARCH_Q' - self.env['bindings'][str([1, ['KEY_R']])] = 'SEARCH_R' - self.env['bindings'][str([1, ['KEY_S']])] = 'SEARCH_S' - self.env['bindings'][str([1, ['KEY_T']])] = 'SEARCH_T' - self.env['bindings'][str([1, ['KEY_U']])] = 'SEARCH_U' - self.env['bindings'][str([1, ['KEY_V']])] = 'SEARCH_V' - self.env['bindings'][str([1, ['KEY_W']])] = 'SEARCH_W' - self.env['bindings'][str([1, ['KEY_X']])] = 'SEARCH_X' - self.env['bindings'][str([1, ['KEY_Y']])] = 'SEARCH_Y' - self.env['bindings'][str([1, ['KEY_Z']])] = 'SEARCH_Z' + self.env["bindings"][str([1, ["KEY_A"]])] = "SEARCH_A" + self.env["bindings"][str([1, ["KEY_B"]])] = "SEARCH_B" + self.env["bindings"][str([1, ["KEY_C"]])] = "SEARCH_C" + self.env["bindings"][str([1, ["KEY_D"]])] = "SEARCH_D" + self.env["bindings"][str([1, ["KEY_E"]])] = "SEARCH_E" + self.env["bindings"][str([1, ["KEY_F"]])] = "SEARCH_F" + self.env["bindings"][str([1, ["KEY_G"]])] = "SEARCH_G" + self.env["bindings"][str([1, ["KEY_H"]])] = "SEARCH_H" + self.env["bindings"][str([1, ["KEY_I"]])] = "SEARCH_I" + self.env["bindings"][str([1, ["KEY_J"]])] = "SEARCH_J" + self.env["bindings"][str([1, ["KEY_K"]])] = "SEARCH_K" + self.env["bindings"][str([1, ["KEY_L"]])] = "SEARCH_L" + self.env["bindings"][str([1, ["KEY_M"]])] = "SEARCH_M" + self.env["bindings"][str([1, ["KEY_N"]])] = "SEARCH_N" + self.env["bindings"][str([1, ["KEY_O"]])] = "SEARCH_O" + self.env["bindings"][str([1, ["KEY_P"]])] = "SEARCH_P" + self.env["bindings"][str([1, ["KEY_Q"]])] = "SEARCH_Q" + self.env["bindings"][str([1, ["KEY_R"]])] = "SEARCH_R" + self.env["bindings"][str([1, ["KEY_S"]])] = "SEARCH_S" + self.env["bindings"][str([1, ["KEY_T"]])] = "SEARCH_T" + self.env["bindings"][str([1, ["KEY_U"]])] = "SEARCH_U" + self.env["bindings"][str([1, ["KEY_V"]])] = "SEARCH_V" + self.env["bindings"][str([1, ["KEY_W"]])] = "SEARCH_W" + self.env["bindings"][str([1, ["KEY_X"]])] = "SEARCH_X" + self.env["bindings"][str([1, ["KEY_Y"]])] = "SEARCH_Y" + self.env["bindings"][str([1, ["KEY_Z"]])] = "SEARCH_Z" # page navigation - self.env['bindings'][str( - [1, ['KEY_PAGEUP']])] = 'PAGE_UP_VMENU' - self.env['bindings'][str( - [1, ['KEY_PAGEDOWN']])] = 'PAGE_DOWN_VMENU' + self.env["bindings"][ + str([1, ["KEY_PAGEUP"]]) + ] = "PAGE_UP_VMENU" + self.env["bindings"][ + str([1, ["KEY_PAGEDOWN"]]) + ] = "PAGE_DOWN_VMENU" except Exception as e: print(e) else: try: self.curr_index = None - self.env['bindings'] = self.env['runtime']['SettingsManager'].get_binding_backup( - ) + self.env["bindings"] = self.env["runtime"][ + "SettingsManager" + ].get_binding_backup() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VmenuManager set_active: Error loading binding backup: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VmenuManager set_active: Error loading binding backup: " + + str(e), + debug.DebugLevel.ERROR, + ) def create_menu_tree(self, resetIndex=True): if resetIndex: @@ -189,7 +209,10 @@ class VmenuManager(): # Add dynamic voice menus try: - from fenrirscreenreader.core.dynamicVoiceMenu import add_dynamic_voice_menus + from fenrirscreenreader.core.dynamicVoiceMenu import ( + add_dynamic_voice_menus, + ) + add_dynamic_voice_menus(self) except Exception as e: print(f"Error adding dynamic voice menus: {e}") @@ -201,9 +224,11 @@ class VmenuManager(): if r == {}: self.curr_index = None except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VmenuManager create_menu_tree: Error checking menu index validity: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VmenuManager create_menu_tree: Error checking menu index validity: " + + str(e), + debug.DebugLevel.ERROR, + ) self.curr_index = None def execute_menu(self): @@ -219,12 +244,15 @@ class VmenuManager(): try: self.inc_level() text = self.get_current_entry() - self.env['runtime']['OutputManager'].present_text( - text, interrupt=True) + self.env["runtime"]["OutputManager"].present_text( + text, interrupt=True + ) except Exception as ex: - self.env['runtime']['DebugManager'].write_debug_out( - 'VmenuManager execute_menu: Error presenting menu text: ' + str(ex), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VmenuManager execute_menu: Error presenting menu text: " + + str(ex), + debug.DebugLevel.ERROR, + ) def inc_level(self): if self.curr_index is None: @@ -234,9 +262,10 @@ class VmenuManager(): if r == {}: return False except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VmenuManager inc_level: Error accessing menu path: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VmenuManager inc_level: Error accessing menu path: " + str(e), + debug.DebugLevel.ERROR, + ) return False self.curr_index.append(0) return True @@ -244,19 +273,20 @@ class VmenuManager(): def dec_level(self): if self.curr_index is None: return False - if self.currMenu != '': + if self.currMenu != "": if len(self.curr_index) <= 2: return False elif len(self.curr_index) == 1: return False - self.curr_index = self.curr_index[:len(self.curr_index) - 1] + self.curr_index = self.curr_index[: len(self.curr_index) - 1] return True def next_index(self): if self.curr_index is None: return False if self.curr_index[len(self.curr_index) - 1] + 1 >= len( - self.get_nested_by_path(self.menuDict, self.curr_index[:-1])): + self.get_nested_by_path(self.menuDict, self.curr_index[:-1]) + ): self.curr_index[len(self.curr_index) - 1] = 0 else: self.curr_index[len(self.curr_index) - 1] += 1 @@ -271,8 +301,14 @@ class VmenuManager(): if self.curr_index is None: return False if self.curr_index[len(self.curr_index) - 1] == 0: - self.curr_index[len(self.curr_index) - 1] = len( - self.get_nested_by_path(self.menuDict, self.curr_index[:-1])) - 1 + self.curr_index[len(self.curr_index) - 1] = ( + len( + self.get_nested_by_path( + self.menuDict, self.curr_index[:-1] + ) + ) + - 1 + ) else: self.curr_index[len(self.curr_index) - 1] -= 1 return True @@ -280,8 +316,9 @@ class VmenuManager(): def page_up(self): if self.curr_index is None: return False - menu_size = len(self.get_nested_by_path( - self.menuDict, self.curr_index[:-1])) + menu_size = len( + self.get_nested_by_path(self.menuDict, self.curr_index[:-1]) + ) if menu_size <= 1: return False jump_size = max(1, int(menu_size * 0.1)) # 10% of menu size, minimum 1 @@ -294,8 +331,9 @@ class VmenuManager(): def page_down(self): if self.curr_index is None: return False - menu_size = len(self.get_nested_by_path( - self.menuDict, self.curr_index[:-1])) + menu_size = len( + self.get_nested_by_path(self.menuDict, self.curr_index[:-1]) + ) if menu_size <= 1: return False jump_size = max(1, int(menu_size * 0.1)) # 10% of menu size, minimum 1 @@ -307,29 +345,31 @@ class VmenuManager(): def get_current_entry(self): return self.get_keys_by_path(self.menuDict, self.curr_index)[ - self.curr_index[-1]] + self.curr_index[-1] + ] def fs_tree_to_dict(self, path_): for root, dirs, files in os.walk(path_): tree = { - d + - ' ' + - _('Menu'): self.fs_tree_to_dict( - os.path.join( - root, - d)) for d in dirs if not d.startswith('__')} + d + + " " + + _("Menu"): self.fs_tree_to_dict(os.path.join(root, d)) + for d in dirs + if not d.startswith("__") + } for f in files: try: file_name, file_extension = os.path.splitext(f) - file_name = file_name.split('/')[-1] - if file_name.startswith('__'): + file_name = file_name.split("/")[-1] + if file_name.startswith("__"): continue # Skip base classes that shouldn't be loaded as commands - if file_name.endswith('_base'): + if file_name.endswith("_base"): continue - command = self.env['runtime']['CommandManager'].load_file( - root + '/' + f) - tree.update({file_name + ' ' + _('Action'): command}) + command = self.env["runtime"]["CommandManager"].load_file( + root + "/" + f + ) + tree.update({file_name + " " + _("Action"): command}) except Exception as e: print(e) return tree # note we discontinue iteration trough os.walk diff --git a/src/fenrirscreenreader/fenrirVersion.py b/src/fenrirscreenreader/fenrirVersion.py index d17ef149..4e13bfe4 100644 --- a/src/fenrirscreenreader/fenrirVersion.py +++ b/src/fenrirscreenreader/fenrirVersion.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. version = "2025.07.05" codeName = "testing" diff --git a/src/fenrirscreenreader/inputDriver/debugDriver.py b/src/fenrirscreenreader/inputDriver/debugDriver.py index 91143d67..dfb33cc8 100644 --- a/src/fenrirscreenreader/inputDriver/debugDriver.py +++ b/src/fenrirscreenreader/inputDriver/debugDriver.py @@ -2,9 +2,10 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver @@ -15,38 +16,38 @@ class driver(inputDriver): def initialize(self, environment): self.env = environment - self.env['runtime']['InputManager'].set_shortcut_type('KEY') + self.env["runtime"]["InputManager"].set_shortcut_type("KEY") self._initialized = True - print('Input Debug Driver: Initialized') + print("Input Debug Driver: Initialized") def shutdown(self): if self._initialized: self.remove_all_devices() self._initialized = False - print('Input Debug Driver: Shutdown') + print("Input Debug Driver: Shutdown") def get_input_event(self): time.sleep(0.1) if not self._initialized: return None - print('Input Debug Driver: get_input_event') + print("Input Debug Driver: get_input_event") return None def write_event_buffer(self): if not self._initialized: return - print('Input Debug Driver: write_event_buffer') + print("Input Debug Driver: write_event_buffer") def clear_event_buffer(self): if not self._initialized: return - del self.env['input']['eventBuffer'][:] - print('Input Debug Driver: clear_event_buffer') + del self.env["input"]["eventBuffer"][:] + print("Input Debug Driver: clear_event_buffer") def update_input_devices(self, new_devices=None, init=False): if not self._initialized: return - print('Input Debug Driver: update_input_devices') + print("Input Debug Driver: update_input_devices") def get_led_state(self, led=0): if not self._initialized: @@ -56,24 +57,24 @@ class driver(inputDriver): def toggle_led_state(self, led=0): if not self._initialized: return - print('Input Debug Driver: toggle_led_state') + print("Input Debug Driver: toggle_led_state") def grab_all_devices(self): if not self._initialized: return - print('Input Debug Driver: grab_all_devices') + print("Input Debug Driver: grab_all_devices") def ungrab_all_devices(self): if not self._initialized: return - print('Input Debug Driver: ungrab_all_devices') + print("Input Debug Driver: ungrab_all_devices") def remove_all_devices(self): if not self._initialized: return - print('Input Debug Driver: remove_all_devices') + print("Input Debug Driver: remove_all_devices") def __del__(self): if self._initialized: self.remove_all_devices() - print('Input Debug Driver: __del__') + print("Input Debug Driver: __del__") diff --git a/src/fenrirscreenreader/inputDriver/dummyDriver.py b/src/fenrirscreenreader/inputDriver/dummyDriver.py index 22462243..22b1c652 100644 --- a/src/fenrirscreenreader/inputDriver/dummyDriver.py +++ b/src/fenrirscreenreader/inputDriver/dummyDriver.py @@ -2,9 +2,10 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver diff --git a/src/fenrirscreenreader/inputDriver/evdevDriver.py b/src/fenrirscreenreader/inputDriver/evdevDriver.py index 626655e6..69f6af64 100644 --- a/src/fenrirscreenreader/inputDriver/evdevDriver.py +++ b/src/fenrirscreenreader/inputDriver/evdevDriver.py @@ -1,23 +1,28 @@ # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import multiprocessing +import threading +import time +from ctypes import c_bool +from multiprocessing.sharedctypes import Value +from select import select -from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver from fenrirscreenreader.core import debug from fenrirscreenreader.core import inputData from fenrirscreenreader.core.eventData import FenrirEventType -import threading -from ctypes import c_bool -from multiprocessing.sharedctypes import Value -import multiprocessing -from select import select -import time +from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver + _evdevAvailable = False _udevAvailable = False -_evdevAvailableError = '' -_udevAvailableError = '' +_evdevAvailableError = "" +_udevAvailableError = "" try: import evdev - from evdev import InputDevice, UInput, ecodes as e + from evdev import InputDevice + from evdev import UInput + from evdev import ecodes as e + _evdevAvailable = True except Exception as e: @@ -25,12 +30,35 @@ except Exception as e: try: import pyudev + _udevAvailable = True except Exception as e: _udevAvailableError = str(e) class driver(inputDriver): + """Linux evdev input driver for Fenrir screen reader. + + This driver provides access to Linux input devices through the evdev interface, + allowing Fenrir to capture keyboard input, manage device grabbing for exclusive + access, and inject synthetic input events. + + Features: + - Automatic device detection and hotplug support via udev + - Device grabbing to prevent input from reaching other applications + - Key event mapping and filtering + - UInput support for synthetic key injection + - Multi-device support with thread-safe access + + Attributes: + iDevices (dict): Map of file descriptor to InputDevice objects + iDevicesFD (list): Shared list of file descriptors for multiprocessing + uDevices (dict): Map of file descriptor to UInput devices + gDevices (dict): Map of file descriptor to grab status + iDeviceNo (int): Total number of input devices + UInputinject (UInput): Device for injecting synthetic events + _deviceLock (Lock): Thread lock for device access + """ def __init__(self): inputDriver.__init__(self) self._manager = multiprocessing.Manager() @@ -44,72 +72,121 @@ class driver(inputDriver): self._deviceLock = threading.Lock() def initialize(self, environment): + """Initialize the evdev input driver. + + Sets up device monitoring, starts watchdog threads for device hotplug + detection and input monitoring, and configures the input subsystem. + + Args: + environment: Fenrir environment dictionary with runtime managers + + Note: + Requires evdev and optionally pyudev libraries. Falls back gracefully + if libraries are not available. + """ self.env = environment - self.env['runtime']['InputManager'].set_shortcut_type('KEY') + self.env["runtime"]["InputManager"].set_shortcut_type("KEY") global _evdevAvailable global _udevAvailable global _evdevAvailableError global _udevAvailableError if not _udevAvailable: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver:' + _udevAvailableError, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver:" + _udevAvailableError, debug.DebugLevel.ERROR + ) if not _evdevAvailable: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver:' + _evdevAvailableError, debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver:" + _evdevAvailableError, debug.DebugLevel.ERROR + ) return if _udevAvailable: - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.plug_input_device_watchdog_udev) - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.input_watchdog) + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.plug_input_device_watchdog_udev + ) + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.input_watchdog + ) self._initialized = True def plug_input_device_watchdog_udev(self, active, event_queue): + """Monitor for input device hotplug events via udev. + + Runs in a separate thread to detect when input devices are + plugged/unplugged and generates appropriate events for device + management. + + Args: + active: Shared boolean controlling the watchdog loop + event_queue: Queue for sending device events to main process + + Events Generated: + FenrirEventType.plug_input_device: When new devices are detected + + Note: + Filters out virtual devices and devices from assistive technologies + like BRLTTY to avoid conflicts. + """ context = pyudev.Context() monitor = pyudev.Monitor.from_netlink(context) - monitor.filter_by(subsystem='input') + monitor.filter_by(subsystem="input") monitor.start() ignore_plug = False while active.value: valid_devices = [] device = monitor.poll(1) while device: - self.env['runtime']['DebugManager'].write_debug_out( - 'plug_input_device_watchdog_udev:' + str(device), debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "plug_input_device_watchdog_udev:" + str(device), + debug.DebugLevel.INFO, + ) try: try: # FIX: Check if attributes exist before accessing them - if hasattr( - device, - 'name') and device.name and device.name.upper() in [ - '', - 'SPEAKUP', - 'FENRIR-UINPUT']: + if ( + hasattr(device, "name") + and device.name + and device.name.upper() + in ["", "SPEAKUP", "FENRIR-UINPUT"] + ): ignore_plug = True - if hasattr( - device, - 'phys') and device.phys and device.phys.upper() in [ - '', - 'SPEAKUP', - 'FENRIR-UINPUT']: + if ( + hasattr(device, "phys") + and device.phys + and device.phys.upper() + in ["", "SPEAKUP", "FENRIR-UINPUT"] + ): ignore_plug = True - if hasattr( - device, - 'name') and device.name and 'BRLTTY' in device.name.upper(): + if ( + hasattr(device, "name") + and device.name + and "BRLTTY" in device.name.upper() + ): ignore_plug = True except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "plug_input_device_watchdog_udev CHECK NAME CRASH: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "plug_input_device_watchdog_udev CHECK NAME CRASH: " + + str(e), + debug.DebugLevel.ERROR, + ) if not ignore_plug: - virtual = '/sys/devices/virtual/input/' in device.sys_path + virtual = ( + "/sys/devices/virtual/input/" in device.sys_path + ) if device.device_node: valid_devices.append( - {'device': device.device_node, 'virtual': virtual}) + { + "device": device.device_node, + "virtual": virtual, + } + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "plug_input_device_watchdog_udev APPEND CRASH: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "plug_input_device_watchdog_udev APPEND CRASH: " + + str(e), + debug.DebugLevel.ERROR, + ) try: poll_timeout = 1 device = monitor.poll(poll_timeout) @@ -118,10 +195,31 @@ class driver(inputDriver): ignore_plug = False if valid_devices: event_queue.put( - {"Type": FenrirEventType.plug_input_device, "data": valid_devices}) + { + "Type": FenrirEventType.plug_input_device, + "data": valid_devices, + } + ) return time.time() def input_watchdog(self, active, event_queue): + """Main input monitoring loop. + + Monitors all registered input devices for key events using select(). + Processes key events, maps them to Fenrir's internal format, and + forwards them to the main application. + + Args: + active: Shared boolean controlling the watchdog loop + event_queue: Queue for sending input events to main process + + Events Generated: + FenrirEventType.keyboard_input: For key press/release events + + Note: + Uses thread-safe device access and handles device disconnection + gracefully. Non-keyboard events are forwarded to UInput devices. + """ try: while active.value: # Get a snapshot of devices for select() to avoid lock @@ -149,16 +247,21 @@ class driver(inputDriver): try: event = device.read_one() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver handle_input_event: Error reading event: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver handle_input_event: Error reading event: " + + str(e), + debug.DebugLevel.ERROR, + ) self.remove_device(fd) continue - while (event): - self.env['runtime']['DebugManager'].write_debug_out( - 'input_watchdog: EVENT:' + str(event), debug.DebugLevel.INFO) - self.env['input']['eventBuffer'].append( - [device, udevice, event]) + while event: + self.env["runtime"]["DebugManager"].write_debug_out( + "input_watchdog: EVENT:" + str(event), + debug.DebugLevel.INFO, + ) + self.env["input"]["eventBuffer"].append( + [device, udevice, event] + ) if event.type == evdev.events.EV_KEY: if not found_key_in_sequence: found_key_in_sequence = True @@ -168,12 +271,17 @@ class driver(inputDriver): event = device.read_one() continue if not isinstance( - curr_map_event['EventName'], str): + curr_map_event["EventName"], str + ): event = device.read_one() continue - if curr_map_event['EventState'] in [0, 1, 2]: + if curr_map_event["EventState"] in [0, 1, 2]: event_queue.put( - {"Type": FenrirEventType.keyboard_input, "data": curr_map_event.copy()}) + { + "Type": FenrirEventType.keyboard_input, + "data": curr_map_event.copy(), + } + ) event_fired = True else: if event.type in [2, 3]: @@ -185,21 +293,24 @@ class driver(inputDriver): self.write_event_buffer() self.clear_event_buffer() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - "INPUT WATCHDOG CRASH: " + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "INPUT WATCHDOG CRASH: " + str(e), debug.DebugLevel.ERROR + ) def write_event_buffer(self): if not self._initialized: return - for iDevice, uDevice, event in self.env['input']['eventBuffer']: + for iDevice, uDevice, event in self.env["input"]["eventBuffer"]: try: if uDevice: if self.gDevices[iDevice.fd]: self.write_u_input(uDevice, event) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver write_event_buffer: Error writing event: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver write_event_buffer: Error writing event: " + + str(e), + debug.DebugLevel.ERROR, + ) def write_u_input(self, uDevice, event): if not self._initialized: @@ -209,6 +320,25 @@ class driver(inputDriver): uDevice.syn() def update_input_devices(self, new_devices=None, init=False): + """Update the list of monitored input devices. + + Scans for available input devices and adds suitable ones based on + the configured device mode. Supports filtering by device type and + name matching. + + Args: + new_devices (list, optional): Specific devices to add + init (bool): Whether this is initial device setup + + Device Modes: + - 'ALL': Monitor all keyboard devices + - 'NOMICE': Monitor keyboards but exclude pointing devices + - Device names: Comma-separated list of specific device names + + Note: + Automatically filters out virtual devices, assistive technology + devices, and devices with insufficient key counts. + """ if init: self.remove_all_devices() @@ -225,8 +355,11 @@ class driver(inputDriver): if not device_file_list: return - mode = self.env['runtime']['SettingsManager'].get_setting( - 'keyboard', 'device').upper() + mode = ( + self.env["runtime"]["SettingsManager"] + .get_setting("keyboard", "device") + .upper() + ) i_devices_files = [] for device in self.iDevices: @@ -237,7 +370,7 @@ class driver(inputDriver): try: if not deviceFile: continue - if deviceFile == '': + if deviceFile == "": continue if deviceFile in i_devices_files: continue @@ -245,9 +378,11 @@ class driver(inputDriver): with open(deviceFile) as f: pass except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver update_input_devices: Error opening device file: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver update_input_devices: Error opening device file: " + + str(e), + debug.DebugLevel.ERROR, + ) continue # 3 pos absolute # 2 pos relative @@ -255,83 +390,129 @@ class driver(inputDriver): try: curr_device = evdev.InputDevice(deviceFile) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver createDeviceType: Error creating device: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver createDeviceType: Error creating device: " + + str(e), + debug.DebugLevel.ERROR, + ) continue try: # FIX: Check if attributes exist before accessing them - if hasattr( - curr_device, - 'name') and curr_device.name and curr_device.name.upper() in [ - '', - 'SPEAKUP', - 'FENRIR-UINPUT']: + if ( + hasattr(curr_device, "name") + and curr_device.name + and curr_device.name.upper() + in ["", "SPEAKUP", "FENRIR-UINPUT"] + ): continue - if hasattr( - curr_device, - 'phys') and curr_device.phys and curr_device.phys.upper() in [ - '', - 'SPEAKUP', - 'FENRIR-UINPUT']: + if ( + hasattr(curr_device, "phys") + and curr_device.phys + and curr_device.phys.upper() + in ["", "SPEAKUP", "FENRIR-UINPUT"] + ): continue - if hasattr( - curr_device, - 'name') and curr_device.name and 'BRLTTY' in curr_device.name.upper(): + if ( + hasattr(curr_device, "name") + and curr_device.name + and "BRLTTY" in curr_device.name.upper() + ): continue except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver: Error checking device capabilities: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver: Error checking device capabilities: " + + str(e), + debug.DebugLevel.ERROR, + ) cap = curr_device.capabilities() - if mode in ['ALL', 'NOMICE']: + if mode in ["ALL", "NOMICE"]: if event_type.EV_KEY in cap: - if 116 in cap[event_type.EV_KEY] and len( - cap[event_type.EV_KEY]) < 10: - self.env['runtime']['DebugManager'].write_debug_out( - 'Device Skipped (has 116):' + curr_device.name, debug.DebugLevel.INFO) + if ( + 116 in cap[event_type.EV_KEY] + and len(cap[event_type.EV_KEY]) < 10 + ): + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "Device Skipped (has 116):" + curr_device.name, + debug.DebugLevel.INFO, + ) continue if len(cap[event_type.EV_KEY]) < 60: - self.env['runtime']['DebugManager'].write_debug_out( - 'Device Skipped (< 60 keys):' + curr_device.name, debug.DebugLevel.INFO) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "Device Skipped (< 60 keys):" + + curr_device.name, + debug.DebugLevel.INFO, + ) continue - if mode == 'ALL': + if mode == "ALL": self.add_device(curr_device) - self.env['runtime']['DebugManager'].write_debug_out( - 'Device added (ALL):' + self.iDevices[curr_device.fd].name, debug.DebugLevel.INFO) - elif mode == 'NOMICE': + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "Device added (ALL):" + + self.iDevices[curr_device.fd].name, + debug.DebugLevel.INFO, + ) + elif mode == "NOMICE": if not ( - (event_type.EV_REL in cap) or ( - event_type.EV_ABS in cap)): + (event_type.EV_REL in cap) + or (event_type.EV_ABS in cap) + ): self.add_device(curr_device) - self.env['runtime']['DebugManager'].write_debug_out( - 'Device added (NOMICE):' + self.iDevices[curr_device.fd].name, debug.DebugLevel.INFO) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "Device added (NOMICE):" + + self.iDevices[curr_device.fd].name, + debug.DebugLevel.INFO, + ) else: - self.env['runtime']['DebugManager'].write_debug_out( - 'Device Skipped (NOMICE):' + curr_device.name, debug.DebugLevel.INFO) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "Device Skipped (NOMICE):" + + curr_device.name, + debug.DebugLevel.INFO, + ) else: - self.env['runtime']['DebugManager'].write_debug_out( - 'Device Skipped (no EV_KEY):' + curr_device.name, debug.DebugLevel.INFO) - elif curr_device.name.upper() in mode.split(','): + self.env["runtime"]["DebugManager"].write_debug_out( + "Device Skipped (no EV_KEY):" + curr_device.name, + debug.DebugLevel.INFO, + ) + elif curr_device.name.upper() in mode.split(","): self.add_device(curr_device) - self.env['runtime']['DebugManager'].write_debug_out( - 'Device added (Name):' + self.iDevices[curr_device.fd].name, debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "Device added (Name):" + + self.iDevices[curr_device.fd].name, + debug.DebugLevel.INFO, + ) except Exception as e: try: - device_name = curr_device.name if hasattr( - curr_device, 'name') else "unknown" - self.env['runtime']['DebugManager'].write_debug_out( - "Device Skipped (Exception): " + - deviceFile + - ' ' + - device_name + - ' ' + - str(e), - debug.DebugLevel.INFO) + device_name = ( + curr_device.name + if hasattr(curr_device, "name") + else "unknown" + ) + self.env["runtime"]["DebugManager"].write_debug_out( + "Device Skipped (Exception): " + + deviceFile + + " " + + device_name + + " " + + str(e), + debug.DebugLevel.INFO, + ) except Exception as ex: - self.env['runtime']['DebugManager'].write_debug_out( - "Device Skipped (Exception): " + deviceFile + ' ' + str(ex), - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "Device Skipped (Exception): " + + deviceFile + + " " + + str(ex), + debug.DebugLevel.INFO, + ) self.iDeviceNo = len(evdev.list_devices()) self.update_m_pi_devices_fd() @@ -344,10 +525,11 @@ class driver(inputDriver): if fd not in self.iDevices: self.iDevicesFD.remove(fd) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver update_m_pi_devices_fd: Error updating device file descriptors: ' + - str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver update_m_pi_devices_fd: Error updating device file descriptors: " + + str(e), + debug.DebugLevel.ERROR, + ) def map_event(self, event): if not self._initialized: @@ -357,18 +539,18 @@ class driver(inputDriver): m_event = inputData.input_event try: # mute is a list = ['KEY_MIN_INTERESTING', 'KEY_MUTE'] - m_event['EventName'] = evdev.ecodes.keys[event.code] - if isinstance(m_event['EventName'], list): - if len(m_event['EventName']) > 0: - m_event['EventName'] = m_event['EventName'][0] - if isinstance(m_event['EventName'], list): - if len(m_event['EventName']) > 0: - m_event['EventName'] = m_event['EventName'][0] - m_event['EventValue'] = event.code - m_event['EventSec'] = event.sec - m_event['EventUsec'] = event.usec - m_event['EventState'] = event.value - m_event['EventType'] = event.type + m_event["EventName"] = evdev.ecodes.keys[event.code] + if isinstance(m_event["EventName"], list): + if len(m_event["EventName"]) > 0: + m_event["EventName"] = m_event["EventName"][0] + if isinstance(m_event["EventName"], list): + if len(m_event["EventName"]) > 0: + m_event["EventName"] = m_event["EventName"][0] + m_event["EventValue"] = event.code + m_event["EventSec"] = event.sec + m_event["EventUsec"] = event.usec + m_event["EventState"] = event.value + m_event["EventType"] = event.type return m_event except Exception as e: return None @@ -416,8 +598,9 @@ class driver(inputDriver): return ok def create_u_input_dev(self, fd): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): self.uDevices[fd] = None return try: @@ -429,61 +612,102 @@ class driver(inputDriver): return try: self.uDevices[fd] = UInput.from_device( - self.iDevices[fd], name='fenrir-uinput', phys='fenrir-uinput') + self.iDevices[fd], name="fenrir-uinput", phys="fenrir-uinput" + ) except Exception as e: try: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: compat fallback: ' + str(e), debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: compat fallback: " + str(e), + debug.DebugLevel.WARNING, + ) dev = self.iDevices[fd] cap = dev.capabilities() del cap[0] self.uDevices[fd] = UInput( - cap, - name='fenrir-uinput', - phys='fenrir-uinput' + cap, name="fenrir-uinput", phys="fenrir-uinput" ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: init Uinput not possible: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: init Uinput not possible: " + str(e), + debug.DebugLevel.ERROR, + ) return def add_device(self, newDevice): - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: device added: ' + str( - newDevice.fd) + ' ' + str(newDevice), - debug.DebugLevel.INFO) + """Add a new input device to the monitoring list. + + Creates the necessary data structures for device monitoring, + sets up UInput forwarding if device grabbing is enabled, and + initializes device state. + + Args: + newDevice: evdev.InputDevice object to add + + Note: + Thread-safe operation. Automatically cleans up on failure. + """ + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: device added: " + + str(newDevice.fd) + + " " + + str(newDevice), + debug.DebugLevel.INFO, + ) with self._deviceLock: try: self.iDevices[newDevice.fd] = newDevice self.create_u_input_dev(newDevice.fd) self.gDevices[newDevice.fd] = False except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: error adding device: ' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: error adding device: " + str(e), + debug.DebugLevel.ERROR, + ) # if it doesnt work clean up try: - del (self.iDevices[newDevice.fd]) + del self.iDevices[newDevice.fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error removing iDevice: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error removing iDevice: " + + str(e), + debug.DebugLevel.ERROR, + ) try: - del (self.uDevices[newDevice.fd]) + del self.uDevices[newDevice.fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error removing uDevice: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error removing uDevice: " + + str(e), + debug.DebugLevel.ERROR, + ) try: - del (self.gDevices[newDevice.fd]) + del self.gDevices[newDevice.fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver add_device: Error cleaning up gDevice: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver add_device: Error cleaning up gDevice: " + + str(e), + debug.DebugLevel.ERROR, + ) def grab_device(self, fd): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + """Grab exclusive access to an input device. + + Takes exclusive control of the device, preventing other applications + from receiving its input. Also resets modifier key states to prevent + stuck keys. + + Args: + fd (int): File descriptor of device to grab + + Returns: + bool: True if grab successful, False otherwise + + Note: + Only effective if grabDevices setting is enabled. + """ + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): return True # FIX: Handle exception variable scope correctly @@ -491,8 +715,12 @@ class driver(inputDriver): try: self.iDevices[fd].grab() self.gDevices[fd] = True - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: grab device (' + str(self.iDevices[fd].name) + ')', debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: grab device (" + + str(self.iDevices[fd].name) + + ")", + debug.DebugLevel.INFO, + ) # Reset modifier keys on successful grab if self.uDevices[fd]: modifier_keys = [ @@ -501,14 +729,17 @@ class driver(inputDriver): e.KEY_LEFTALT, e.KEY_RIGHTALT, e.KEY_LEFTSHIFT, - e.KEY_RIGHTSHIFT] + e.KEY_RIGHTSHIFT, + ] for key in modifier_keys: try: self.uDevices[fd].write(e.EV_KEY, key, 0) # 0 = key up self.uDevices[fd].syn() except Exception as mod_error: - self.env['runtime']['DebugManager'].write_debug_out( - 'Failed to reset modifier key: ' + str(mod_error), debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "Failed to reset modifier key: " + str(mod_error), + debug.DebugLevel.WARNING, + ) except IOError: if not self.gDevices[fd]: return False @@ -516,17 +747,29 @@ class driver(inputDriver): grab_error = ex if grab_error: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: grabing not possible: ' + - str(grab_error), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: grabing not possible: " + str(grab_error), + debug.DebugLevel.ERROR, + ) return False return True def ungrab_device(self, fd): - if not self.env['runtime']['SettingsManager'].get_setting_as_bool( - 'keyboard', 'grabDevices'): + """Release exclusive access to an input device. + + Returns control of the device to the system, allowing other + applications to receive its input. + + Args: + fd (int): File descriptor of device to ungrab + + Returns: + bool: True if ungrab successful, False otherwise + """ + if not self.env["runtime"]["SettingsManager"].get_setting_as_bool( + "keyboard", "grabDevices" + ): return True # FIX: Handle exception variable scope correctly @@ -534,8 +777,12 @@ class driver(inputDriver): try: self.iDevices[fd].ungrab() self.gDevices[fd] = False - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: ungrab device (' + str(self.iDevices[fd].name) + ')', debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: ungrab device (" + + str(self.iDevices[fd].name) + + ")", + debug.DebugLevel.INFO, + ) except IOError: if self.gDevices[fd]: return False @@ -543,64 +790,105 @@ class driver(inputDriver): ungrab_error = ex if ungrab_error: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: ungrabing not possible: ' + - str(ungrab_error), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: ungrabing not possible: " + + str(ungrab_error), + debug.DebugLevel.ERROR, + ) return False return True def remove_device(self, fd): + """Remove an input device from monitoring. + + Cleanly removes a device by ungrabbing it, closing file handles, + and cleaning up all associated data structures. + + Args: + fd (int): File descriptor of device to remove + + Note: + Thread-safe operation with comprehensive error handling. + """ with self._deviceLock: try: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: device removed: ' + str(fd) + ' ' + str( - self.iDevices[fd]), debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: device removed: " + + str(fd) + + " " + + str(self.iDevices[fd]), + debug.DebugLevel.INFO, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'InputDriver evdev: device removed: ' + - str(fd) + - ' Error: ' + - str(e), - debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "InputDriver evdev: device removed: " + + str(fd) + + " Error: " + + str(e), + debug.DebugLevel.INFO, + ) self.clear_event_buffer() try: self.ungrab_device(fd) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error ungrabbing device ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error ungrabbing device " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) try: self.iDevices[fd].close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error closing iDevice ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error closing iDevice " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) try: self.uDevices[fd].close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error closing uDevice ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error closing uDevice " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) try: - del (self.iDevices[fd]) + del self.iDevices[fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error deleting iDevice ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error deleting iDevice " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) try: - del (self.uDevices[fd]) + del self.uDevices[fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error deleting uDevice ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error deleting uDevice " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) try: - del (self.gDevices[fd]) + del self.gDevices[fd] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver remove_device: Error deleting gDevice ' + str(fd) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver remove_device: Error deleting gDevice " + + str(fd) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) self.update_m_pi_devices_fd() def has_i_devices(self): @@ -613,15 +901,28 @@ class driver(inputDriver): return True def send_key(self, key, state): + """Inject a synthetic key event. + + Sends a key press or release event using UInput. Used for + features like key forwarding and macro execution. + + Args: + key (str): Key name (e.g., 'KEY_A') + state (int): Key state (0=release, 1=press, 2=repeat) + """ if not self._initialized: return try: self.UInputinject.write(e.EV_KEY, e.ecodes[key], state) self.UInputinject.syn() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'evdevDriver send_key: Error sending key ' + str(key) + ': ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "evdevDriver send_key: Error sending key " + + str(key) + + ": " + + str(e), + debug.DebugLevel.ERROR, + ) def remove_all_devices(self): if not self.has_i_devices(): diff --git a/src/fenrirscreenreader/inputDriver/ptyDriver.py b/src/fenrirscreenreader/inputDriver/ptyDriver.py index 87a10ba2..7ca54df9 100644 --- a/src/fenrirscreenreader/inputDriver/ptyDriver.py +++ b/src/fenrirscreenreader/inputDriver/ptyDriver.py @@ -2,19 +2,44 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import time + from fenrirscreenreader.core import debug from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver class driver(inputDriver): + """PTY (Pseudo-terminal) input driver for Fenrir screen reader. + + This driver provides input handling for terminal emulation environments + where direct device access (evdev) is not available or appropriate. + It uses byte-based input processing instead of key event processing. + + This is primarily used when running Fenrir in terminal emulators, + desktop environments, or other contexts where traditional TTY device + access is not available. + + Features: + - Byte-based input processing + - Terminal emulation compatibility + - Simplified input handling for non-TTY environments + """ def __init__(self): self._is_initialized = False inputDriver.__init__(self) def initialize(self, environment): + """Initialize the PTY input driver. + + Sets the input manager to use byte-based shortcuts instead of + key-based shortcuts, enabling proper operation in terminal + emulation environments. + + Args: + environment: Fenrir environment dictionary + """ self.env = environment - self.env['runtime']['InputManager'].set_shortcut_type('BYTE') + self.env["runtime"]["InputManager"].set_shortcut_type("BYTE") self._is_initialized = True diff --git a/src/fenrirscreenreader/remoteDriver/dummyDriver.py b/src/fenrirscreenreader/remoteDriver/dummyDriver.py index 1a715036..1b686fe6 100644 --- a/src/fenrirscreenreader/remoteDriver/dummyDriver.py +++ b/src/fenrirscreenreader/remoteDriver/dummyDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver diff --git a/src/fenrirscreenreader/remoteDriver/tcpDriver.py b/src/fenrirscreenreader/remoteDriver/tcpDriver.py index 01280b8a..149eda17 100644 --- a/src/fenrirscreenreader/remoteDriver/tcpDriver.py +++ b/src/fenrirscreenreader/remoteDriver/tcpDriver.py @@ -2,16 +2,16 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug -from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver -from fenrirscreenreader.core.eventData import FenrirEventType - -import select -import socket import os import os.path +import select +import socket + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import FenrirEventType +from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver class driver(remoteDriver): @@ -20,16 +20,18 @@ class driver(remoteDriver): def initialize(self, environment): self.env = environment - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.watch_dog, multiprocess=True) + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.watch_dog, multiprocess=True + ) def watch_dog(self, active, event_queue): # echo "command say this is a test" | nc localhost 22447 self.fenrirSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.fenrirSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.host = '127.0.0.1' - self.port = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'remote', 'port') + self.host = "127.0.0.1" + self.port = self.env["runtime"]["SettingsManager"].get_setting_as_int( + "remote", "port" + ) self.fenrirSock.bind((self.host, self.port)) self.fenrirSock.listen(1) while active.value: @@ -44,24 +46,30 @@ class driver(remoteDriver): try: rawdata = client_sock.recv(8129) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'tcpDriver watch_dog: Error receiving data from client: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "tcpDriver watch_dog: Error receiving data from client: " + + str(e), + debug.DebugLevel.ERROR, + ) try: data = rawdata.decode("utf-8").rstrip().lstrip() - event_queue.put({"Type": FenrirEventType.remote_incomming, - "data": data - }) + event_queue.put( + {"Type": FenrirEventType.remote_incomming, "data": data} + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'tcpDriver watch_dog: Error decoding/queuing data: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "tcpDriver watch_dog: Error decoding/queuing data: " + + str(e), + debug.DebugLevel.ERROR, + ) try: client_sock.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'tcpDriver watch_dog: Error closing client socket: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "tcpDriver watch_dog: Error closing client socket: " + + str(e), + debug.DebugLevel.ERROR, + ) if self.fenrirSock: self.fenrirSock.close() self.fenrirSock = None diff --git a/src/fenrirscreenreader/remoteDriver/unixDriver.py b/src/fenrirscreenreader/remoteDriver/unixDriver.py index 23294fa7..01b6d2c0 100644 --- a/src/fenrirscreenreader/remoteDriver/unixDriver.py +++ b/src/fenrirscreenreader/remoteDriver/unixDriver.py @@ -2,16 +2,16 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -from fenrirscreenreader.core import debug -from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver -from fenrirscreenreader.core.eventData import FenrirEventType - -import select -import socket import os import os.path +import select +import socket + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import FenrirEventType +from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver class driver(remoteDriver): @@ -20,27 +20,36 @@ class driver(remoteDriver): def initialize(self, environment): self.env = environment - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.watch_dog, multiprocess=True) + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.watch_dog, multiprocess=True + ) def watch_dog(self, active, event_queue): # echo "command say this is a test" | socat - # UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock - socket_file = '' + socket_file = "" try: - socket_file = self.env['runtime']['SettingsManager'].get_setting( - 'remote', 'socket_file') + socket_file = self.env["runtime"]["SettingsManager"].get_setting( + "remote", "socket_file" + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'unixDriver watch_dog: Error getting socket file setting: ' + str(e), - debug.DebugLevel.ERROR) - if socket_file == '': - if self.env['runtime']['SettingsManager'].get_setting( - 'screen', 'driver') == 'vcsaDriver': - socket_file = '/tmp/fenrirscreenreader-deamon.sock' + self.env["runtime"]["DebugManager"].write_debug_out( + "unixDriver watch_dog: Error getting socket file setting: " + + str(e), + debug.DebugLevel.ERROR, + ) + if socket_file == "": + if ( + self.env["runtime"]["SettingsManager"].get_setting( + "screen", "driver" + ) + == "vcsaDriver" + ): + socket_file = "/tmp/fenrirscreenreader-deamon.sock" else: - socket_file = '/tmp/fenrirscreenreader-' + \ - str(os.getppid()) + '.sock' + socket_file = ( + "/tmp/fenrirscreenreader-" + str(os.getppid()) + ".sock" + ) if os.path.exists(socket_file): os.unlink(socket_file) self.fenrirSock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) @@ -63,28 +72,37 @@ class driver(remoteDriver): try: rawdata = client_sock.recv(8129) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'unixDriver watch_dog: Error receiving data from client: ' + str(e), - debug.DebugLevel.ERROR) - rawdata = b'' # Set default empty data if recv fails + self.env["runtime"]["DebugManager"].write_debug_out( + "unixDriver watch_dog: Error receiving data from client: " + + str(e), + debug.DebugLevel.ERROR, + ) + rawdata = b"" # Set default empty data if recv fails try: data = rawdata.decode("utf-8").rstrip().lstrip() - event_queue.put({"Type": FenrirEventType.remote_incomming, - "data": data - }) + event_queue.put( + { + "Type": FenrirEventType.remote_incomming, + "data": data, + } + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'unixDriver watch_dog: Error decoding/queuing data: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "unixDriver watch_dog: Error decoding/queuing data: " + + str(e), + debug.DebugLevel.ERROR, + ) finally: # Always close client socket, even if data processing fails try: client_sock.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'unixDriver watch_dog: Error closing client socket: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "unixDriver watch_dog: Error closing client socket: " + + str(e), + debug.DebugLevel.ERROR, + ) if self.fenrirSock: self.fenrirSock.close() self.fenrirSock = None diff --git a/src/fenrirscreenreader/screenDriver/dummyDriver.py b/src/fenrirscreenreader/screenDriver/dummyDriver.py index 667c9a58..09c41cf6 100644 --- a/src/fenrirscreenreader/screenDriver/dummyDriver.py +++ b/src/fenrirscreenreader/screenDriver/dummyDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.screenDriver import ScreenDriver as screenDriver diff --git a/src/fenrirscreenreader/screenDriver/ptyDriver.py b/src/fenrirscreenreader/screenDriver/ptyDriver.py index e7015a27..92b04134 100644 --- a/src/fenrirscreenreader/screenDriver/ptyDriver.py +++ b/src/fenrirscreenreader/screenDriver/ptyDriver.py @@ -2,21 +2,23 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. -import os -import struct -import sys -import pty -import tty -import termios -import shlex -import signal -import pyte -import time import fcntl import getpass +import os +import pty +import shlex +import signal +import struct +import sys +import termios +import time +import tty from select import select + +import pyte + from fenrirscreenreader.core import debug from fenrirscreenreader.core.eventData import FenrirEventType from fenrirscreenreader.core.screenDriver import ScreenDriver as screenDriver @@ -31,11 +33,12 @@ class FenrirScreen(pyte.Screen): class Terminal: def __init__(self, columns, lines, p_in): - self.text = '' + self.text = "" self.attributes = None self.screen = FenrirScreen(columns, lines) - self.screen.write_process_input = \ - lambda data: p_in.write(data.encode()) + self.screen.write_process_input = lambda data: p_in.write( + data.encode() + ) self.stream = pyte.ByteStream() self.stream.attach(self.screen) @@ -49,8 +52,13 @@ class Terminal: lines = self.screen.dirty else: lines = range(self.screen.lines) - self.attributes = [[list(attribute[1:]) + [False, 'default', 'default'] - for attribute in line.values()] for line in buffer.values()] + self.attributes = [ + [ + list(attribute[1:]) + [False, "default", "default"] + for attribute in line.values() + ] + for line in buffer.values() + ] for y in lines: try: t = self.attributes[y] @@ -58,23 +66,30 @@ class Terminal: # Terminal class doesn't have access to env, use fallback # logging print( - f'ptyDriver Terminal update_attributes: Error accessing attributes: {e}') + f"ptyDriver Terminal update_attributes: Error accessing attributes: {e}" + ) self.attributes.append([]) - self.attributes[y] = [list( - attribute[1:]) + [False, 'default', 'default'] for attribute in (buffer[y].values())] + self.attributes[y] = [ + list(attribute[1:]) + [False, "default", "default"] + for attribute in (buffer[y].values()) + ] if len(self.attributes[y]) < self.screen.columns: diff = self.screen.columns - len(self.attributes[y]) - self.attributes[y] += [['default', - 'default', - False, - False, - False, - False, - False, - False, - 'default', - 'default']] * diff + self.attributes[y] += [ + [ + "default", + "default", + False, + False, + False, + False, + False, + False, + "default", + "default", + ] + ] * diff def resize(self, lines, columns): self.screen.resize(lines, columns) @@ -89,23 +104,24 @@ class Terminal: if y_pos == -1: y_pos = self.screen.cursor.y self.screen.cursor.x = min( - self.screen.cursor.x, - self.screen.columns - 1) + self.screen.cursor.x, self.screen.columns - 1 + ) self.screen.cursor.y = min(self.screen.cursor.y, self.screen.lines - 1) def get_screen_content(self): cursor = self.screen.cursor - self.text = '\n'.join(self.screen.display) + self.text = "\n".join(self.screen.display) self.update_attributes(self.attributes is None) self.screen.dirty.clear() - return {"cursor": (cursor.x, cursor.y), - 'lines': self.screen.lines, - 'columns': self.screen.columns, - "text": self.text, - 'attributes': self.attributes.copy(), - 'screen': 'pty', - 'screenUpdateTime': time.time(), - }.copy() + return { + "cursor": (cursor.x, cursor.y), + "lines": self.screen.lines, + "columns": self.screen.columns, + "text": self.text, + "attributes": self.attributes.copy(), + "screen": "pty", + "screenUpdateTime": time.time(), + }.copy() class driver(screenDriver): @@ -119,31 +135,34 @@ class driver(screenDriver): def initialize(self, environment): self.env = environment - self.command = self.env['runtime']['SettingsManager'].get_setting( - 'general', 'shell') - self.shortcutType = self.env['runtime']['InputManager'].get_shortcut_type( + self.command = self.env["runtime"]["SettingsManager"].get_setting( + "general", "shell" + ) + self.shortcutType = self.env["runtime"][ + "InputManager" + ].get_shortcut_type() + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.terminal_emulation ) - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.terminal_emulation) def get_curr_screen(self): - self.env['screen']['oldTTY'] = 'pty' - self.env['screen']['newTTY'] = 'pty' + self.env["screen"]["oldTTY"] = "pty" + self.env["screen"]["newTTY"] = "pty" def inject_text_to_screen(self, msg_bytes, screen=None): if not screen: screen = self.p_out.fileno() if isinstance(msg_bytes, str): - msg_bytes = bytes(msg_bytes, 'UTF-8') + msg_bytes = bytes(msg_bytes, "UTF-8") os.write(screen, msg_bytes) def get_session_information(self): - self.env['screen']['autoIgnoreScreens'] = [] - self.env['general']['prev_user'] = getpass.getuser() - self.env['general']['curr_user'] = getpass.getuser() + self.env["screen"]["autoIgnoreScreens"] = [] + self.env["general"]["prev_user"] = getpass.getuser() + self.env["general"]["curr_user"] = getpass.getuser() def read_all(self, fd, timeout=0.3, interruptFd=None, len=65536): - msg_bytes = b'' + msg_bytes = b"" fd_list = [] fd_list += [fd] if interruptFd: @@ -155,7 +174,7 @@ class driver(screenDriver): if fd not in r: break data = os.read(fd, len) - if data == b'': + if data == b"": raise EOFError msg_bytes += data # exit on interrupt available @@ -174,44 +193,47 @@ class driver(screenDriver): env = os.environ.copy() # values are VT100,xterm-256color,linux try: - if env["TERM"] == '': - env["TERM"] = 'linux' + if env["TERM"] == "": + env["TERM"] = "linux" except Exception as e: # Child process doesn't have access to env, use fallback # logging print( - f'ptyDriver spawnTerminal: Error checking TERM environment: {e}') - env["TERM"] = 'linux' + f"ptyDriver spawnTerminal: Error checking TERM environment: {e}" + ) + env["TERM"] = "linux" os.execvpe(argv[0], argv, env) # File-like object for I/O with the child process aka command. p_out = os.fdopen(master_fd, "w+b", 0) return Terminal(columns, lines, p_out), p_pid, p_out def resize_terminal(self, fd): - s = struct.pack('HHHH', 0, 0, 0, 0) + s = struct.pack("HHHH", 0, 0, 0, 0) s = fcntl.ioctl(0, termios.TIOCGWINSZ, s) fcntl.ioctl(fd, termios.TIOCSWINSZ, s) - lines, columns, _, _ = struct.unpack('hhhh', s) + lines, columns, _, _ = struct.unpack("hhhh", s) return lines, columns def get_terminal_size(self, fd): - s = struct.pack('HHHH', 0, 0, 0, 0) + s = struct.pack("HHHH", 0, 0, 0, 0) lines, columns, _, _ = struct.unpack( - 'HHHH', fcntl.ioctl(fd, termios.TIOCGWINSZ, s)) + "HHHH", fcntl.ioctl(fd, termios.TIOCGWINSZ, s) + ) return lines, columns def handle_sigwinch(self, *args): - os.write(self.signalPipe[1], b'w') + os.write(self.signalPipe[1], b"w") def terminal_emulation(self, active, event_queue): try: old_attr = termios.tcgetattr(sys.stdin) tty.setraw(0) lines, columns = self.get_terminal_size(0) - if self.command == '': + if self.command == "": self.command = screen_utils.get_shell() self.terminal, self.p_pid, self.p_out = self.open_terminal( - columns, lines, self.command) + columns, lines, self.command + ) lines, columns = self.resize_terminal(self.p_out) self.terminal.resize(lines, columns) fd_list = [sys.stdin, self.p_out, self.signalPipe[0]] @@ -231,29 +253,50 @@ class driver(screenDriver): msg_bytes = self.read_all(sys.stdin.fileno(), len=4096) except (EOFError, OSError): event_queue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + { + "Type": FenrirEventType.stop_main_loop, + "data": None, + } + ) break - if self.shortcutType == 'KEY': + if self.shortcutType == "KEY": try: self.inject_text_to_screen(msg_bytes) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'ptyDriver getInputData: Error injecting text to screen: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "ptyDriver getInputData: Error injecting text to screen: " + + str(e), + debug.DebugLevel.ERROR, + ) event_queue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + { + "Type": FenrirEventType.stop_main_loop, + "data": None, + } + ) break else: - event_queue.put({"Type": FenrirEventType.byte_input, - "data": msg_bytes}) + event_queue.put( + { + "Type": FenrirEventType.byte_input, + "data": msg_bytes, + } + ) # output if self.p_out in r: try: msg_bytes = self.read_all( - self.p_out.fileno(), interruptFd=sys.stdin.fileno()) + self.p_out.fileno(), interruptFd=sys.stdin.fileno() + ) except (EOFError, OSError): event_queue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + { + "Type": FenrirEventType.stop_main_loop, + "data": None, + } + ) break # feed and send event bevore write, the pyte already has the right state # so fenrir already can progress bevore os.write what @@ -263,19 +306,25 @@ class driver(screenDriver): { "Type": FenrirEventType.screen_update, "data": screen_utils.create_screen_event_data( - self.terminal.get_screen_content())}) + self.terminal.get_screen_content() + ), + } + ) self.inject_text_to_screen( - msg_bytes, screen=sys.stdout.fileno()) + msg_bytes, screen=sys.stdout.fileno() + ) except Exception as e: # Process died? print(e) event_queue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + {"Type": FenrirEventType.stop_main_loop, "data": None} + ) finally: os.kill(self.p_pid, signal.SIGTERM) self.p_out.close() termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr) event_queue.put( - {"Type": FenrirEventType.stop_main_loop, "data": None}) + {"Type": FenrirEventType.stop_main_loop, "data": None} + ) sys.exit(0) def get_curr_application(self): diff --git a/src/fenrirscreenreader/screenDriver/vcsaDriver.py b/src/fenrirscreenreader/screenDriver/vcsaDriver.py index 09705391..3705306e 100644 --- a/src/fenrirscreenreader/screenDriver/vcsaDriver.py +++ b/src/fenrirscreenreader/screenDriver/vcsaDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # attrib: # http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html # 0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. @@ -10,17 +10,21 @@ # blink = 5 if attr & 1 else 0 # bold = 1 if attr & 16 else 0 -import subprocess +import fcntl import glob import os +import select +import subprocess import termios import time -import select -import dbus -import fcntl from array import array from fcntl import ioctl -from struct import unpack_from, unpack, pack +from struct import pack +from struct import unpack +from struct import unpack_from + +import dbus + from fenrirscreenreader.core import debug from fenrirscreenreader.core.eventData import FenrirEventType from fenrirscreenreader.core.screenDriver import ScreenDriver as screenDriver @@ -28,128 +32,230 @@ from fenrirscreenreader.utils import screen_utils class driver(screenDriver): + """Linux VCSA (Virtual Console Screen Access) driver for Fenrir screen reader. + + This driver provides access to Linux virtual consoles (TTYs) through the VCSA + interface, allowing real-time monitoring of screen content and cursor position. + It supports both text content extraction and color/attribute detection. + + The driver monitors multiple virtual consoles simultaneously and can detect: + - Screen content changes (text updates) + - Cursor movement + - TTY switching + - Text attributes (colors, bold, etc.) + - Session information via D-Bus/logind + + Attributes: + ListSessions: D-Bus method for listing login sessions + sysBus: D-Bus system bus connection + charmap: Character mapping for text decoding + bgColorValues: Background color value mappings + fgColorValues: Foreground color value mappings + hichar: High character mask for Unicode support + """ def __init__(self): screenDriver.__init__(self) self.ListSessions = None self.sysBus = None self.charmap = {} self.bgColorValues = { - 0: 'black', - 1: 'blue', - 2: 'green', - 3: 'cyan', - 4: 'red', - 5: 'magenta', - 6: 'brown/yellow', - 7: 'white'} + 0: "black", + 1: "blue", + 2: "green", + 3: "cyan", + 4: "red", + 5: "magenta", + 6: "brown/yellow", + 7: "white", + } self.fgColorValues = { - 0: 'black', - 1: 'blue', - 2: 'green', - 3: 'cyan', - 4: 'red', - 5: 'magenta', - 6: 'brown/yellow', - 7: 'light gray', - 8: 'dark gray', - 9: 'light blue', - 10: 'light green', - 11: 'light cyan', - 12: 'light red', - 13: 'light magenta', - 14: 'light yellow', - 15: 'white'} + 0: "black", + 1: "blue", + 2: "green", + 3: "cyan", + 4: "red", + 5: "magenta", + 6: "brown/yellow", + 7: "light gray", + 8: "dark gray", + 9: "light blue", + 10: "light green", + 11: "light cyan", + 12: "light red", + 13: "light magenta", + 14: "light yellow", + 15: "white", + } self.hichar = None try: # set workaround for paste clipboard -> inject_text_to_screen - subprocess.run(['sysctl', 'dev.tty.legacy_tiocsti=1'], - check=False, capture_output=True, timeout=5) + subprocess.run( + ["sysctl", "dev.tty.legacy_tiocsti=1"], + check=False, + capture_output=True, + timeout=5, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver shutdown: Error running fgconsole: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver shutdown: Error running fgconsole: " + str(e), + debug.DebugLevel.ERROR, + ) def initialize(self, environment): + """Initialize the VCSA driver with the given environment. + + Sets up default attributes, starts the screen monitoring watchdog process, + and prepares the driver for screen content monitoring. + + Args: + environment: The Fenrir environment dictionary containing runtime managers + and configuration settings. + """ self.env = environment - self.env['runtime']['AttributeManager'].append_default_attributes([ - self.fgColorValues[7], # fg - self.bgColorValues[0], # bg - False, # bold - False, # italics - False, # underscore - False, # strikethrough - False, # reverse - False, # blink - 'default', # fontsize - 'default' # fontfamily - ]) # end attribute ) - self.env['runtime']['ProcessManager'].add_custom_event_thread( - self.update_watchdog, multiprocess=True) + self.env["runtime"]["AttributeManager"].append_default_attributes( + [ + self.fgColorValues[7], # fg + self.bgColorValues[0], # bg + False, # bold + False, # italics + False, # underscore + False, # strikethrough + False, # reverse + False, # blink + "default", # fontsize + "default", # fontfamily + ] + ) # end attribute ) + self.env["runtime"]["ProcessManager"].add_custom_event_thread( + self.update_watchdog, multiprocess=True + ) def get_curr_screen(self): - self.env['screen']['oldTTY'] = self.env['screen']['newTTY'] + """Get the currently active TTY number. + + Reads from /sys/devices/virtual/tty/tty0/active to determine which + virtual console is currently active and updates the environment. + + Updates: + env['screen']['oldTTY']: Previous TTY number + env['screen']['newTTY']: Current TTY number + """ + self.env["screen"]["oldTTY"] = self.env["screen"]["newTTY"] try: - with open('/sys/devices/virtual/tty/tty0/active', 'r') as currScreenFile: - self.env['screen']['newTTY'] = str(currScreenFile.read()[3:-1]) + with open( + "/sys/devices/virtual/tty/tty0/active", "r" + ) as currScreenFile: + self.env["screen"]["newTTY"] = str(currScreenFile.read()[3:-1]) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) def inject_text_to_screen(self, text, screen=None): - use_screen = "/dev/tty" + self.env['screen']['newTTY'] + """Inject text into the specified screen as if typed by user. + + Uses the TIOCSTI ioctl to simulate keystrokes on the target TTY. + This is primarily used for clipboard paste functionality. + + Args: + text (str): Text to inject into the screen + screen (str, optional): Target screen device (e.g., '/dev/tty1'). + If None, uses current TTY. + + Note: + Requires appropriate permissions and may need legacy_tiocsti=1 + kernel parameter on newer systems. + """ + use_screen = "/dev/tty" + self.env["screen"]["newTTY"] if screen is not None: use_screen = screen - with open(use_screen, 'w') as fd: + with open(use_screen, "w") as fd: for c in text: fcntl.ioctl(fd, termios.TIOCSTI, c) def get_session_information(self): - self.env['screen']['autoIgnoreScreens'] = [] + """Retrieve session information via D-Bus logind interface. + + Connects to systemd-logind to gather information about active sessions, + including session types and TTY assignments. This helps identify which + screens should be automatically ignored (e.g., X11 sessions). + + Updates: + env['screen']['autoIgnoreScreens']: List of screens to ignore + env['general']['curr_user']: Current user for active session + env['general']['prev_user']: Previous user + + Note: + Gracefully handles cases where logind is not available. + """ + self.env["screen"]["autoIgnoreScreens"] = [] try: if not self.sysBus: self.sysBus = dbus.SystemBus() obj = self.sysBus.get_object( - 'org.freedesktop.login1', '/org/freedesktop/login1') - inf = dbus.Interface(obj, 'org.freedesktop.login1.Manager') - self.ListSessions = inf.get_dbus_method('ListSessions') + "org.freedesktop.login1", "/org/freedesktop/login1" + ) + inf = dbus.Interface(obj, "org.freedesktop.login1.Manager") + self.ListSessions = inf.get_dbus_method("ListSessions") sessions = self.ListSessions() for session in sessions: obj = self.sysBus.get_object( - 'org.freedesktop.login1', session[4]) - inf = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - session_type = inf.Get('org.freedesktop.login1.Session', 'Type') - screen = str(inf.Get('org.freedesktop.login1.Session', 'VTNr')) - if screen == '': + "org.freedesktop.login1", session[4] + ) + inf = dbus.Interface(obj, "org.freedesktop.DBus.Properties") + session_type = inf.Get( + "org.freedesktop.login1.Session", "Type" + ) + screen = str(inf.Get("org.freedesktop.login1.Session", "VTNr")) + if screen == "": screen = str( - inf.Get( - 'org.freedesktop.login1.Session', - 'TTY')) - screen = screen[screen.upper().find('TTY') + 3:] - if screen == '': - self.env['runtime']['DebugManager'].write_debug_out( - 'No TTY found for session:' + session[4], debug.DebugLevel.ERROR) + inf.Get("org.freedesktop.login1.Session", "TTY") + ) + screen = screen[screen.upper().find("TTY") + 3 :] + if screen == "": + self.env["runtime"]["DebugManager"].write_debug_out( + "No TTY found for session:" + session[4], + debug.DebugLevel.ERROR, + ) return - if session_type.upper() != 'TTY': - self.env['screen']['autoIgnoreScreens'] += [screen] - if screen == self.env['screen']['newTTY']: - if self.env['general']['curr_user'] != session[2]: - self.env['general']['prev_user'] = self.env['general']['curr_user'] - self.env['general']['curr_user'] = session[2] + if session_type.upper() != "TTY": + self.env["screen"]["autoIgnoreScreens"] += [screen] + if screen == self.env["screen"]["newTTY"]: + if self.env["general"]["curr_user"] != session[2]: + self.env["general"]["prev_user"] = self.env["general"][ + "curr_user" + ] + self.env["general"]["curr_user"] = session[2] except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'get_session_information: Maybe no LoginD:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "get_session_information: Maybe no LoginD:" + str(e), + debug.DebugLevel.ERROR, + ) # self.env['runtime']['DebugManager'].write_debug_out('get_session_information:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) ,debug.DebugLevel.INFO) def read_file(self, file): - d = b'' + """Read content from a file handle with error recovery. + + Attempts to read the entire file content, falling back to + line-by-line reading if the initial read fails. This is used + for reading VCSA/VCSU device files. + + Args: + file: Open file handle to read from + + Returns: + bytes: File content as bytes + """ + d = b"" file.seek(0) try: d = file.read() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver get_screen_text: Error reading file: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver get_screen_text: Error reading file: " + str(e), + debug.DebugLevel.ERROR, + ) file.seek(0) while True: # Read from file @@ -162,40 +268,64 @@ class driver(screenDriver): return d def update_watchdog(self, active, event_queue): + """Main watchdog loop for monitoring screen changes. + + This is the core monitoring function that runs in a separate process. + It uses epoll to efficiently monitor multiple VCSA devices and the + active TTY file for changes. When changes are detected, it generates + appropriate events for the main Fenrir process. + + The watchdog monitors: + - Screen content changes (text updates) + - TTY switches (screen changes) + - Cursor position changes + + Args: + active: Shared boolean value controlling the watchdog loop + event_queue: Queue for sending events to the main process + + Events Generated: + - FenrirEventType.screen_changed: When switching TTYs + - FenrirEventType.screen_update: When screen content changes + + Note: + This method runs in a multiprocess context and includes comprehensive + cleanup of file handles in the finally block. + """ vcsa = {} vcsu = {} tty = None watchdog = None try: - use_vcsu = os.access('/dev/vcsu', os.R_OK) - vcsa_devices = glob.glob('/dev/vcsa*') + use_vcsu = os.access("/dev/vcsu", os.R_OK) + vcsa_devices = glob.glob("/dev/vcsa*") vcsu_devices = None - last_screen_content = b'' + last_screen_content = b"" # Open TTY file with proper cleanup - tty = open('/sys/devices/virtual/tty/tty0/active', 'r') + tty = open("/sys/devices/virtual/tty/tty0/active", "r") curr_screen = str(tty.read()[3:-1]) old_screen = curr_screen # Open VCSA devices with proper cleanup tracking for vcsaDev in vcsa_devices: index = str(vcsaDev[9:]) - vcsa[index] = open(vcsaDev, 'rb') + vcsa[index] = open(vcsaDev, "rb") if index == curr_screen: last_screen_content = self.read_file(vcsa[index]) # Open VCSU devices if available if use_vcsu: - vcsu_devices = glob.glob('/dev/vcsu*') + vcsu_devices = glob.glob("/dev/vcsu*") for vcsuDev in vcsu_devices: index = str(vcsuDev[9:]) - vcsu[index] = open(vcsuDev, 'rb') + vcsu[index] = open(vcsuDev, "rb") self.update_char_map(curr_screen) watchdog = select.epoll() watchdog.register( - vcsa[curr_screen], - select.POLLPRI | select.POLLERR) + vcsa[curr_screen], select.POLLPRI | select.POLLERR + ) watchdog.register(tty, select.POLLPRI | select.POLLERR) while active.value: changes = watchdog.poll(1) @@ -203,43 +333,70 @@ class driver(screenDriver): fileno = change[0] event = change[1] if fileno == tty.fileno(): - self.env['runtime']['DebugManager'].write_debug_out( - 'ScreenChange', debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "ScreenChange", debug.DebugLevel.INFO + ) tty.seek(0) curr_screen = str(tty.read()[3:-1]) if curr_screen != old_screen: try: watchdog.unregister(vcsa[old_screen]) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver update_watchdog: Error unregistering watchdog: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "vcsaDriver update_watchdog: Error unregistering watchdog: " + + str(e), + debug.DebugLevel.ERROR, + ) try: watchdog.register( - vcsa[curr_screen], select.POLLPRI | select.POLLERR) + vcsa[curr_screen], + select.POLLPRI | select.POLLERR, + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver update_watchdog: Error registering watchdog: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "vcsaDriver update_watchdog: Error registering watchdog: " + + str(e), + debug.DebugLevel.ERROR, + ) self.update_char_map(curr_screen) old_screen = curr_screen try: vcsa[curr_screen].seek(0) last_screen_content = self.read_file( - vcsa[curr_screen]) + vcsa[curr_screen] + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver update_watchdog: Error reading screen content: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"][ + "DebugManager" + ].write_debug_out( + "vcsaDriver update_watchdog: Error reading screen content: " + + str(e), + debug.DebugLevel.ERROR, + ) vcsu_content = None if use_vcsu: vcsu[curr_screen].seek(0) - vcsu_content = self.read_file(vcsu[curr_screen]) - event_queue.put({"Type": FenrirEventType.screen_changed, "data": self.create_screen_event_data( - curr_screen, last_screen_content, vcsu_content)}) + vcsu_content = self.read_file( + vcsu[curr_screen] + ) + event_queue.put( + { + "Type": FenrirEventType.screen_changed, + "data": self.create_screen_event_data( + curr_screen, + last_screen_content, + vcsu_content, + ), + } + ) else: - self.env['runtime']['DebugManager'].write_debug_out( - 'screen_update', debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "screen_update", debug.DebugLevel.INFO + ) vcsa[curr_screen].seek(0) time.sleep(0.01) dirty_content = self.read_file(vcsa[curr_screen]) @@ -247,16 +404,32 @@ class driver(screenDriver): vcsu_content = None timeout = time.time() # error case - if screen_content == b'': + if screen_content == b"": continue - if last_screen_content == b'': + if last_screen_content == b"": last_screen_content = screen_content - if (abs(int(screen_content[2]) - int(last_screen_content[2])) in [1, 2]) and ( - int(screen_content[3]) == int(last_screen_content[3])): + if ( + abs( + int(screen_content[2]) + - int(last_screen_content[2]) + ) + in [1, 2] + ) and ( + int(screen_content[3]) + == int(last_screen_content[3]) + ): # Skip X Movement pass - elif (abs(int(screen_content[3]) - int(last_screen_content[3])) in [1]) and \ - (int(screen_content[2]) == int(last_screen_content[2])): + elif ( + abs( + int(screen_content[3]) + - int(last_screen_content[3]) + ) + in [1] + ) and ( + int(screen_content[2]) + == int(last_screen_content[2]) + ): # Skip Y Movement pass else: @@ -268,7 +441,9 @@ class driver(screenDriver): # if not vcsa[curr_screen] in r: # break vcsa[curr_screen].seek(0) - dirty_content = self.read_file(vcsa[curr_screen]) + dirty_content = self.read_file( + vcsa[curr_screen] + ) if screen_content == dirty_content: break if time.time() - timeout >= 0.1: @@ -278,11 +453,18 @@ class driver(screenDriver): vcsu[curr_screen].seek(0) vcsu_content = self.read_file(vcsu[curr_screen]) last_screen_content = screen_content - event_queue.put({"Type": FenrirEventType.screen_update, "data": self.create_screen_event_data( - curr_screen, screen_content, vcsu_content)}) + event_queue.put( + { + "Type": FenrirEventType.screen_update, + "data": self.create_screen_event_data( + curr_screen, screen_content, vcsu_content + ), + } + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VCSA:update_watchdog:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VCSA:update_watchdog:" + str(e), debug.DebugLevel.ERROR + ) time.sleep(0.2) finally: # Clean up all file handles @@ -290,114 +472,186 @@ class driver(screenDriver): if watchdog: watchdog.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver update_watchdog: Error closing watchdog: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver update_watchdog: Error closing watchdog: " + + str(e), + debug.DebugLevel.ERROR, + ) try: if tty: tty.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver shutdown: Error closing TTY: ' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver shutdown: Error closing TTY: " + str(e), + debug.DebugLevel.ERROR, + ) for handle in vcsa.values(): try: handle.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver shutdown: Error closing VCSA handle: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver shutdown: Error closing VCSA handle: " + + str(e), + debug.DebugLevel.ERROR, + ) for handle in vcsu.values(): try: handle.close() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver shutdown: Error closing VCSU handle: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver shutdown: Error closing VCSU handle: " + + str(e), + debug.DebugLevel.ERROR, + ) def create_screen_event_data(self, screen, vcsaContent, vcsu_content=None): + """Create standardized screen event data from VCSA content. + + Processes raw VCSA bytes into a structured event data dictionary + containing screen dimensions, cursor position, text content, and + color attributes. + + Args: + screen (str): TTY number (e.g., '1' for tty1) + vcsaContent (bytes): Raw VCSA device content + vcsu_content (bytes, optional): VCSU content for Unicode support + + Returns: + dict: Event data with keys: + - bytes: Raw VCSA content + - lines: Screen height + - columns: Screen width + - textCursor: Cursor position {x, y} + - screen: TTY number + - screenUpdateTime: Timestamp + - text: Decoded text content + - attributes: Color/formatting attributes + """ event_data = { - 'bytes': vcsaContent, - 'lines': int(vcsaContent[0]), - 'columns': int(vcsaContent[1]), - 'textCursor': - { - 'x': int(vcsaContent[2]), - 'y': int(vcsaContent[3]) - }, - 'screen': screen, - 'screenUpdateTime': time.time(), - 'text': '', - 'attributes': [], + "bytes": vcsaContent, + "lines": int(vcsaContent[0]), + "columns": int(vcsaContent[1]), + "textCursor": {"x": int(vcsaContent[2]), "y": int(vcsaContent[3])}, + "screen": screen, + "screenUpdateTime": time.time(), + "text": "", + "attributes": [], } try: - event_data['text'], event_data['attributes'] = self.auto_decode_vcsa( - vcsaContent[4:], event_data['lines'], event_data['columns']) + event_data["text"], event_data["attributes"] = ( + self.auto_decode_vcsa( + vcsaContent[4:], event_data["lines"], event_data["columns"] + ) + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver create_screen_event_data: Error decoding VCSA content: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver create_screen_event_data: Error decoding VCSA content: " + + str(e), + debug.DebugLevel.ERROR, + ) # VCSU seems to give b' ' instead of b'\x00\x00\x00' (tsp), # deactivated until its fixed if vcsu_content is not None: try: - vcsu_content_as_text = vcsu_content.decode('UTF-32') - event_data['text'] = screen_utils.insert_newlines( - vcsu_content_as_text, event_data['columns']) + vcsu_content_as_text = vcsu_content.decode("UTF-32") + event_data["text"] = screen_utils.insert_newlines( + vcsu_content_as_text, event_data["columns"] + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver create_screen_event_data: Error decoding VCSU content: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver create_screen_event_data: Error decoding VCSU content: " + + str(e), + debug.DebugLevel.ERROR, + ) return event_data.copy() def update_char_map(self, screen): + """Update character mapping for the specified screen. + + Reads the Unicode font mapping from the TTY to properly decode + character data from VCSA. This handles special characters and + Unicode properly. + + Args: + screen (str): TTY number to update mapping for + + Updates: + self.charmap: Dictionary mapping byte values to Unicode characters + self.hichar: High character mask for extended characters + """ self.charmap = {} try: - with open('/dev/tty' + screen, 'rb') as tty: + with open("/dev/tty" + screen, "rb") as tty: GIO_UNIMAP = 0x4B66 VT_GETHIFONTMASK = 0x560D himask = array("H", (0,)) ioctl(tty, VT_GETHIFONTMASK, himask) - self.hichar, = unpack_from("@H", himask) + (self.hichar,) = unpack_from("@H", himask) sz = 512 - line = '' + line = "" while True: try: unipairs = array("H", [0] * (2 * sz)) unimapdesc = array( - "B", pack( - "@HP", sz, unipairs.buffer_info()[0])) + "B", pack("@HP", sz, unipairs.buffer_info()[0]) + ) ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) break except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VCSA:update_char_map:scaling up sz=' + str(sz) + ' ' + str(e), - debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "VCSA:update_char_map:scaling up sz=" + + str(sz) + + " " + + str(e), + debug.DebugLevel.WARNING, + ) sz *= 2 except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'VCSA:update_char_map:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "VCSA:update_char_map:" + str(e), debug.DebugLevel.ERROR + ) return - ncodes, = unpack_from("@H", unimapdesc) + (ncodes,) = unpack_from("@H", unimapdesc) utable = unpack_from("@%dH" % (2 * ncodes), unipairs) for u, b in zip(utable[::2], utable[1::2]): if self.charmap.get(b) is None: self.charmap[b] = chr(u) def auto_decode_vcsa(self, allData, rows, cols): - all_text = '' + """Decode raw VCSA data into text and attributes. + + Processes the character and attribute data from VCSA devices, + extracting both the text content and formatting information + (colors, bold, blink, etc.). + + Args: + allData (bytes): Raw character and attribute data from VCSA + rows (int): Number of screen rows + cols (int): Number of screen columns + + Returns: + tuple: (text_content, attributes) + - text_content (str): Decoded text with newlines + - attributes (list): List of attribute arrays for each character + + Note: + Each character in VCSA is stored as 2 bytes: character + attribute. + Attributes encode foreground/background colors, bold, blink, etc. + """ + all_text = "" all_attrib = [] i = 0 for y in range(rows): - line_text = '' + line_text = "" line_attrib = [] blink = 0 bold = 0 ink = 7 paper = 0 for x in range(cols): - data = allData[i: i + 2] + data = allData[i : i + 2] i += 2 - if data == b' \x07': + if data == b" \x07": # attr = 7 # ink = 7 # paper = 0 @@ -411,10 +665,11 @@ class driver(screenDriver): False, # strikethrough False, # reverse False, # blink - 'default', # fontsize - 'default'] # fontfamily + "default", # fontsize + "default", + ] # fontfamily line_attrib.append(char_attrib) - line_text += ' ' + line_text += " " continue ch = None try: @@ -425,9 +680,11 @@ class driver(screenDriver): if sh & self.hichar: ch |= 0x100 except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver auto_decode_vcsa: Error processing character: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver auto_decode_vcsa: Error processing character: " + + str(e), + debug.DebugLevel.ERROR, + ) ch = None if self.hichar == 0x100: attr >>= 1 @@ -443,13 +700,15 @@ class driver(screenDriver): # if (ink != 7) or (paper != 0): # print(ink,paper) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'vcsaDriver auto_decode_vcsa: Error processing attributes: ' + str(e), - debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "vcsaDriver auto_decode_vcsa: Error processing attributes: " + + str(e), + debug.DebugLevel.ERROR, + ) try: line_text += self.charmap[ch] except KeyError: - line_text += '?' + line_text += "?" char_attrib = [ self.fgColorValues[ink], @@ -460,30 +719,47 @@ class driver(screenDriver): False, # strikethrough False, # reverse blink == 1, # blink - 'default', # fontsize - 'default'] # fontfamily + "default", # fontsize + "default", + ] # fontfamily line_attrib.append(char_attrib) all_text += line_text if y + 1 < rows: - all_text += '\n' + all_text += "\n" all_attrib.append(line_attrib) return str(all_text), all_attrib def get_curr_application(self): + """Detect the currently running application on the active TTY. + + Uses 'ps' command to identify which process is currently in the + foreground on the active TTY, enabling application-specific features + like bookmarks and settings. + + Updates: + env['screen']['new_application']: Name of current application + + Note: + Filters out common shell processes (grep, sh, ps) to find the + actual user application. + """ apps = [] try: - curr_screen = self.env['screen']['newTTY'] - apps = subprocess.Popen( - 'ps -t tty' + - curr_screen + - ' -o comm,tty,stat', - shell=True, - stdout=subprocess.PIPE).stdout.read().decode()[ - :- - 1].split('\n') + curr_screen = self.env["screen"]["newTTY"] + apps = ( + subprocess.Popen( + "ps -t tty" + curr_screen + " -o comm,tty,stat", + shell=True, + stdout=subprocess.PIPE, + ) + .stdout.read() + .decode()[:-1] + .split("\n") + ) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) return try: for i in apps: @@ -491,15 +767,23 @@ class driver(screenDriver): i = i.split() i[0] = i[0] i[1] = i[1] - if '+' in i[2]: - if i[0] != '': - if not "GREP" == i[0] and \ - not "SH" == i[0] and \ - not "PS" == i[0]: + if "+" in i[2]: + if i[0] != "": + if ( + not "GREP" == i[0] + and not "SH" == i[0] + and not "PS" == i[0] + ): if "TTY" + curr_screen in i[1]: - if self.env['screen']['new_application'] != i[0]: - self.env['screen']['new_application'] = i[0] + if ( + self.env["screen"]["new_application"] + != i[0] + ): + self.env["screen"]["new_application"] = i[ + 0 + ] return except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + str(e), debug.DebugLevel.ERROR + ) diff --git a/src/fenrirscreenreader/soundDriver/debugDriver.py b/src/fenrirscreenreader/soundDriver/debugDriver.py index 70307f51..bafe74a6 100644 --- a/src/fenrirscreenreader/soundDriver/debugDriver.py +++ b/src/fenrirscreenreader/soundDriver/debugDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.soundDriver import sound_driver @@ -15,55 +15,53 @@ class driver(sound_driver): def initialize(self, environment): self.env = environment self._initialized = True - print('Sound Debug Driver: Initialized') + print("Sound Debug Driver: Initialized") def shutdown(self): if not self._initialized: return self.cancel() self._initialized = False - print('Sound Debug Driver: Shutdown') + print("Sound Debug Driver: Shutdown") def play_frequence( - self, - frequence, - duration, - adjust_volume=0.0, - interrupt=True): + self, frequence, duration, adjust_volume=0.0, interrupt=True + ): if not self._initialized: return if interrupt: self.cancel() print( - 'Sound Debug Driver: play_frequence:' + - ' freq:' + - str(frequence) + - ' duration:' + - str(duration) + - ' adjust_volume:' + - str(adjust_volume)) - print('Sound Debug Driver: -----------------------------------') + "Sound Debug Driver: play_frequence:" + + " freq:" + + str(frequence) + + " duration:" + + str(duration) + + " adjust_volume:" + + str(adjust_volume) + ) + print("Sound Debug Driver: -----------------------------------") def play_sound_file(self, file_path, interrupt=True): if not self._initialized: return if interrupt: self.cancel() - print('Sound Debug Driver: play_sound_file:' + str(file_path)) - print('Sound Debug Driver: -----------------------------------') + print("Sound Debug Driver: play_sound_file:" + str(file_path)) + print("Sound Debug Driver: -----------------------------------") def cancel(self): if not self._initialized: return - print('Sound Debug Driver: Cancel') + print("Sound Debug Driver: Cancel") def set_callback(self, callback): if not self._initialized: return - print('Sound Debug Driver: set_callback') + print("Sound Debug Driver: set_callback") def set_volume(self, volume): if not self._initialized: return self.volume = volume - print('Sound Debug Driver: set_volume:' + str(self.volume)) + print("Sound Debug Driver: set_volume:" + str(self.volume)) diff --git a/src/fenrirscreenreader/soundDriver/dummyDriver.py b/src/fenrirscreenreader/soundDriver/dummyDriver.py index c2460d77..68757f52 100644 --- a/src/fenrirscreenreader/soundDriver/dummyDriver.py +++ b/src/fenrirscreenreader/soundDriver/dummyDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.core.soundDriver import sound_driver diff --git a/src/fenrirscreenreader/soundDriver/genericDriver.py b/src/fenrirscreenreader/soundDriver/genericDriver.py index 8125deb3..407e56ba 100644 --- a/src/fenrirscreenreader/soundDriver/genericDriver.py +++ b/src/fenrirscreenreader/soundDriver/genericDriver.py @@ -2,40 +2,73 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import shlex +import subprocess from fenrirscreenreader.core import debug -import subprocess -import shlex from fenrirscreenreader.core.soundDriver import sound_driver class driver(sound_driver): + """Generic sound driver for Fenrir screen reader. + + This driver provides sound playback through external command-line tools + like sox, aplay, or other audio utilities. It supports both sound file + playback and frequency/tone generation. + + Features: + - Configurable external command execution + - Sound file playback (WAV, OGG, etc.) + - Frequency/tone generation + - Process management and cancellation + + Attributes: + proc: Currently running subprocess for sound playback + soundFileCommand (str): Command template for playing sound files + frequenceCommand (str): Command template for generating frequencies + """ def __init__(self): sound_driver.__init__(self) self.proc = None - self.soundType = '' - self.soundFileCommand = '' - self.frequenceCommand = '' + self.soundType = "" + self.soundFileCommand = "" + self.frequenceCommand = "" def initialize(self, environment): + """Initialize the generic sound driver. + + Loads command templates from configuration for sound file playback + and frequency generation. + + Args: + environment: Fenrir environment dictionary with settings + """ self.env = environment - self.soundFileCommand = self.env['runtime']['SettingsManager'].get_setting( - 'sound', 'genericPlayFileCommand') - self.frequenceCommand = self.env['runtime']['SettingsManager'].get_setting( - 'sound', 'genericFrequencyCommand') - if self.soundFileCommand == '': - self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile' - if self.frequenceCommand == '': - self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' + self.soundFileCommand = self.env["runtime"][ + "SettingsManager" + ].get_setting("sound", "genericPlayFileCommand") + self.frequenceCommand = self.env["runtime"][ + "SettingsManager" + ].get_setting("sound", "genericFrequencyCommand") + if self.soundFileCommand == "": + self.soundFileCommand = "play -q -v fenrirVolume fenrirSoundFile" + if self.frequenceCommand == "": + self.frequenceCommand = "play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence" self._initialized = True def play_frequence( - self, - frequence, - duration, - adjust_volume=0.0, - interrupt=True): + self, frequence, duration, adjust_volume=0.0, interrupt=True + ): + """Play a tone at the specified frequency. + + Args: + frequence (float): Frequency in Hz + duration (float): Duration in seconds + adjust_volume (float): Volume adjustment + interrupt (bool): Whether to interrupt current sound + """ if not self._initialized: return if interrupt: @@ -43,42 +76,54 @@ class driver(sound_driver): popen_frequence_command = shlex.split(self.frequenceCommand) for idx, word in enumerate(popen_frequence_command): word = word.replace( - 'fenrirVolume', str( - self.volume * adjust_volume)) - word = word.replace('fenrirDuration', str(duration)) - word = word.replace('fenrirFrequence', str(frequence)) + "fenrirVolume", str(self.volume * adjust_volume) + ) + word = word.replace("fenrirDuration", str(duration)) + word = word.replace("fenrirFrequence", str(frequence)) popen_frequence_command[idx] = word self.proc = subprocess.Popen( popen_frequence_command, stdin=None, stdout=None, stderr=None, - shell=False) - self.soundType = 'frequence' + shell=False, + ) + self.soundType = "frequence" def play_sound_file(self, file_path, interrupt=True): + """Play a sound file. + + Args: + file_path (str): Path to the sound file to play + interrupt (bool): Whether to interrupt current sound + """ if not self._initialized: return if interrupt: self.cancel() # Validate file path to prevent injection import os - if not os.path.isfile(file_path) or '..' in file_path: + + if not os.path.isfile(file_path) or ".." in file_path: return popen_sound_file_command = shlex.split(self.soundFileCommand) for idx, word in enumerate(popen_sound_file_command): - word = word.replace('fenrirVolume', str(self.volume)) - word = word.replace('fenrirSoundFile', shlex.quote(str(file_path))) + word = word.replace("fenrirVolume", str(self.volume)) + word = word.replace("fenrirSoundFile", shlex.quote(str(file_path))) popen_sound_file_command[idx] = word self.proc = subprocess.Popen(popen_sound_file_command, shell=False) - self.soundType = 'file' + self.soundType = "file" def cancel(self): + """Cancel currently playing sound. + + Terminates the subprocess playing sound and cleans up resources. + """ if not self._initialized: return - if self.soundType == '': + if self.soundType == "": return - if self.soundType == 'file': + if self.soundType == "file": self.proc.kill() try: # Wait for process to finish to prevent zombies @@ -87,7 +132,7 @@ class driver(sound_driver): pass # Process already terminated except Exception as e: pass # Handle any other wait errors - if self.soundType == 'frequence': + if self.soundType == "frequence": self.proc.kill() try: # Wait for process to finish to prevent zombies @@ -96,4 +141,4 @@ class driver(sound_driver): pass # Process already terminated except Exception as e: pass # Handle any other wait errors - self.soundType = '' + self.soundType = "" diff --git a/src/fenrirscreenreader/soundDriver/gstreamerDriver.py b/src/fenrirscreenreader/soundDriver/gstreamerDriver.py index 722d7bb8..8889cd12 100644 --- a/src/fenrirscreenreader/soundDriver/gstreamerDriver.py +++ b/src/fenrirscreenreader/soundDriver/gstreamerDriver.py @@ -2,19 +2,22 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import threading +import time from fenrirscreenreader.core import debug -import time -import threading from fenrirscreenreader.core.soundDriver import sound_driver _gstreamerAvailable = False try: import gi from gi.repository import GLib - gi.require_version('Gst', '1.0') + + gi.require_version("Gst", "1.0") from gi.repository import Gst + _gstreamerAvailable, args = Gst.init_check(None) except Exception as e: _gstreamerAvailable = False @@ -33,21 +36,23 @@ class driver(sound_driver): self._initialized = _gstreamerAvailable if not self._initialized: global _availableError - self.environment['runtime']['DebugManager'].write_debug_out( - 'Gstreamer not available ' + _availableError, debug.DebugLevel.ERROR) + self.environment["runtime"]["DebugManager"].write_debug_out( + "Gstreamer not available " + _availableError, + debug.DebugLevel.ERROR, + ) return - self._player = Gst.ElementFactory.make('playbin', 'player') + self._player = Gst.ElementFactory.make("playbin", "player") bus = self._player.get_bus() bus.add_signal_watch() bus.connect("message", self._on_player_message) - self._pipeline = Gst.Pipeline(name='fenrir-pipeline') + self._pipeline = Gst.Pipeline(name="fenrir-pipeline") bus = self._pipeline.get_bus() bus.add_signal_watch() bus.connect("message", self._on_pipeline_message) - self._source = Gst.ElementFactory.make('audiotestsrc', 'src') - self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') + self._source = Gst.ElementFactory.make("audiotestsrc", "src") + self._sink = Gst.ElementFactory.make("autoaudiosink", "output") self._pipeline.add(self._source) self._pipeline.add(self._sink) self._source.link(self._sink) @@ -61,7 +66,7 @@ class driver(sound_driver): self.cancel() self.mainloop.quit() # Wait for the GLib MainLoop thread to finish to prevent shutdown races - if hasattr(self, 'thread') and self.thread.is_alive(): + if hasattr(self, "thread") and self.thread.is_alive(): # 2 second timeout to prevent hanging self.thread.join(timeout=2.0) @@ -73,9 +78,10 @@ class driver(sound_driver): elif message.type == Gst.MessageType.ERROR: self._player.set_state(Gst.State.NULL) error, info = message.parse_error() - self.env['runtime']['DebugManager'].write_debug_out( - 'GSTREAMER: _on_player_message' + str(error) + str(info), - debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "GSTREAMER: _on_player_message" + str(error) + str(info), + debug.DebugLevel.WARNING, + ) def _on_pipeline_message(self, bus, message): if not self._initialized: @@ -85,9 +91,10 @@ class driver(sound_driver): elif message.type == Gst.MessageType.ERROR: self._pipeline.set_state(Gst.State.NULL) error, info = message.parse_error() - self.env['runtime']['DebugManager'].write_debug_out( - 'GSTREAMER: _on_pipeline_message' + str(error) + str(info), - debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "GSTREAMER: _on_pipeline_message" + str(error) + str(info), + debug.DebugLevel.WARNING, + ) def _on_timeout(self, element): if not self._initialized: @@ -99,23 +106,20 @@ class driver(sound_driver): return if interrupt: self.cancel() - self._player.set_property('volume', self.volume) - self._player.set_property('uri', 'file://%s' % file_name) + self._player.set_property("volume", self.volume) + self._player.set_property("uri", "file://%s" % file_name) self._player.set_state(Gst.State.PLAYING) def play_frequence( - self, - frequence, - duration, - adjust_volume=0.0, - interrupt=True): + self, frequence, duration, adjust_volume=0.0, interrupt=True + ): if not self._initialized: return if interrupt: self.cancel() duration = duration * 1000 - self._source.set_property('volume', self.volume * adjust_volume) - self._source.set_property('freq', frequence) + self._source.set_property("volume", self.volume * adjust_volume) + self._source.set_property("freq", frequence) self._pipeline.set_state(Gst.State.PLAYING) GLib.timeout_add(duration, self._on_timeout, self._pipeline) diff --git a/src/fenrirscreenreader/speechDriver/debugDriver.py b/src/fenrirscreenreader/speechDriver/debugDriver.py index defaf016..baf92e48 100644 --- a/src/fenrirscreenreader/speechDriver/debugDriver.py +++ b/src/fenrirscreenreader/speechDriver/debugDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # generic driver from fenrirscreenreader.core import debug @@ -10,67 +10,126 @@ from fenrirscreenreader.core.speechDriver import speech_driver class driver(speech_driver): + """Debug speech driver for Fenrir development and testing. + + This driver provides speech output to console/debug output instead of + actual audio, making it useful for development, testing, and debugging + scenarios where audio output is not needed or available. + + All speech operations are logged to console with descriptive messages, + allowing developers to trace speech behavior without audio hardware. + """ def __init__(self): speech_driver.__init__(self) def initialize(self, environment): + """Initialize the debug speech driver. + + Args: + environment: Fenrir environment dictionary + """ self._is_initialized = True self.env = environment - print('Speech Debug Driver: Iitialized') + print("Speech Debug Driver: Initialized") def shutdown(self): + """Shutdown the debug speech driver.""" if self._is_initialized: self.cancel() self._is_initialized = False - print('Speech Debug Driver: Shutdown') + print("Speech Debug Driver: Shutdown") def speak(self, text, queueable=True, ignore_punctuation=False): + """Output speech text to console for debugging. + + Args: + text (str): Text to speak + queueable (bool): Whether speech can be queued + ignore_punctuation (bool): Whether to ignore punctuation + """ if not self._is_initialized: return if not queueable: self.cancel() - print('Speech Debug Driver: Speak:' + text) - print('Speech Debug Driver: -----------------------------------') + print("Speech Debug Driver: Speak:" + text) + print("Speech Debug Driver: -----------------------------------") def cancel(self): + """Log speech cancellation to console.""" if not self._is_initialized: return - print('Speech Debug Driver: Cancel') + print("Speech Debug Driver: Cancel") def set_callback(self, callback): - print('Speech Debug Driver: set_callback') + """Log callback setting to console. + + Args: + callback: Callback function (logged but not used) + """ + print("Speech Debug Driver: set_callback") def clear_buffer(self): + """Log buffer clearing to console.""" if not self._is_initialized: return - print('Speech Debug Driver: clear_buffer') + print("Speech Debug Driver: clear_buffer") def set_voice(self, voice): + """Log voice setting to console. + + Args: + voice: Voice setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_voice:' + str(voice)) + print("Speech Debug Driver: set_voice:" + str(voice)) def set_pitch(self, pitch): + """Log pitch setting to console. + + Args: + pitch: Pitch setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_pitch:' + str(pitch)) + print("Speech Debug Driver: set_pitch:" + str(pitch)) def set_rate(self, rate): + """Log rate setting to console. + + Args: + rate: Rate setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_rate:' + str(rate)) + print("Speech Debug Driver: set_rate:" + str(rate)) def set_module(self, module): + """Log module setting to console. + + Args: + module: Module setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_module:' + str(module)) + print("Speech Debug Driver: set_module:" + str(module)) def set_language(self, language): + """Log language setting to console. + + Args: + language: Language setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_language:' + str(language)) + print("Speech Debug Driver: set_language:" + str(language)) def set_volume(self, volume): + """Log volume setting to console. + + Args: + volume: Volume setting (logged but not used) + """ if not self._is_initialized: return - print('Speech Debug Driver: set_volume:' + str(volume)) + print("Speech Debug Driver: set_volume:" + str(volume)) diff --git a/src/fenrirscreenreader/speechDriver/dummyDriver.py b/src/fenrirscreenreader/speechDriver/dummyDriver.py index e23680c7..72bf61d9 100644 --- a/src/fenrirscreenreader/speechDriver/dummyDriver.py +++ b/src/fenrirscreenreader/speechDriver/dummyDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # generic driver from fenrirscreenreader.core import debug diff --git a/src/fenrirscreenreader/speechDriver/genericDriver.py b/src/fenrirscreenreader/speechDriver/genericDriver.py index dd2707df..ed2acda2 100644 --- a/src/fenrirscreenreader/speechDriver/genericDriver.py +++ b/src/fenrirscreenreader/speechDriver/genericDriver.py @@ -2,15 +2,18 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # generic driver -from fenrirscreenreader.core import debug -from threading import Thread, Lock -from queue import Queue, Empty import shlex -from subprocess import Popen import subprocess +from queue import Empty +from queue import Queue +from subprocess import Popen +from threading import Lock +from threading import Thread + +from fenrirscreenreader.core import debug from fenrirscreenreader.core.speechDriver import speech_driver @@ -33,22 +36,29 @@ class driver(speech_driver): def initialize(self, environment): self.env = environment - self.minVolume = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMinVolume') - self.maxVolume = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMaxVolume') - self.minPitch = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMinPitch') - self.maxPitch = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMaxPitch') - self.minRate = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMinRate') - self.maxRate = self.env['runtime']['SettingsManager'].get_setting_as_int( - 'speech', 'fenrirMaxRate') + self.minVolume = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMinVolume") + self.maxVolume = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMaxVolume") + self.minPitch = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMinPitch") + self.maxPitch = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMaxPitch") + self.minRate = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMinRate") + self.maxRate = self.env["runtime"][ + "SettingsManager" + ].get_setting_as_int("speech", "fenrirMaxRate") - self.speechCommand = self.env['runtime']['SettingsManager'].get_setting( - 'speech', 'genericSpeechCommand') - if self.speechCommand == '': + self.speechCommand = self.env["runtime"][ + "SettingsManager" + ].get_setting("speech", "genericSpeechCommand") + if self.speechCommand == "": self.speechCommand = 'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice -- "fenrirText"' if False: # for debugging overwrite here # self.speechCommand = 'spd-say --wait -r 100 -i 100 "fenrirText"' @@ -70,13 +80,13 @@ class driver(speech_driver): if not queueable: self.cancel() utterance = { - 'text': text, - 'volume': self.volume, - 'rate': self.rate, - 'pitch': self.pitch, - 'module': self.module, - 'language': self.language, - 'voice': self.voice, + "text": text, + "volume": self.volume, + "rate": self.rate, + "pitch": self.pitch, + "module": self.module, + "language": self.language, + "voice": self.voice, } self.textQueue.put(utterance.copy()) @@ -97,22 +107,26 @@ class driver(speech_driver): self.proc.kill() self.proc.wait(timeout=1.0) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'speech_driver:Cancel:self.proc.terminate():' + str(e), debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "speech_driver:Cancel:self.proc.terminate():" + str(e), + debug.DebugLevel.WARNING, + ) try: self.proc.kill() # Wait after kill to prevent zombies self.proc.wait(timeout=1.0) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'speech_driver:Cancel:self.proc.kill():' + str(e), debug.DebugLevel.WARNING) + self.env["runtime"]["DebugManager"].write_debug_out( + "speech_driver:Cancel:self.proc.kill():" + str(e), + debug.DebugLevel.WARNING, + ) self.proc = None finally: # Ensure lock is always released, even if process termination fails self.lock.release() def set_callback(self, callback): - print('SpeechDummyDriver: set_callback') + print("SpeechDummyDriver: set_callback") def clear_buffer(self): if not self._is_initialized: @@ -127,8 +141,9 @@ class driver(speech_driver): def set_pitch(self, pitch): if not self._is_initialized: return - self.pitch = str(self.minPitch + pitch * - (self.maxPitch - self.minPitch)) + self.pitch = str( + self.minPitch + pitch * (self.maxPitch - self.minPitch) + ) def set_rate(self, rate): if not self._is_initialized: @@ -148,8 +163,9 @@ class driver(speech_driver): def set_volume(self, volume): if not self._is_initialized: return - self.volume = str(self.minVolume + volume * - (self.maxVolume - self.minVolume)) + self.volume = str( + self.minVolume + volume * (self.maxVolume - self.minVolume) + ) def worker(self): while True: @@ -163,68 +179,73 @@ class driver(speech_driver): elif not isinstance(utterance, dict): continue # no text means nothing to speak - if 'text' not in utterance: + if "text" not in utterance: continue - if not isinstance(utterance['text'], str): + if not isinstance(utterance["text"], str): continue - if utterance['text'] == '': + if utterance["text"] == "": continue # check for valid data fields - if 'volume' not in utterance: - utterance['volume'] = '' - if not isinstance(utterance['volume'], str): - utterance['volume'] = '' - if 'module' not in utterance: - utterance['module'] = '' - if not isinstance(utterance['module'], str): - utterance['module'] = '' - if 'language' not in utterance: - utterance['language'] = '' - if not isinstance(utterance['language'], str): - utterance['language'] = '' - if 'voice' not in utterance: - utterance['voice'] = '' - if not isinstance(utterance['voice'], str): - utterance['voice'] = '' - if 'pitch' not in utterance: - utterance['pitch'] = '' - if not isinstance(utterance['pitch'], str): - utterance['pitch'] = '' - if 'rate' not in utterance: - utterance['rate'] = '' - if not isinstance(utterance['rate'], str): - utterance['rate'] = '' + if "volume" not in utterance: + utterance["volume"] = "" + if not isinstance(utterance["volume"], str): + utterance["volume"] = "" + if "module" not in utterance: + utterance["module"] = "" + if not isinstance(utterance["module"], str): + utterance["module"] = "" + if "language" not in utterance: + utterance["language"] = "" + if not isinstance(utterance["language"], str): + utterance["language"] = "" + if "voice" not in utterance: + utterance["voice"] = "" + if not isinstance(utterance["voice"], str): + utterance["voice"] = "" + if "pitch" not in utterance: + utterance["pitch"] = "" + if not isinstance(utterance["pitch"], str): + utterance["pitch"] = "" + if "rate" not in utterance: + utterance["rate"] = "" + if not isinstance(utterance["rate"], str): + utterance["rate"] = "" popen_speech_command = shlex.split(self.speechCommand) for idx, word in enumerate(popen_speech_command): - word = word.replace('fenrirVolume', str(utterance['volume'])) - word = word.replace('fenrirModule', str(utterance['module'])) + word = word.replace("fenrirVolume", str(utterance["volume"])) + word = word.replace("fenrirModule", str(utterance["module"])) word = word.replace( - 'fenrirLanguage', str( - utterance['language'])) - word = word.replace('fenrirVoice', str(utterance['voice'])) - word = word.replace('fenrirPitch', str(utterance['pitch'])) - word = word.replace('fenrirRate', str(utterance['rate'])) + "fenrirLanguage", str(utterance["language"]) + ) + word = word.replace("fenrirVoice", str(utterance["voice"])) + word = word.replace("fenrirPitch", str(utterance["pitch"])) + word = word.replace("fenrirRate", str(utterance["rate"])) # Properly quote text to prevent command injection - word = word.replace('fenrirText', - shlex.quote(str(utterance['text']))) + word = word.replace( + "fenrirText", shlex.quote(str(utterance["text"])) + ) popen_speech_command[idx] = word try: - self.env['runtime']['DebugManager'].write_debug_out( - 'speech_driver:worker:' + ' '.join(popen_speech_command), debug.DebugLevel.INFO) + self.env["runtime"]["DebugManager"].write_debug_out( + "speech_driver:worker:" + " ".join(popen_speech_command), + debug.DebugLevel.INFO, + ) self.lock.acquire(True) self.proc = Popen( popen_speech_command, stdin=None, stdout=None, stderr=None, - shell=False) + shell=False, + ) self.lock.release() self.proc.wait() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'speech_driver:worker:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "speech_driver:worker:" + str(e), debug.DebugLevel.ERROR + ) self.lock.acquire(True) self.proc = None diff --git a/src/fenrirscreenreader/speechDriver/speechdDriver.py b/src/fenrirscreenreader/speechDriver/speechdDriver.py index 92da1d80..fb113d62 100644 --- a/src/fenrirscreenreader/speechDriver/speechdDriver.py +++ b/src/fenrirscreenreader/speechDriver/speechdDriver.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. # speech-dispatcher driver from fenrirscreenreader.core import debug @@ -10,33 +10,71 @@ from fenrirscreenreader.core.speechDriver import speech_driver class driver(speech_driver): + """Speech-dispatcher driver for Fenrir screen reader. + + This driver provides text-to-speech functionality through speech-dispatcher, + which acts as a common interface to various TTS engines. It supports voice + selection, speech parameters (rate, pitch, volume), and multiple TTS modules. + + Features: + - Dynamic voice switching and parameter adjustment + - Support for multiple speech-dispatcher modules (espeak, festival, etc.) + - Real-time speech cancellation and queueing + - Language and voice selection + - Speech callbacks for synchronization + + Attributes: + _sd: Speech-dispatcher client connection + language (str): Current speech language + voice (str): Current voice name + module (str): Current TTS module name + """ def __init__(self): speech_driver.__init__(self) def initialize(self, environment): + """Initialize the speech-dispatcher connection. + + Establishes connection to speech-dispatcher daemon and configures + initial speech parameters. Sets up callbacks and prepares the + speech subsystem for use. + + Args: + environment: Fenrir environment dictionary with settings and managers + + Note: + Gracefully handles cases where speech-dispatcher is not available. + """ self._sd = None self.env = environment self._is_initialized = False # Only set these if they haven't been set yet (preserve existing # values) - if not hasattr(self, 'language') or self.language is None: - self.language = '' - if not hasattr(self, 'voice') or self.voice is None: - self.voice = '' - if not hasattr(self, 'module') or self.module is None: - self.module = '' + if not hasattr(self, "language") or self.language is None: + self.language = "" + if not hasattr(self, "voice") or self.voice is None: + self.voice = "" + if not hasattr(self, "module") or self.module is None: + self.module = "" try: import speechd - self._sd = speechd.SSIPClient('fenrir-dev') + + self._sd = speechd.SSIPClient("fenrir-dev") self._punct = speechd.PunctuationMode() self._is_initialized = True except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver initialize:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver initialize:" + str(e), debug.DebugLevel.ERROR + ) def shutdown(self): + """Shutdown the speech-dispatcher connection. + + Cleanly closes the connection to speech-dispatcher and releases + any allocated resources. + """ if not self._is_initialized: return self.cancel() @@ -47,6 +85,16 @@ class driver(speech_driver): self._is_initialized = False def speak(self, text, queueable=True, ignore_punctuation=False): + """Speak the given text through speech-dispatcher. + + Args: + text (str): Text to speak + queueable (bool): Whether speech can be queued with other speech + ignore_punctuation (bool): Whether to ignore punctuation settings + + Note: + Handles text preprocessing and manages speech queue based on parameters. + """ if not queueable: self.cancel() if not self._is_initialized: @@ -57,25 +105,28 @@ class driver(speech_driver): return try: - if self.module != '': + if self.module != "": self._sd.set_output_module(self.module) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_module:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_module:" + str(e), debug.DebugLevel.ERROR + ) try: - if self.language != '': + if self.language != "": self._sd.set_language(self.language) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_language:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_language:" + str(e), debug.DebugLevel.ERROR + ) try: - if self.voice != '': + if self.voice != "": self._sd.set_synthesis_voice(self.voice) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_voice:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_voice:" + str(e), debug.DebugLevel.ERROR + ) try: if ignore_punctuation: @@ -83,17 +134,24 @@ class driver(speech_driver): else: self._sd.set_punctuation(self._punct.NONE) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_punctuation:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_punctuation:" + str(e), + debug.DebugLevel.ERROR, + ) try: self._sd.speak(text) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver speak:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver speak:" + str(e), debug.DebugLevel.ERROR + ) self._is_initialized = False def cancel(self): + """Cancel all pending and current speech. + + Immediately stops speech output and clears the speech queue. + """ if not self._is_initialized: self.initialize(self.env) if not self._is_initialized: @@ -101,33 +159,52 @@ class driver(speech_driver): try: self._sd.cancel() except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver cancel:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver cancel:" + str(e), debug.DebugLevel.ERROR + ) self._is_initialized = False def set_pitch(self, pitch): + """Set the speech pitch. + + Args: + pitch (float): Speech pitch (0.0 to 1.0, where 0.5 is normal) + """ if not self._is_initialized: return try: self._sd.set_pitch(int(-100 + pitch * 200)) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_pitch:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_pitch:" + str(e), debug.DebugLevel.ERROR + ) def set_rate(self, rate): + """Set the speech rate. + + Args: + rate (float): Speech rate (0.0 to 1.0, where 0.5 is normal) + """ if not self._is_initialized: return try: self._sd.set_rate(int(-100 + rate * 200)) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_rate:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_rate:" + str(e), debug.DebugLevel.ERROR + ) def set_volume(self, volume): + """Set the speech volume. + + Args: + volume (float): Volume level (0.0 to 1.0) + """ if not self._is_initialized: return try: self._sd.set_volume(int(-100 + volume * 200)) except Exception as e: - self.env['runtime']['DebugManager'].write_debug_out( - 'SpeechDriver set_volume:' + str(e), debug.DebugLevel.ERROR) + self.env["runtime"]["DebugManager"].write_debug_out( + "SpeechDriver set_volume:" + str(e), debug.DebugLevel.ERROR + ) diff --git a/src/fenrirscreenreader/utils/char_utils.py b/src/fenrirscreenreader/utils/char_utils.py index bef49d3e..f1b92b33 100644 --- a/src/fenrirscreenreader/utils/char_utils.py +++ b/src/fenrirscreenreader/utils/char_utils.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug @@ -10,9 +10,9 @@ from fenrirscreenreader.core import debug def get_prev_char(curr_x, curr_y, curr_text): line_break = False end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen, line_break - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen, line_break + wrapped_lines = curr_text.split("\n") x = curr_x y = curr_y if x - 1 < 0: @@ -25,31 +25,31 @@ def get_prev_char(curr_x, curr_y, curr_text): end_of_screen = True else: x -= 1 - curr_char = '' + curr_char = "" if not end_of_screen: curr_char = wrapped_lines[y][x] return x, y, curr_char, end_of_screen, line_break def get_current_char(curr_x, curr_y, curr_text): - if curr_text == '': - return -1, -1, '' - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "" + wrapped_lines = curr_text.split("\n") curr_char = wrapped_lines[curr_y][curr_x] return curr_x, curr_y, curr_char def get_up_char(curr_x, curr_y, curr_text): end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen + wrapped_lines = curr_text.split("\n") curr_y -= 1 if curr_y < 0: curr_y = 0 else: end_of_screen = True - curr_char = '' + curr_char = "" if not end_of_screen: curr_char = wrapped_lines[curr_y][curr_x] return curr_x, curr_y, curr_char, end_of_screen @@ -57,15 +57,15 @@ def get_up_char(curr_x, curr_y, curr_text): def get_down_char(curr_x, curr_y, curr_text): end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen + wrapped_lines = curr_text.split("\n") curr_y += 1 if curr_y >= len(wrapped_lines): curr_y = len(wrapped_lines) - 1 else: end_of_screen = True - curr_char = '' + curr_char = "" if not end_of_screen: curr_char = wrapped_lines[curr_y][curr_x] return curr_x, curr_y, curr_char, end_of_screen @@ -73,9 +73,9 @@ def get_down_char(curr_x, curr_y, curr_text): def get_last_char_in_line(curr_y, curr_text): end_of_screen = False - if curr_text == '': - return -1, -1, '' - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "" + wrapped_lines = curr_text.split("\n") curr_x = len(wrapped_lines[curr_y].rstrip()) - 1 if curr_x < 0: curr_x = 0 @@ -86,9 +86,9 @@ def get_last_char_in_line(curr_y, curr_text): def get_next_char(curr_x, curr_y, curr_text): line_break = False end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen, line_break - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen, line_break + wrapped_lines = curr_text.split("\n") x = curr_x y = curr_y if x + 1 == len(wrapped_lines[y]): @@ -101,7 +101,7 @@ def get_next_char(curr_x, curr_y, curr_text): end_of_screen = True else: x += 1 - curr_char = '' + curr_char = "" if not end_of_screen: curr_char = wrapped_lines[y][x] @@ -112,12 +112,32 @@ def get_phonetic(curr_char): if len(curr_char) != 1: return curr_char phonetics_dict = { - "A": "alpha", "B": "bravo", "C": "charlie", "D": "delta", "E": "echo", - "F": "foxtrot", "G": "golf", "H": "hotel", "I": "india", "J": "juliet", - "K": "kilo", "L": "lima", "M": "mike", "N": "november", "O": "oscar", - "P": "papa", "Q": "quebec", "R": "romeo", "S": "sierra", "T": "tango", - "U": "uniform", "V": "victor", "W": "whisky", "X": "x ray", - "Y": "yankee", "Z": "zulu" + "A": "alpha", + "B": "bravo", + "C": "charlie", + "D": "delta", + "E": "echo", + "F": "foxtrot", + "G": "golf", + "H": "hotel", + "I": "india", + "J": "juliet", + "K": "kilo", + "L": "lima", + "M": "mike", + "N": "november", + "O": "oscar", + "P": "papa", + "Q": "quebec", + "R": "romeo", + "S": "sierra", + "T": "tango", + "U": "uniform", + "V": "victor", + "W": "whisky", + "X": "x ray", + "Y": "yankee", + "Z": "zulu", } try: phon_char = phonetics_dict[curr_char.upper()] @@ -130,23 +150,22 @@ def get_phonetic(curr_char): def present_char_for_review( - env, - char, - interrupt=True, - announce_capital=True, - flush=False): + env, char, interrupt=True, announce_capital=True, flush=False +): """Present a character for explicit review commands only""" - if char == ' ': - if ' ' in env['punctuation']['PUNCTDICT']: - announce_char = env['punctuation']['PUNCTDICT'][' '] + if char == " ": + if " " in env["punctuation"]["PUNCTDICT"]: + announce_char = env["punctuation"]["PUNCTDICT"][" "] else: - announce_char = 'space' - env['runtime']['OutputManager'].present_text( - announce_char, interrupt=interrupt, flush=flush) + announce_char = "space" + env["runtime"]["OutputManager"].present_text( + announce_char, interrupt=interrupt, flush=flush + ) else: - env['runtime']['OutputManager'].present_text( + env["runtime"]["OutputManager"].present_text( char, interrupt=interrupt, ignore_punctuation=True, announce_capital=announce_capital, - flush=flush) + flush=flush, + ) diff --git a/src/fenrirscreenreader/utils/fenrir-config.py b/src/fenrirscreenreader/utils/fenrir-config.py index 455bca6e..dbe68ead 100644 --- a/src/fenrirscreenreader/utils/fenrir-config.py +++ b/src/fenrirscreenreader/utils/fenrir-config.py @@ -3,9 +3,11 @@ import configparser import os import sys -from os import listdir -from os.path import isfile, join from inspect import isfunction +from os import listdir +from os.path import isfile +from os.path import join + from xdg import BaseDirectory # Get configuration directory diff --git a/src/fenrirscreenreader/utils/line_utils.py b/src/fenrirscreenreader/utils/line_utils.py index 694e95da..cf508bae 100644 --- a/src/fenrirscreenreader/utils/line_utils.py +++ b/src/fenrirscreenreader/utils/line_utils.py @@ -2,16 +2,16 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug def get_prev_line(curr_x, curr_y, curr_text): end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen + wrapped_lines = curr_text.split("\n") x = curr_x y = curr_y if y - 1 >= 0: @@ -19,16 +19,16 @@ def get_prev_line(curr_x, curr_y, curr_text): else: end_of_screen = True x = curr_x - curr_line = '' + curr_line = "" if not end_of_screen: curr_line = wrapped_lines[y] return x, y, curr_line, end_of_screen def get_current_line(curr_x, curr_y, curr_text): - if curr_text == '': - return -1, -1, '' - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "" + wrapped_lines = curr_text.split("\n") x = curr_x y = curr_y x = 0 @@ -38,9 +38,9 @@ def get_current_line(curr_x, curr_y, curr_text): def get_next_line(curr_x, curr_y, curr_text): end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen - wrapped_lines = curr_text.split('\n') + if curr_text == "": + return -1, -1, "", end_of_screen + wrapped_lines = curr_text.split("\n") x = curr_x y = curr_y if y + 1 < len(wrapped_lines): @@ -48,7 +48,7 @@ def get_next_line(curr_x, curr_y, curr_text): else: end_of_screen = True x = curr_x - curr_line = '' + curr_line = "" if not end_of_screen: curr_line = wrapped_lines[y] return x, y, curr_line, end_of_screen diff --git a/src/fenrirscreenreader/utils/mark_utils.py b/src/fenrirscreenreader/utils/mark_utils.py index 1f561a9b..ec525cec 100644 --- a/src/fenrirscreenreader/utils/mark_utils.py +++ b/src/fenrirscreenreader/utils/mark_utils.py @@ -2,66 +2,68 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug def get_text_between_marks(firstMark, secondMark, in_text): if in_text is None: - return '' + return "" if not isinstance(in_text, list): - in_text = in_text.split('\n') + in_text = in_text.split("\n") if len(in_text) < 1: - return '' + return "" if firstMark is None: - return '' + return "" if secondMark is None: - return '' - if (firstMark['y'] + 1) * (firstMark['x'] + - 1) <= (secondMark['y'] + 1) * (secondMark['x'] + 1): + return "" + if (firstMark["y"] + 1) * (firstMark["x"] + 1) <= (secondMark["y"] + 1) * ( + secondMark["x"] + 1 + ): start_mark = firstMark.copy() end_mark = secondMark.copy() else: end_mark = firstMark.copy() start_mark = secondMark.copy() - text_part = '' - if start_mark['y'] == end_mark['y']: - text_part += in_text[start_mark['y']][start_mark['x']:end_mark['x'] + 1] + text_part = "" + if start_mark["y"] == end_mark["y"]: + text_part += in_text[start_mark["y"]][ + start_mark["x"] : end_mark["x"] + 1 + ] else: - curr_y = start_mark['y'] - while curr_y <= end_mark['y']: - if curr_y < end_mark['y']: - if curr_y == start_mark['y']: - text_part += in_text[curr_y][start_mark['x']:] + curr_y = start_mark["y"] + while curr_y <= end_mark["y"]: + if curr_y < end_mark["y"]: + if curr_y == start_mark["y"]: + text_part += in_text[curr_y][start_mark["x"] :] else: text_part += in_text[curr_y] if len(in_text[curr_y].strip()) != 0: if len(text_part) - len(text_part.rstrip()) > 0: - text_part = text_part[:len(text_part.rstrip())] + "\n" + text_part = text_part[: len(text_part.rstrip())] + "\n" else: - text_part += '\n' + text_part += "\n" else: - text_part += in_text[curr_y][:end_mark['x'] + 1] + text_part += in_text[curr_y][: end_mark["x"] + 1] curr_y += 1 return text_part def get_text_before_mark(mark, in_text): if in_text is None: - return '' + return "" if mark is None: - return '' - return get_text_between_marks({'x': 0, 'y': 0}, mark, in_text) + return "" + return get_text_between_marks({"x": 0, "y": 0}, mark, in_text) def get_text_after_mark(mark, in_text): if in_text is None: - return '' + return "" if mark is None: - return '' - in_text = in_text.split('\n') + return "" + in_text = in_text.split("\n") return get_text_between_marks( - mark, { - 'x': len( - in_text[0]) - 1, 'y': len(in_text) - 1}, in_text) + mark, {"x": len(in_text[0]) - 1, "y": len(in_text) - 1}, in_text + ) diff --git a/src/fenrirscreenreader/utils/module_utils.py b/src/fenrirscreenreader/utils/module_utils.py index 2107397b..c0e55d49 100644 --- a/src/fenrirscreenreader/utils/module_utils.py +++ b/src/fenrirscreenreader/utils/module_utils.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. import sys + version = sys.version[:3] # we only need major.minor version. if version in ["3.3", "3.4"]: from importlib.machinery import SourceFileLoader @@ -15,7 +16,8 @@ def import_module(moduleName, moduleLocation): return SourceFileLoader(moduleName, moduleLocation).load_module() else: spec = importlib.util.spec_from_file_location( - moduleName, moduleLocation) + moduleName, moduleLocation + ) driver_mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(driver_mod) return driver_mod diff --git a/src/fenrirscreenreader/utils/review_utils.py b/src/fenrirscreenreader/utils/review_utils.py index cde145bd..4dcb61a6 100644 --- a/src/fenrirscreenreader/utils/review_utils.py +++ b/src/fenrirscreenreader/utils/review_utils.py @@ -2,6 +2,6 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug diff --git a/src/fenrirscreenreader/utils/screen_utils.py b/src/fenrirscreenreader/utils/screen_utils.py index dfc58911..8810ef94 100644 --- a/src/fenrirscreenreader/utils/screen_utils.py +++ b/src/fenrirscreenreader/utils/screen_utils.py @@ -2,54 +2,57 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import getpass +import os +import string +import time +from select import select from fenrirscreenreader.core import debug -import getpass -import time -import string -import os -from select import select def remove_nonprintable(text): # Get the difference of all ASCII characters from the set of printable # characters - nonprintable = set([chr(i) for i in range(128)] - ).difference(string.printable) + nonprintable = set([chr(i) for i in range(128)]).difference( + string.printable + ) # Use translate to remove all non-printable characters return text.translate({ord(character): None for character in nonprintable}) def insert_newlines(string, every=64): - return '\n'.join(string[i:i + every] for i in range(0, len(string), every)) + return "\n".join( + string[i : i + every] for i in range(0, len(string), every) + ) def split_every(toSplit, every=64): - return list(toSplit[i:i + every] for i in range(0, len(toSplit), every)) + return list(toSplit[i : i + every] for i in range(0, len(toSplit), every)) def create_screen_event_data(content): event_data = { - 'bytes': content, - 'lines': content['lines'], - 'columns': content['columns'], - 'textCursor': - { - 'x': int(content['cursor'][0]), - 'y': int(content['cursor'][1]) + "bytes": content, + "lines": content["lines"], + "columns": content["columns"], + "textCursor": { + "x": int(content["cursor"][0]), + "y": int(content["cursor"][1]), }, - 'screen': content['screen'], - 'text': content['text'], - 'attributes': content['attributes'], - 'screenUpdateTime': time.time(), + "screen": content["screen"], + "text": content["text"], + "attributes": content["attributes"], + "screenUpdateTime": time.time(), } return event_data.copy() def has_more(fd, timetout=0.05): r, _, _ = select([fd], [], [], timetout) - return (fd in r) + return fd in r def has_more_what(fd_list, timetout=0.05): @@ -61,10 +64,10 @@ def has_more_what(fd_list, timetout=0.05): return r -def is_valid_shell(shell=''): +def is_valid_shell(shell=""): if not isinstance(shell, str): return False - if shell == '': + if shell == "": return False try: if not os.path.isfile(shell): @@ -73,7 +76,9 @@ def is_valid_shell(shell=''): return False except Exception as e: # Utility function, no env access - use fallback logging - print(f'screen_utils is_valid_shell: Error checking shell {shell}: {e}') + print( + f"screen_utils is_valid_shell: Error checking shell {shell}: {e}" + ) return False return True @@ -94,19 +99,20 @@ def get_shell(): # Utility function, no env access - continue silently pass try: - if os.access('/etc/passwd', os.R_OK): - with open('/etc/passwd') as f: + if os.access("/etc/passwd", os.R_OK): + with open("/etc/passwd") as f: users = f.readlines() for user in users: - (username, encrypwd, uid, gid, gecos, - homedir, shell) = user.split(':') - shell = shell.replace('\n', '') + (username, encrypwd, uid, gid, gecos, homedir, shell) = ( + user.split(":") + ) + shell = shell.replace("\n", "") if username == getpass.getuser(): if is_valid_shell(shell): return shell except Exception as e: # Utility function, no env access - continue silently pass - if is_valid_shell('/bin/bash'): - return '/bin/bash' - return '/bin/sh' + if is_valid_shell("/bin/bash"): + return "/bin/bash" + return "/bin/sh" diff --git a/src/fenrirscreenreader/utils/word_utils.py b/src/fenrirscreenreader/utils/word_utils.py index 6d4b4952..1e5d9380 100644 --- a/src/fenrirscreenreader/utils/word_utils.py +++ b/src/fenrirscreenreader/utils/word_utils.py @@ -2,26 +2,27 @@ # -*- coding: utf-8 -*- # Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. +# By Chrys, Storm Dragon, and contributors. + +import string from fenrirscreenreader.core import debug -import string def get_current_word(curr_x, curr_y, curr_text): line_break = False end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen, line_break - if curr_text.strip(string.whitespace) == '': - return curr_x, curr_y, '', end_of_screen, line_break + if curr_text == "": + return -1, -1, "", end_of_screen, line_break + if curr_text.strip(string.whitespace) == "": + return curr_x, curr_y, "", end_of_screen, line_break x = curr_x y = curr_y - curr_word = '' - wrapped_lines = curr_text.split('\n') + curr_word = "" + wrapped_lines = curr_text.split("\n") curr_line = wrapped_lines[y] found = False - while (not found): + while not found: if not curr_line[x] in string.whitespace: if x == 0: found = True @@ -33,7 +34,7 @@ def get_current_word(curr_x, curr_y, curr_text): if y - 1 < 0: line_break = False end_of_screen = True - return curr_x, curr_y, '', end_of_screen, line_break + return curr_x, curr_y, "", end_of_screen, line_break else: y -= 1 curr_line = wrapped_lines[y] @@ -48,27 +49,28 @@ def get_current_word(curr_x, curr_y, curr_text): if delimiter_pos != -1: curr_word = curr_word[:delimiter_pos] return x, y, curr_word, end_of_screen, line_break - return curr_x, curr_y, '', False, False + return curr_x, curr_y, "", False, False def get_prev_word(curr_x, curr_y, curr_text): line_break = False end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen, line_break - if curr_text.strip(string.whitespace) == '': - return curr_x, curr_y, '', end_of_screen, line_break + if curr_text == "": + return -1, -1, "", end_of_screen, line_break + if curr_text.strip(string.whitespace) == "": + return curr_x, curr_y, "", end_of_screen, line_break x, y, curr_word, end_of_screen, line_break_curr_word = get_current_word( - curr_x, curr_y, curr_text) + curr_x, curr_y, curr_text + ) if end_of_screen: return x, y, curr_word, end_of_screen, line_break - wrapped_lines = curr_text.split('\n') + wrapped_lines = curr_text.split("\n") curr_line = wrapped_lines[y] if x - 1 < 0: if y - 1 < 0: line_break = False end_of_screen = True - return curr_x, curr_y, '', end_of_screen, line_break + return curr_x, curr_y, "", end_of_screen, line_break else: y -= 1 curr_line = wrapped_lines[y] @@ -77,7 +79,9 @@ def get_prev_word(curr_x, curr_y, curr_text): else: x -= 1 line_break_curr_word = line_break or line_break_curr_word - x, y, curr_word, end_of_screen, line_break = get_current_word(x, y, curr_text) + x, y, curr_word, end_of_screen, line_break = get_current_word( + x, y, curr_text + ) line_break = line_break or line_break_curr_word return x, y, curr_word, end_of_screen, line_break @@ -85,23 +89,23 @@ def get_prev_word(curr_x, curr_y, curr_text): def get_next_word(curr_x, curr_y, curr_text): line_break = False end_of_screen = False - if curr_text == '': - return -1, -1, '', end_of_screen, line_break - if curr_text.strip(string.whitespace) == '': - return curr_x, curr_y, '', end_of_screen, line_break + if curr_text == "": + return -1, -1, "", end_of_screen, line_break + if curr_text.strip(string.whitespace) == "": + return curr_x, curr_y, "", end_of_screen, line_break x = curr_x y = curr_y - curr_word = '' - wrapped_lines = curr_text.split('\n') + curr_word = "" + wrapped_lines = curr_text.split("\n") curr_line = wrapped_lines[y] found = False - while (not found): + while not found: if not found: if x + 1 > len(curr_line) - 1: if y + 1 > len(wrapped_lines) - 1: line_break = False end_of_screen = True - return curr_x, curr_y, '', end_of_screen, line_break + return curr_x, curr_y, "", end_of_screen, line_break else: y += 1 curr_line = wrapped_lines[y] @@ -122,4 +126,4 @@ def get_next_word(curr_x, curr_y, curr_text): if delimiter_pos != -1: curr_word = curr_word[:delimiter_pos] return x, y, curr_word, end_of_screen, line_break - return curr_x, curr_y, '', False, False + return curr_x, curr_y, "", False, False