[orca] Verbalize punctuation for the new ARIA code role



commit 1b4b2ce40d4629f633e3227e253d755731a9cecb
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Wed Mar 25 17:02:20 2020 -0400

    Verbalize punctuation for the new ARIA code role
    
    According to the ARIA spec, for the code role screen readers should
    prefer full punctuation verbosity to ensure common symbols (e.g. "-")
    are spoken. In order to balance this with user preference, we'll only
    do this when the user has their punctuation level set to some or most,
    which suggests they are interested in relevant punctuation but have not
    explicitly turned over this work to their speech synthesizer.

 src/orca/script_utilities.py             | 25 +++++++++++++++++++++++++
 src/orca/scripts/web/script_utilities.py |  6 ++++++
 src/orca/speech_generator.py             |  6 ++++++
 3 files changed, 37 insertions(+)
---
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index d51fb4e3d..734445c04 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -81,6 +81,7 @@ class Utilities:
     WORDS_RE = re.compile(r"(\W+)", flags)
     SUPERSCRIPTS_RE = re.compile("[%s]+" % "".join(SUPERSCRIPT_DIGITS), flags)
     SUBSCRIPTS_RE = re.compile("[%s]+" % "".join(SUBSCRIPT_DIGITS), flags)
+    PUNCTUATION = re.compile(r"[^\w\s]", flags)
 
     # generatorCache
     #
@@ -740,6 +741,9 @@ class Utilities:
     def isAnchor(self, obj):
         return False
 
+    def isCode(self, obj):
+        return False
+
     def isDesktop(self, obj):
         try:
             role = obj.getRole()
@@ -3139,6 +3143,27 @@ class Utilities:
 
         return line
 
+    def shouldVerbalizeAllPunctuation(self, obj):
+        if not self.isCode(obj):
+            return False
+
+        # If the user has set their punctuation level to All, then the synthesizer will
+        # do the work for us. If the user has set their punctuation level to None, then
+        # they really don't want punctuation and we mustn't override that.
+        style = _settingsManager.getSetting("verbalizePunctuationStyle")
+        if style in [settings.PUNCTUATION_STYLE_ALL, settings.PUNCTUATION_STYLE_NONE]:
+            return False
+
+        return True
+
+    def verbalizeAllPunctuation(self, string):
+        result = string
+        for symbol in set(re.findall(self.PUNCTUATION, result)):
+            charName = " %s " % chnames.getCharacterName(symbol)
+            result = re.sub("\%s" % symbol, charName, result)
+
+        return result
+
     def adjustForLinks(self, obj, line, startOffset):
         """Adjust line to include the word "link" after any hypertext links.
 
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index a5a372067..4956bde35 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -3221,6 +3221,12 @@ class Utilities(script_utilities.Utilities):
         self._isClickableElement[hash(obj)] = rv
         return rv
 
+    def isCode(self, obj):
+        if not (obj and self.inDocumentContent(obj)):
+            return super().isCode(obj)
+
+        return self._getTag(obj) == "code" or "code" in self._getXMLRoles(obj)
+
     def isEditableDescendantOfComboBox(self, obj):
         if not (obj and self.inDocumentContent(obj)):
             return super().isEditableDescendantOfComboBox(obj)
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index cdd2848ef..25713200a 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -1185,6 +1185,9 @@ class SpeechGenerator(generator.Generator):
            and not self._script.inSayAll() and args.get('total', 1) == 1:
             result = [messages.BLANK]
 
+        if self._script.utilities.shouldVerbalizeAllPunctuation(obj):
+            result[0] = self._script.utilities.verbalizeAllPunctuation(result[0])
+
         result.extend(acss)
         return result
 
@@ -1443,6 +1446,9 @@ class SpeechGenerator(generator.Generator):
            and not self._script.inSayAll() and args.get('total', 1) == 1:
             result[0] = messages.BLANK
 
+        if self._script.utilities.shouldVerbalizeAllPunctuation(obj):
+            result[0] = self._script.utilities.verbalizeAllPunctuation(result[0])
+
         return result
 
     def _generateTextIndentation(self, obj, **args):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]