Repository: nvaccess/nvda

Issue:
UIA Terminal: If the previous line output is less than two characters, output isn't spoken
<!--
Please thoroughly read NVDA's wiki article on how to fill in this template, including how to provide the required files.
Issues may be closed if the required information is not present.
https://github.com/nvaccess/nvda/wiki/Github-issue-template-explanation-and-examples
-->

### Steps to reproduce:

1. Open a python interpreter.
2. Write a sentense like this:

```python
x = 455
```

3. Show the result of _x_ by typing `x` and pressing <kbd>Enter</kbd>.
4. Change the value of _x_ to 45 and repeat the previous step.

### Actual behavior:

If you output x with the value of 455, the output is read out by NVDA, but 45 is not read.

### Expected behavior:

Both outputs have to be spoken.

### System configuration
#### NVDA installed/portable/running from source:

NVDA installed.

#### NVDA version:

alpha-18488,4b53f876

#### Windows version:

Windows 10 Pro 64bits Version 1903 (Build SO 18362.295)

#### Name and version of other software in use when reproducing the issue:

Tested python 2 and 3 interpreters, but I think that this is unrelated to python itself.

#### Other information about your system:

### Other questions
#### Does the issue still occur after restarting your PC?
Yes
#### Have you tried any other versions of NVDA? If so, please report their behaviors.
No


Discussion:
CC @codeofdusk try same steps with a CMD session and echo commands, same results.

Cheers,
This is true for both UIA and legacy terminal support. This must be some kind of regression in liveText.
Likely related to #9673. We need to filter out very short announcements to prevent some typed characters from being reported twice.
> This is true for both UIA and legacy terminal support.

@michaelDCurran Yes, since both inherit from `keyboardHandlerBasedTypedCharSupport`. See #9915.
I think the issue is that in keyboardHandlerBasedTypedCharSupport, 
_reportNewText is the thing that filters out the single characters in 
case they are typed characters, but  that method only receives 
individual lines, even if  the new text was made up of multiple lines.

For example, if I have a terminal with just one line:

```

mick@neutrino~$

```


Then I type:

```

echo x

```

and press enter, when pressing enter,  liveText detects two new lines 
all in one go:

```

x

mick@neutrino~$

```

However, it only speaks the final line, because the first is filtered by 
_reportNewText.


Somehow,  the filtering logic needs to be moved higher up, so that it 
only filters if the diff produces only one line, and that line only 
contains 1 or so characters. If there are multiple added lines in the 
diff, then it should not be allowed to filter.


My preference would probably be to perhaps add a _reportNewLines method 
which took the new lines, and called _reportNewText on each of them, and 
then it could be overridden to filter typed characters.



Can replicate in both beta and alpha.

-- 
Luke Davis
Moderator: the new NVDA Help mailing list! (https://groups.io/g/NVDAHelp)
Author: Debug Helper NVDA add-on (https://addons.nvda-project.org/addons/debugHelper.en.html)


Resolving patch:
diff --git a/source/NVDAObjects/behaviors.py b/source/NVDAObjects/behaviors.py
--- a/source/NVDAObjects/behaviors.py
+++ b/source/NVDAObjects/behaviors.py
@@ -1,9 +1,9 @@
 # -*- coding: UTF-8 -*-
-#NVDAObjects/behaviors.py
-#A part of NonVisual Desktop Access (NVDA)
-#This file is covered by the GNU General Public License.
-#See the file COPYING for more details.
-#Copyright (C) 2006-2017 NV Access Limited, Peter Vágner, Joseph Lee
+# NVDAObjects/behaviors.py
+# A part of NonVisual Desktop Access (NVDA)
+# This file is covered by the GNU General Public License.
+# See the file COPYING for more details.
+# Copyright (C) 2006-2019 NV Access Limited, Peter Vágner, Joseph Lee, Bill Dengler
 
 """Mix-in classes which provide common behaviour for particular types of controls across different APIs.
 Behaviors described in this mix-in include providing table navigation commands for certain table rows, terminal input and output support, announcing notifications and suggestion items and so on.
@@ -261,6 +261,15 @@ def _getTextLines(self):
 		"""
 		return list(self.makeTextInfo(textInfos.POSITION_ALL).getTextInChunks(textInfos.UNIT_LINE))
 
+	def _reportNewLines(self, lines):
+		"""
+		Reports new lines of text using _reportNewText for each new line.
+		Subclasses may override this method to provide custom filtering of new text,
+		where logic depends on multiple lines.
+		"""
+		for line in lines:
+			self._reportNewText(line)
+
 	def _reportNewText(self, line):
 		"""Report a line of new text.
 		"""
@@ -294,8 +303,8 @@ def _monitor(self):
 						# which probably means it is just a typed character,
 						# so ignore it.
 						del outLines[0]
-					for line in outLines:
-						queueHandler.queueFunction(queueHandler.eventQueue, self._reportNewText, line)
+					if outLines:
+						queueHandler.queueFunction(queueHandler.eventQueue, self._reportNewLines, outLines)
 				oldLines = newLines
 			except:
 				log.exception("Error getting lines or calculating new text")
@@ -397,14 +406,15 @@ class KeyboardHandlerBasedTypedCharSupport(Terminal):
 	#: be short.
 	_hasTab = False
 
-	def _reportNewText(self, line):
+	def _reportNewLines(self, lines):
 		# Perform typed character filtering, as typed characters are handled with events.
 		if (
-			not self._hasTab
-			and len(line.strip()) < max(len(speech.curWordChars) + 1, 3)
+			len(lines) == 1
+			and not self._hasTab
+			and len(lines[0].strip()) < max(len(speech.curWordChars) + 1, 3)
 		):
 			return
-		super()._reportNewText(line)
+		super()._reportNewLines(lines)
 
 	def event_typedCharacter(self, ch):
 		if ch == '\t':


Test patch: