Skip to content

Commit

Permalink
Add commands to move the review cursor to the first and last characte…
Browse files Browse the repository at this point in the history
…r of selected text (#17393)

Link to issue number:
Fixes #17299

Summary of the issue:
NVDA doesn't have commands to move the review cursor to start and end of selection, which may be useful to review the selected text.

Description of user facing changes
`NVDA+alt+home` and `NVDA+alt+end` can be used to move the review cursor to the first and last carácter of selected text.

Description of development approach
In globalCommands.py, GlobalCommands class, a staticmethod has been added to get the current selection. This is used to scripts added to move the review cursor to start and end of selection, similar to other scripts used to move the review cursor.

Testing strategy:
Tested manually in a webpage and in Notepad.
  • Loading branch information
nvdaes authored Nov 21, 2024
1 parent ab11a11 commit c32e0e7
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 0 deletions.
77 changes: 77 additions & 0 deletions source/globalCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@
# Translators: Reported when there are no settings to configure in synth settings ring
# (example: when there is no setting for language).
NO_SETTINGS_MSG = _("No settings")
# Translators: Reported when there is no selection
NO_SELECTION_MESSAGE = _("No selection")


def toggleBooleanValue(
Expand Down Expand Up @@ -374,6 +376,24 @@ def script_reportCurrentSelection(self, gesture):
speech.speakTextSelected(info.text)
braille.handler.message(selectMessage)

@staticmethod
def _getSelection() -> textInfos.TextInfo | None:
"""Gets the current selection, if any.
:return: The TextInfo corresponding to the current selection, or None if no selection is available.
"""
obj = api.getFocusObject()
treeInterceptor = obj.treeInterceptor
if (
isinstance(treeInterceptor, treeInterceptorHandler.DocumentTreeInterceptor)
and not treeInterceptor.passThrough
):
obj = treeInterceptor
try:
info = obj.makeTextInfo(textInfos.POSITION_SELECTION)
return info.copy()
except (RuntimeError, NotImplementedError):
return None

@script(
description=_(
# Translators: Input help mode message for report date and time command.
Expand Down Expand Up @@ -2215,6 +2235,63 @@ def script_review_endOfLine(self, gesture: inputCore.InputGesture):
ui.reviewMessage(gui.blockAction.Context.WINDOWS_LOCKED.translatedMessage)
return

@script(
description=_(
# Translators: Input help mode message for move review cursor to start of selection command.
"Moves the review cursor to the first character of the selection, and speaks it",
),
category=SCRCAT_TEXTREVIEW,
gesture="kb:NVDA+alt+home",
)
def script_review_startOfSelection(self, gesture: inputCore.InputGesture):
info = self._getSelection()
if info is None or info.isCollapsed:
ui.message(NO_SELECTION_MESSAGE)
return
info.collapse()

# This script is available on the lock screen via getSafeScripts, as such
# ensure the review position does not contain secure information
# before announcing this object
if api.setReviewPosition(info):
info.expand(textInfos.UNIT_CHARACTER)
speech.speakTextInfo(
info,
unit=textInfos.UNIT_CHARACTER,
reason=controlTypes.OutputReason.CARET,
)
else:
ui.reviewMessage(gui.blockAction.Context.WINDOWS_LOCKED.translatedMessage)

@script(
description=_(
# Translators: Input help mode message for move review cursor to end of selection command.
"Moves the review cursor to the last character of the selection, and speaks it",
),
category=SCRCAT_TEXTREVIEW,
gesture="kb:NVDA+alt+end",
)
def script_review_endOfSelection(self, gesture: inputCore.InputGesture):
info = self._getSelection()
if info is None or info.isCollapsed:
ui.message(NO_SELECTION_MESSAGE)
return
info.move(textInfos.UNIT_CHARACTER, -1, "end")
info.collapse(end=True)

# This script is available on the lock screen via getSafeScripts, as such
# ensure the review position does not contain secure information
# before announcing this object
if api.setReviewPosition(info):
info.expand(textInfos.UNIT_CHARACTER)
speech.speakTextInfo(
info,
unit=textInfos.UNIT_CHARACTER,
reason=controlTypes.OutputReason.CARET,
)
else:
ui.reviewMessage(gui.blockAction.Context.WINDOWS_LOCKED.translatedMessage)

def _getCurrentLanguageForTextInfo(self, info):
curLanguage = None
if config.conf["speech"]["autoLanguageSwitching"]:
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ To use this feature, "allow NVDA to control the volume of other applications" mu
* Default input and output braille tables can now be determined based on the NVDA language. (#17306, #16390, #290, @nvdaes)
* In Microsoft Word, when using the "report focus" command, the document layout will be announced if this information is available and reporting object descriptions is enabled. (#15088, @nvdaes)
* NVDA will now only warn about add-on incompatibility when updating to a version which has an incompatible add-on API to the currently installed copy. (#17071)
* Added commands to move the review cursor to the first and last character of the selected text, assigned to `NVDA+alt+home` and `NVDA+alt+end`, respectively. (#17299, @nvdaes)

### Bug Fixes

Expand Down
2 changes: 2 additions & 0 deletions user_docs/en/userGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,8 @@ The following commands are available for reviewing text:
|Move to end of line in review |shift+numpad3 |NVDA+end |none |Moves the review cursor to the end of the current line of text|
|Move to previous page in review |`NVDA+pageUp` |`NVDA+shift+pageUp` |none |Moves the review cursor to the previous page of text if supported by the application|
|Move to next page in review |`NVDA+pageDown` |`NVDA+shift+pageDown` |none |Moves the review cursor to the next page of text if supported by the application|
|Move to start of selection in review |NVDA+alt+home |NVDA+alt+home |none |Moves the review cursor to the first character of the selected text|
|Move to end of selection in review |NVDA+alt+end |NVDA+alt+end |none |Moves the review cursor to the last character of the selected text|
|Say all with review |numpadPlus |NVDA+shift+a |3-finger flick down (text mode) |Reads from the current position of the review cursor, moving it as it goes|
|Select then Copy from review cursor |NVDA+f9 |NVDA+f9 |none |Starts the select then copy process from the current position of the review cursor. The actual action is not performed until you tell NVDA where the end of the text range is|
|Select then Copy to review cursor |NVDA+f10 |NVDA+f10 |none |On the first press, text is selected from the position previously set as start marker up to and including the review cursor's current position. If the system caret can reach the text, it will be moved to the selected text. After pressing this key stroke a second time, the text will be copied to the Windows clipboard|
Expand Down

0 comments on commit c32e0e7

Please sign in to comment.