Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speak all symbols when moving by words (#11779) #11856

Merged
merged 33 commits into from Jul 7, 2021

Conversation

JulienCochuyt
Copy link
Collaborator

@JulienCochuyt JulienCochuyt commented Nov 23, 2020

Link to issue number:

Fixes #11779
Fixes #10855

Summary of the issue:

Navigation by word is inconsistent among different editors.
This might lead to different symbol announcements, or opening and closing symbols not announced consistently.

Description of how this pull request fixes the issue:

  • Add a new "symbolLevelWord" key in the "speech" config category, setting the symbol level to use when reviewing by word.
    Default: All
  • Add a new constant in characterProcessing: SYMLVL_UNCHANGED = -1
  • The Settings UI and an unassigned global command allow to toggle between "All" and "Unchanged"

Testing performed:

Played with #11779 STR in different editors.

System tests have been added to test the STR with notepad.

Known issues with pull request:

This effectively reverts PR #11167.
The reverted portion of the code would benefit from extra clean-up, as I guess there is no need to test for UNIT_WORD there anymore.

Change log entry:

Changes:

For developers:

Code Review Checklist:

  • Pull Request description is up to date.
  • Unit tests.
  • System (end to end) tests.
  • Manual testing.
  • User Documentation.
  • Change log entry.
  • Context sensitive help for GUI changes.
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers

OzancanKaratas
OzancanKaratas previously approved these changes Nov 24, 2020
Copy link
Collaborator

@OzancanKaratas OzancanKaratas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works as expected.

@CyrilleB79
Copy link
Collaborator

Sorry to comment a bit late on this topic.
I have just tested the snapshot of this PR.
Reading the following sentences (in notepad or Word) is less smooth with this PR than with 2020.3:

  • (in English) I think he'd have liked it, but he didn't.
  • (in French) Aujourd'hui, l'école n'a pas d'élèves absent.
    Indeed, the apostrophes in the words are pronounced and thus, the words are less understandable.
    Was it expected?

As an alternative, has it been considered to force symbol pronunciation only when they appear at the start of end of the word? Let's imagine the formatted word is retrieved as follows:

  1. 0 or more symbols
  2. one letter
  3. 0 or more symbol or letter
  4. one letter
  5. 0 or more symbols

Taking the word "didn't." as an example we would split it as follows:

  1. empty (0 symbol)
  2. letter "d"
  3. letters & symbols "idn'"
  4. letter "t"
  5. symbol "." (dot)

I would then suggest to ignore char pronunciation level for symbols in part 1. and 5., but not in part 3.

I know that finding a compromise on this topic is not easy. And maybe all this has already been discussed. In this case, feel free to ignore this comment and proposal.

michaelDCurran
michaelDCurran previously approved these changes Nov 25, 2020
@michaelDCurran
Copy link
Member

I think the concern around apostrophe in the middle of words when navigating by word with this pr is valid, but at the same time I don't think it is anywhere near as bad as not saying anything at all / providing an unpredictable experience. My vote would be to take this pr, but perhaps a little more discussion should be had first.

@JulienCochuyt
Copy link
Collaborator Author

@CyrilleB79, I also agree your concerns are valid.
Still, I feel the proposed change improves upon the current situation, even if in an imperfect way.
I guess it all depends on what you consider as the primary use of navigating by words.
When used to re-read a misheard word, this change might have a negative impact depending on how the editor splits by word.
When used to proof-read text, this change is IMHO a big improvement, whatever the editor.
The "re-read" use case would benefit from handling differently symbols at the boundary or in the middle of a word.
The "proof-read" use case would not.

@LeonarddeR
Copy link
Collaborator

Couldn't we make this optional? So after the punctuation/symbol level combo box, add a checkbox "Always speak all symbols when navigating by word"

@lukaszgo1
Copy link
Contributor

I wholeheartedly agree with @CyrilleB79 's comment. Making this configurable would not solve the problem he outlined IMHO and announcing symbols only at the beginnings/ends of words seems doable though certainly not as easy as what this PR implements.

@Adriani90
Copy link
Collaborator

Does this fix also #10855? If yes, then that issue should be contained in this description of the PR to make sure it will be closed once this is merged.

@JulienCochuyt
Copy link
Collaborator Author

@Adriani90 wrote:

Does this fix also #10855? If yes, then that issue should be contained in this description of the PR to make sure it will be closed once this is merged.

Good catch. Thanks!

@michaelDCurran
Copy link
Member

My vote is to speak words with symbol level of all by default, but allow the user to turn this off with an option if they must. This then means that by default, no symbols are missed, and the rule is totally predictable. With it off, the user gets the current behaviour. I think that trying to come up with rules about speaking specific symbols at the start or end of a word will then produce functionality which is confusing and more likely to break.
NV Access will merge this if this pr is made configurable and on by default.

@CyrilleB79
Copy link
Collaborator

My vote is to speak words with symbol level of all by default, but allow the user to turn this off with an option if they must. This then means that by default, no symbols are missed, and the rule is totally predictable. With it off, the user gets the current behaviour. I think that trying to come up with rules about speaking specific symbols at the start or end of a word will then produce functionality which is confusing and more likely to break.
NV Access will merge this if this pr is made configurable and on by default.

I support this solution that allows to merge this PR quickly. In a second time, another PR could be suggested after testing this one to add a third option allowing to speak punctations only at the start and ends of words.

For the current PR, I would advocate to add an unbounded gesture to be able to change quickly this verbosity option.

@JulienCochuyt
Copy link
Collaborator Author

Alternative implementation

@michaelDCurran wrote:

I think that trying to come up with rules about speaking specific symbols at the start or end of a word will then produce functionality which is confusing and more likely to break.

I agree. This would also not fully fit the "proof-read" use case, which IMHO should take priority over the "re-read" one.

Configurability

@michaelDCurran wrote:

allow the user to turn this off with an option if they must

@LeonarddeR wrote:

after the punctuation/symbol level combo box, add a checkbox "Always speak all symbols when navigating by word"

Do you all agree with adding a new regular setting in the Speech category? Or would you prefer an experimental one in the Advanced category for less intrusive removal if we come up with a better approach?

@CyrilleB79 wrote:

I would advocate to add an unbounded gesture to be able to change quickly this verbosity option.

This would IMHO orient towards a regular setting in the Speech category.

What do you think?

@CyrilleB79
Copy link
Collaborator

I agree to put this option in the speech category.
The solution to speak words with symbol level of all seems quite simple. Thus I would not expect it to land in the advanced settings.

 * New configuration setting:
     Speech > Speak all punctuations and symbols when reviewing by word
     `config.conf["speech"]["symbolLevelWord"]`
 * New constant: characterProcessing.SYMLVL_UNCHANGED = -1
@AppVeyorBot
Copy link

@JulienCochuyt
Copy link
Collaborator Author

Added configurability and unassigned global command.
Edited PR description accordingly for clarity.

@CyrilleB79
Copy link
Collaborator

Also I have had a look at the code and have noted the following comments:

  • Why are you using a 3-state checkbox for this option? It seems to me that the symbol level when navigating by word can only be unchanged or all.
  • If this is the case, the code would also be easier to read if you were using a boolean in the config; you may get rid of the "unchanged" level and do not need to store a symbol level in the config, but only the state of the option to read all symbols when navigating by words.

Is all this coded the way you did in order to support more symbol levels in the future?

@JulienCochuyt
Copy link
Collaborator Author

@CyrilleB79 wrote:

Also I have had a look at the code and have noted the following comments:
Thank you for reviewing.

  • Why are you using a 3-state checkbox for this option? It seems to me that the symbol level when navigating by word can only be unchanged or all.

The checkbox implements the high-level on/off toggling from the UI.
The third state allows the config to hold any other valid value, left unchanged when saving settings unless explicitly changed from the checkbox or the (unassigned) global command. A user won't ever be presented the third state unless it has manually edited the actual value.

  • If this is the case, the code would also be easier to read if you were using a boolean in the config; you may get rid of the "unchanged" level and do not need to store a symbol level in the config, but only the state of the option to read all symbols when navigating by words.

Actually, the implementation of the new behavior really boils down to "Use another symbol level when reviewing by word"
That is, depending on the setting, pass a symbol level or let default.
Storing a bool versus storing an int is here mapping bool to int in speech module versus mapping bool to int in settingsDialogs module.
I choose the latter as I had no reason to impose a limitation.
I can of course modify it to store a bool instead if requested to.

Is all this coded the way you did in order to support more symbol levels in the future?

I indeed had your #11856 (comment) in mind when not limiting support for evolution.

@dpy013
Copy link
Contributor

dpy013 commented Jan 21, 2021

hi @JulienCochuyt
and
@michaelDCurran
Please fix
Conflicting files
source/globalCommands.py
thanks

@SeanTolstoyevski
Copy link

SeanTolstoyevski commented Jun 17, 2021

Sorry for participating in an irrelevant way. There is another similar problem (#12556).
But I don't know if this pr will fix it.
The problem is that there is a problem for Turkish. No problem for English.

Different speech behavior for each language precludes me from understanding whether this pr covers it.
If it works correctly for English, I think the problem may be something different for Turkish.
Maybe a wrong flag in the Turkish symbol tables.

@seanbudd
Copy link
Member

seanbudd commented Jun 18, 2021

You can test if this fixes your problem by running a copy of this build. Happy to reopen your issue if it is not a duplicate, and has a separate cause.

Copy link
Contributor

@feerrenrut feerrenrut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ready to go. I'll leave it up to you about what to do with the test.

Comment on lines 32 to 37
for expectedWord in wordsWithSymbols:
wordSpoken = _notepad.getSpeechAfterKey("numpad6")
for symbol in symbolMap.keys():
if isSymbolLevelWordAllExpected:
expectedWord = expectedWord.replace(symbol, f" {symbolMap[symbol]}{symbol}")
# unlike other symbols used, symbols.dic doesn't preserve quote symbols with SYMPRES_ALWAYS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic in tests smells, being pragmatic it may not easily be avoidable. The problems it introduces are:

  • higher possibility of a bug in the test itself.
  • the test is harder to read, it doesn't serve as documentation for the expected behavior as well.

Parameterized tests are useful, but mostly when there is a lot of data to get through. Say every combination of a number of parameters. If it's a small number of combinations personally I think explicit is better.

You could instead have something like:

wordsToExpectedSymbolSpeech = {
'Say':'Say',
'(quietly)': 'left paren  quietly  right paren',
'"Hello,': 'quote  Hello  comma',
'Jim".': 'Jim  dot  quote',
}
def test_symbolLevelWord_symbolLevelWord:
	textStr = ' '.join(wordsToExpectedSymbolSpeech.keys())
	_notepad.prepareNotepad(f"Test: {textStr}")
	for expectedWord in wordsToExpectedSymbolSpeech.values():
		wordSpoken = _notepad.getSpeechAfterKey("numpad6")  # navigate to next word
		# unlike other symbols used, symbols.dic doesn't preserve quote symbols with SYMPRES_ALWAYS
		expectedWord = expectedWord.replace('"', ' ').strip()
		_asserts.strings_match(wordSpoken, expectedWord)

wordsToExpectedSymbolSpeech = {
'Say':'Say',
'(quietly)': 'quietly',
'"Hello,': 'Hello',
'Jim".': 'Jim',
}
def test_symbolLevelWord_symbolLevelSome:  # todo: is 'some' the correct level?
	textStr = ' '.join(wordsToExpectedSymbolSpeech.keys())
	_notepad.prepareNotepad(f"Test: {textStr}")
	for expectedWord in wordsToExpectedSymbolSpeech.values():
		wordSpoken = _notepad.getSpeechAfterKey("numpad6")  # navigate to next word
		# unlike other symbols used, symbols.dic doesn't preserve quote symbols with SYMPRES_ALWAYS
		expectedWord = expectedWord.replace('"', ' ').strip()
		_asserts.strings_match(wordSpoken, expectedWord)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer that approach too, I've updated the tests to follow this pattern, but I have made some changes to simplify it further, if you want to take another look.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@seanbudd seanbudd merged commit cbf7407 into nvaccess:master Jul 7, 2021
@nvaccessAuto nvaccessAuto added this to the 2021.2 milestone Jul 7, 2021
feerrenrut added a commit that referenced this pull request Jul 28, 2021
PR #11856 is: "Speak all symbols when moving by words (#11779)"
@feerrenrut feerrenrut mentioned this pull request Jul 28, 2021
8 tasks
feerrenrut added a commit that referenced this pull request Jul 29, 2021
Fixes #12653

# Summary:
PR #11856 introduced speaking symbols when navigating by word.
The changes produced an unintended side effect of double processing symbols.
The text replacement for symbols gets spoken at symbol level all.

# Description of fix:
There isn't enough time before release to be confident in a fix for this behavior, instead the feature is reverted.
Reverting is in commit 619e5f7
Some changes have been kept:
- Symbol level enum: used in other aspects of the code and isn't a cause of this issue
- System test for notepad: Useful to confirm behavior for reading by word is not changed when this feature is re-introduced.

# Testing strategy:
Notepad system test
Generated and checked output of changes doc and userGuide
Ran NVDA with symbolLevelWordAll = True remaining in config (a problem here would only affect alpha users anyway).
feerrenrut added a commit that referenced this pull request Jul 29, 2021
This reverts commit 619e5f7.
feerrenrut added a commit that referenced this pull request Jul 30, 2021
This reverts commit 619e5f7.
feerrenrut added a commit that referenced this pull request Aug 4, 2021
This reverts commit 619e5f7.
Additionally re-enable and update tests so expectation matches behaviour.
feerrenrut added a commit that referenced this pull request Aug 9, 2021
This reverts commit 619e5f7.
Additionally re-enable and update tests so expectation matches behaviour.
feerrenrut added a commit that referenced this pull request Aug 18, 2021
This reverts commit 619e5f7.
Additionally re-enable and update tests so expectation matches behaviour.
feerrenrut added a commit that referenced this pull request Aug 20, 2021
aaclause added a commit to aaclause/BrailleExtender that referenced this pull request Oct 26, 2021
See nvaccess/nvda#12510, nvaccess/nvda#11856 and nvaccess/nvda#12636

According to the NVDA change log:

> - `characterProcessing.SYMLVL_*` constants should be replaced using their equivalent `SymbolLevel.*` before 2022.1.
> - controlTypes has been split up into various submodules, symbols marked for deprecation must be replaced before 2022.1.
seanbudd pushed a commit that referenced this pull request Jan 18, 2022
Removes code deprecated as part of PR #11856

Summary of the issue:
PR #11856 converted module level constants for symbol levels in characterProcessing into an enum. The constants were marked for removal in 2022.1.

Description of how this pull request fixes the issue:
These constants are removed.

Testing strategy:
With git grep made sure that the removed symbol levels are not used in the source code.
feerrenrut added a commit that referenced this pull request Feb 4, 2022
This reverts commit 619e5f7.
Additionally re-enable and update tests so expectation matches behaviour.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deprecated/2022.1 Label used to track deprecations due for removal in the 2022.1 release
Projects
None yet