Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Comments

A command to repeat last spoken information#19173

Merged
SaschaCowley merged 16 commits intonvaccess:masterfrom
CyrilleB79:repLastSpeech
Dec 12, 2025
Merged

A command to repeat last spoken information#19173
SaschaCowley merged 16 commits intonvaccess:masterfrom
CyrilleB79:repLastSpeech

Conversation

@CyrilleB79
Copy link
Contributor

Although this PR addresses #625, it should be actually considered as a first step to address #18400 (full speech history), since that's what most NVDA users want at the end.

Starting with a single "Repeat last speech" command was recommended by NV Access though, and may be a first step to gather feedback on a concrete implementation and UX. I.e. this may be a first base to discuss a more complete speech history feature.

Link to issue number:

Close #625

Summary of the issue:

People want commands to repeat the last spoken information, to be able to display it and to copy it.
Actually, they also want a deeper history of the speech, but NV Access has recommended in #18400 to begin with the last speech.

Description of user facing changes:

A new commands has been introduced: Repeat last spoken information (NVDA+shift+F12). Pressing it twice displays this information in a browseable message.

The copy concern can be considered addressed since browseable message now have a copy button.

When in on-demand speech mode, the last string to be spoken is memorized, no matter if it is actually spoken (on-demand command), or not. This provide a quite handy mode to retrive the last information that should have been spoken if speech mode had been on.

Description of developer facing changes:

N/A

Description of development approach:

Use pre_speech extension point to store the last spoken information

Testing strategy:

Manual test, with speech modes on and on-demand.

Known issues with pull request:

This minimalist PR may be frustrating for a lot of people expecting more, i.e. a more complete speech history feature as in the add-on, in Jaws or in Narrator.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@CyrilleB79
Copy link
Contributor Author

@Qchristensen, I have questions on the User Guide.
That may not be the first thing to discuss. But I write it here to keep it in mind:

The command is mentioned both in the Quick Start Guide as in the normal place. It makes sense to have it in the Quick start Guide IMO since the command is quite basic.

In the Quick Start Guide part, I have put it in "2.3.5. Reporting location and other information" since this paragraph includes various types of basic commands. Alternatively thought, I may have put it in "2.3.3. Starting and stopping NVDA" since this paragraph already includes Stop speech (control key) and pause speech (shift key). In this case, the paragraph, which already did not include only start/stop commands could be split into two paragraphs: one for start/stop NVDA and another part for speech-control commands.

Regarding the mention in the rest of the User Guide, where we have more detailed information on NVDA and its commands, I have put the command in "Basic NVDA commands" (4.6). But alternatively, I could have put it in a paragraph dedicated to speech, to be reworded, including this new command, and other ones related to last speech copy or speech history if we want to integrate these in the future, as well as all the speech mode paragraph.

@amirmahdifard
Copy link

you're working on this already, so while you're at it, just do it the simple speech history. a key to view backward, and a key to view next history speech, and a key to speech it or 2 times to copy, or however you like it. But the current speech history addon is very grate and we'd be morethan enough grateful if the same has been implemented hear. My suggestion is that now that you're in doing kind of this, do that one once forever and for all. Thanks alot!

@CyrilleB79
Copy link
Contributor Author

@amirmahdifard please read #18400 as well as the full initial description of this PR.
It was a bit difficult to convince NV Access of the interest to include Speech History feature in NVDA. At the end, they accepted it but required to start with a single "repeat last spoken information" command in a first step.

If you wish to provide arguments for full Speech History feature integration in NVDA, check #18400 and add your arguments if not already discussed there. Thanks.

@seanbudd seanbudd added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label Nov 11, 2025
@CyrilleB79 CyrilleB79 marked this pull request as ready for review November 13, 2025 20:30
@CyrilleB79 CyrilleB79 requested review from a team as code owners November 13, 2025 20:30
Copy link
Member

@SaschaCowley SaschaCowley left a comment

Choose a reason for hiding this comment

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

@CyrilleB79 said:

When in on-demand speech mode, the last string to be spoken is memorized, no matter if it is actually spoken (on-demand command), or not. This provide a quite handy mode to retrive the last information that should have been spoken if speech mode had been on.

I think this creates a very confusing user experience, as the command no-longer does what it says it will. I think this probably needs to be re-implemented more tightly in the speech framework (I.E. after deciders and filters have executed).



def _setLastSpeechString(speechSequence, symbolLevel, priority):
text = " ".join(i for i in speechSequence if isinstance(i, str))
Copy link
Member

Choose a reason for hiding this comment

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

Is it worth adding a context manager that allows disabling this behaviour? For instance, imagine that we wanted to present the last spoken information as "Last said: {message}". In that case, if NVDA said "Hello, world!":
1st invocation: "Last said: Hello, world!"
2nd invocation: "Last said: Last said: Hello, world!"
... etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For instance, imagine that we wanted to present the last spoken information as "Last said: {message}".

Is it what you really wish?

If not, I am a bit reluctant to develop something for an imaginary use case, which may not be adapted to a future real use case.

If you have real use cases where spoken information should not be stored in last speech, let me know. In this case, can you also give me some indications on how to implement this context manager?

@SaschaCowley SaschaCowley marked this pull request as draft November 14, 2025 00:46
@CyrilleB79
Copy link
Contributor Author

@SaschaCowley wrote:

@CyrilleB79 said:

When in on-demand speech mode, the last string to be spoken is memorized, no matter if it is actually spoken (on-demand command), or not. This provide a quite handy mode to retrive the last information that should have been spoken if speech mode had been on.

I think this creates a very confusing user experience, as the command no-longer does what it says it will.

Though, we have already two similar cases where speech is considered as what should have been spoken if speech mode was on:

  • speech viewer: it displays what would be spoken with speech mode on, no matter if speech mode is off or on-demand
  • When braille mode is set on "display speech output", it displays what would be spoken with speech mode on, no matter if speech mode is off or on-demand

So taking the same approach for repeat last speech would be consistent with these use cases.

Moreover, when speech mode is off or on-demand, I feel that the command as I have implemented seems more useful than what you suggest:

  • when speech mode is off:
    • with your suggestion, the result of the command would always be the same, that is the last speech before speech is off, probably "speech off".
    • with my current implementation: the command can be called to braille the last speech (ui.message)
  • when speech mode is on-demand:
    • with your suggestion: the command would speak again the last speaking command. Since speaking commands in on-demand mode are the commands that perform no other action than speaking, these commands can just be repeated to hear again what they say, no need of an additional command for this.
    • with my current implementation: as explained before the repeat last speech command can repeat what a silent command would have said.

If you are concerned that the command no longer does not do what it says it will, maybe we can try to find a better wording to describe it, in the input help / input gesture dialog, and overall in the user guide?

IMO, this decision should be discussed more broadly (cc @seanbudd, @Qchristensen)

Though, if you confirm at NV Access level that last speech should be the speech actually spoken, I'll change this. I think that there is another extension point that can be used.

@CyrilleB79 CyrilleB79 marked this pull request as ready for review November 14, 2025 18:44
@cary-rowen
Copy link
Contributor

cary-rowen commented Nov 16, 2025

Thank you for your work, @CyrilleB79.

I just wanted to point out some user habits from the Chinese community for your consideration:

I must say that, from the perspective of Chinese user habits, the current changes are useful but not significantly impactful. This feedback is based on my experience maintaining clipboardEnhancement over many years and the popularity of similar features in other screen readers used in China.

The two features most frequently requested for clipboardEnhancement were:

  • "Copy last spoken text" (which replaces the current clipboard content).
  • "Append last spoken text" (which adds the new text while preserving the existing clipboard content).

I did also add "Repeat last spoken text," but it seems very few people mention it, and no one has ever proposed assigning a default gesture for it.

Regarding your statement:

The copy concern can be considered addressed since browseable message now have a copy button.

I believe this is insufficient. Based on the demands above, the number of steps required to achieve 'copy last spoken' with this method is too high.

If you or NV Access feel that the two main needs I mentioned (copy and append) should be implemented separately, I fully accept that. However, please do not attempt to cover too many use cases with this single pull request.

A Note on the Key Gesture (F12)

I do not think F12 is a good choice:

On modern laptop keyboards, the F keys (F1 to F12) often switch between function mode and F key mode. Furthermore, they lack clear grouping boundaries (e.g., in groups of four). I am generally reluctant to assign F keys to frequently used functions, including the existing NVDA+F9/F10 commands.

@CyrilleB79
Copy link
Contributor Author

Thanks for your feedback @cary-rowen.
I'd encourage NV Access (@SaschaCowley or others) to look at it carefully.

I must say that, from the perspective of Chinese user habits, the current changes are useful but not significantly impactful.

It's true. As written before, my first idea was to implement speech history, but NV Access has considered that repeating last speech was a required first step and a basis for further discussions (to be done in the dedicated issue).

Re this PR:

If you or NV Access feel that the two main needs I mentioned (copy and append) should be implemented separately, I fully accept that. However, please do not attempt to cover too many use cases with this single pull request.

IMO, if NV Access agrees with it, a copy last speech script can be added, e.g. NVDA+control+x if we want to follow Narrator's key binding. Or NVDA+shift+x if we want to keep NVDA+control+x to open a future settings window or panel.

The append use case IMO should be discussed separately in a issue.

I do not think F12 is a good choice:

I have already changed it to NVDA+x, as in Narrator, following Sascha's suggestion.

On modern laptop keyboards, the F keys (F1 to F12) often switch between function mode and F key mode. Furthermore, they lack clear grouping boundaries (e.g., in groups of four). I am generally reluctant to assign F keys to frequently used functions, including the existing NVDA+F9/F10 commands.

Many function keys are already used in NVDA, with or without modifiers; a lot for a long time, but some recently added (NVDA+shift+f10 to switch to native selection mode). If you wish to open a discussion on this topic, I'd recommend that you do this separately rather than commenting each PR introducing a new gesture user a function key.
If you do so, I'll explain you why I do not agree with this analysis, but again, in a dedicated discussion please.

@SaschaCowley
Copy link
Member

@CyrilleB79 thanks for the additional context. We will discuss it and get back to you.

Regarding using x, I looked at what other Screen Readers do (the following are from memory, so apologies if they're inaccurate):

  • Narrator uses Narrator+x to repeat, Narrator+control+x to copy, and Narrator+alt+x to bring up history
  • Jaws uses Jaws+space, h for speech history (we don't have layered shortcuts, so this isn't an option for us
  • VoiceOver on Mac uses VO+shift+z, which toggles sleep mode in laptop layout
  • As far as I can tell, Orca does not have a speech history feature
  • Dolphin Screen Reader seems to use capsLock+\ or capsLock+numPad9
    I did not check any other screen readers

@CyrilleB79
Copy link
Contributor Author

@SaschaCowley have you had the opportunity to re-discuss this internally?

@seanbudd seanbudd added the merge-early Merge Early in a developer cycle label Dec 9, 2025
Copy link
Member

@SaschaCowley SaschaCowley left a comment

Choose a reason for hiding this comment

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

Thanks @CyrilleB79, this looks really great! Could you please move the changes entry to the 2026.2 section of the change long and resolve conflicts? Then I think this is good to merge.

@SaschaCowley
Copy link
Member

@CyrilleB79 apologies for the delay in getting to this, things have been hectic. I think the only thing left to do is fix the changes file :)

@SaschaCowley SaschaCowley marked this pull request as draft December 9, 2025 06:52
@CyrilleB79
Copy link
Contributor Author

@CyrilleB79 apologies for the delay in getting to this, things have been hectic. I think the only thing left to do is fix the changes file :)

Oh too bad that it did not make the cut for 2026.1, so that we could have user feedback on this feature.
Anyway, 2026.2 will probably be released not so long after 2026.1, so that's not a so big deal.

@CyrilleB79 CyrilleB79 marked this pull request as ready for review December 9, 2025 07:43
@SaschaCowley SaschaCowley merged commit 835486a into nvaccess:master Dec 12, 2025
41 checks passed
@github-actions github-actions bot added this to the 2026.2 milestone Dec 12, 2025
@CyrilleB79 CyrilleB79 deleted the repLastSpeech branch December 12, 2025 08:41
@CyrilleB79 CyrilleB79 mentioned this pull request Dec 19, 2025
5 tasks
seanbudd pushed a commit that referenced this pull request Dec 29, 2025
Fixes #19395
Fix-up of #19173.
Summary of the issue:

Sometimes, e.g. in Notepad, skim reading process was not correctly interrupted when pressing control key: say all was restarting when another key was pressed.
Description of user facing changes:

Skim reading process is now correctly interrupted when control is pressed.
Description of developer facing changes:

N/A
Description of development approach:

When the speech sequence is stored, it is first filtered.
CallbackCommands are filtered out of the sequence since callback functions such as say all ones should not be called again when repeating the last speech (this was the cause of say all restarting).

Not all BaseCallbackCommands are filtered since other BaseCallbackCommand such as BeepCommand (for indentation reporting) or WaveFileCommands (for spelling error reporting) still need to be reported.

I have not included IndexCommands in the filtering since in any case, they only seem to appear downstream, in the speech manager part.

Regarding CancellableSpeechCommands, I have included them, since I've seen that they are also filtered out from remote speech. Though, I do not exactly know how cancellable speech works, so please double check. Thanks.
Somsubhra-Nandi pushed a commit to Somsubhra-Nandi/nvda that referenced this pull request Jan 9, 2026
Close nvaccess#625
First step to nvaccess#18400

### Summary of the issue:
People want commands to repeat the last spoken information, to be able
to display it and to copy it.
Actually, they also want a deeper history of the speech, but NV Access
has recommended in nvaccess#18400 to begin with the last speech.

### Description of user facing changes:
A new commands has been introduced: Repeat last spoken information
(`NVDA+shift+F12`). Pressing it twice displays this information in a
browseable message.

The copy concern can be considered addressed since browseable message
now have a copy button.

When in on-demand speech mode, the last string to be spoken is
memorized, no matter if it is actually spoken (on-demand command), or
not. This provide a quite handy mode to retrive the last information
that should have been spoken if speech mode had been on.

### Description of developer facing changes:
N/A
### Description of development approach:
Use `pre_speech` extension point to store the last spoken information

### Testing strategy:
Manual test, with speech modes on and on-demand.

### Known issues with pull request:
This minimalist PR may be frustrating for a lot of people expecting
more, i.e. a more complete speech history feature as in the add-on, in
Jaws or in Narrator.
Somsubhra-Nandi pushed a commit to Somsubhra-Nandi/nvda that referenced this pull request Jan 9, 2026
Fixes nvaccess#19395
Fix-up of nvaccess#19173.
Summary of the issue:

Sometimes, e.g. in Notepad, skim reading process was not correctly interrupted when pressing control key: say all was restarting when another key was pressed.
Description of user facing changes:

Skim reading process is now correctly interrupted when control is pressed.
Description of developer facing changes:

N/A
Description of development approach:

When the speech sequence is stored, it is first filtered.
CallbackCommands are filtered out of the sequence since callback functions such as say all ones should not be called again when repeating the last speech (this was the cause of say all restarting).

Not all BaseCallbackCommands are filtered since other BaseCallbackCommand such as BeepCommand (for indentation reporting) or WaveFileCommands (for spelling error reporting) still need to be reported.

I have not included IndexCommands in the filtering since in any case, they only seem to appear downstream, in the speech manager part.

Regarding CancellableSpeechCommands, I have included them, since I've seen that they are also filtered out from remote speech. Though, I do not exactly know how cancellable speech works, so please double check. Thanks.
tareh7z pushed a commit to tareh7z/nvda that referenced this pull request Feb 16, 2026
Close nvaccess#625
First step to nvaccess#18400

People want commands to repeat the last spoken information, to be able
to display it and to copy it.
Actually, they also want a deeper history of the speech, but NV Access
has recommended in nvaccess#18400 to begin with the last speech.

A new commands has been introduced: Repeat last spoken information
(`NVDA+shift+F12`). Pressing it twice displays this information in a
browseable message.

The copy concern can be considered addressed since browseable message
now have a copy button.

When in on-demand speech mode, the last string to be spoken is
memorized, no matter if it is actually spoken (on-demand command), or
not. This provide a quite handy mode to retrive the last information
that should have been spoken if speech mode had been on.

N/A
Use `pre_speech` extension point to store the last spoken information

Manual test, with speech modes on and on-demand.

This minimalist PR may be frustrating for a lot of people expecting
more, i.e. a more complete speech history feature as in the add-on, in
Jaws or in Narrator.
tareh7z pushed a commit to tareh7z/nvda that referenced this pull request Feb 16, 2026
Fixes nvaccess#19395
Fix-up of nvaccess#19173.
Summary of the issue:

Sometimes, e.g. in Notepad, skim reading process was not correctly interrupted when pressing control key: say all was restarting when another key was pressed.
Description of user facing changes:

Skim reading process is now correctly interrupted when control is pressed.
Description of developer facing changes:

N/A
Description of development approach:

When the speech sequence is stored, it is first filtered.
CallbackCommands are filtered out of the sequence since callback functions such as say all ones should not be called again when repeating the last speech (this was the cause of say all restarting).

Not all BaseCallbackCommands are filtered since other BaseCallbackCommand such as BeepCommand (for indentation reporting) or WaveFileCommands (for spelling error reporting) still need to be reported.

I have not included IndexCommands in the filtering since in any case, they only seem to appear downstream, in the speech manager part.

Regarding CancellableSpeechCommands, I have included them, since I've seen that they are also filtered out from remote speech. Though, I do not exactly know how cancellable speech works, so please double check. Thanks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. merge-early Merge Early in a developer cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide a key to read last spoken info

5 participants