Files
fenrir/src/fenrirscreenreader/core/punctuationManager.py
2025-07-07 00:42:23 -04:00

221 lines
7.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
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())))
)
fenrir_path = os.path.dirname(currentdir)
class PunctuationManager:
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
self.allPunctNone = dict.fromkeys(
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("-"),
]:
self.allPunctNone[char] = chr(char)
def shutdown(self):
pass
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:
try:
del curr_all_punct_none[ord(char)]
except Exception as e:
pass
return text.translate(curr_all_punct_none)
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)
):
result_text = re.sub(
str(key[len(regex_lbl) :]),
seperator + str(item) + seperator,
result_text,
)
else:
result_text = result_text.replace(
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),
debug.DebugLevel.ERROR,
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:
result_text = result_text.replace(
" ", " " + 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 "',.;:?!"
):
result_text = result_text.replace(
str(key), " " + str(item) + str(key) + " "
)
else:
result_text = result_text.replace(
str(key), " " + str(item) + " "
)
return result_text
def is_puctuation(self, char):
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.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()
]
else:
curr_punct_level = string.punctuation + " §"
result_text = self.use_punctuation_dict(
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())
try:
curr_index = punct_list.index(
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()
)
return True
def load_dicts(
self,
dictConfigPath=fenrir_path + "/../../config/punctuation/default.conf",
):
dict_config = open(dictConfigPath, "r")
curr_dict_name = ""
while True:
line = dict_config.readline()
if not line:
break
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()
else:
if curr_dict_name == "":
continue
if ":===:" not in line:
continue
sep_line = line.split(":===:")
if len(sep_line) == 1:
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],
debug.DebugLevel.INFO,
on_any_level=True,
)
dict_config.close()