improved documentation for the diff generation.

This commit is contained in:
Storm Dragon
2025-06-09 16:53:05 -04:00
parent 6998706934
commit b0ac6e1409
2 changed files with 112 additions and 12 deletions

View File

@ -120,47 +120,94 @@ class screenManager():
self.env['screen']['newDelta'] = ''
self.env['runtime']['attributeManager'].resetAttributeDelta()
# changes on the screen
# Diff generation - critical for screen reader functionality
# This code detects and categorizes screen content changes to provide appropriate
# speech feedback (typing echo vs incoming text vs screen updates)
# Pre-process screen text for comparison - collapse multiple spaces to single space
# This normalization prevents spurious diffs from spacing inconsistencies
oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['oldContentText']))
newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['newContentText']))
# Track whether this appears to be typing (user input) vs other screen changes
typing = False
diffList = []
if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']):
# Special case: Initial screen content (going from empty to populated)
# This handles first screen load or TTY switch scenarios
if self.env['screen']['newContentText'] != '' and self.env['screen']['oldContentText'] == '':
if oldScreenText == '' and\
newScreenText != '':
self.env['screen']['newDelta'] = newScreenText
else:
# Calculate byte positions for the current cursor's line in the flat text buffer
# Formula: (line_number * columns) + line_number accounts for newlines
# Each line contributes 'columns' chars + 1 newline char
cursorLineStart = self.env['screen']['newCursor']['y'] * self.env['screen']['columns'] + self.env['screen']['newCursor']['y']
cursorLineEnd = cursorLineStart + self.env['screen']['columns']
# TYPING DETECTION ALGORITHM
# Determines if this screen change is likely user typing vs other content changes
# All conditions must be met for typing detection:
if abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) >= 1 and \
self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \
self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart] and \
self.env['screen']['newContentText'][cursorLineEnd:] == self.env['screen']['oldContentText'][cursorLineEnd:]:
# Condition 1: Cursor moved horizontally by at least 1 position (typical of typing)
# Condition 2: Cursor stayed on same line (typing doesn't usually change lines)
# Condition 3: Content BEFORE cursor line is unchanged (text above typing area)
# Condition 4: Content AFTER cursor line is unchanged (text below typing area)
# Together: only the current line changed, cursor moved horizontally = likely typing
# Optimize diff calculation for typing by focusing on a small window around cursor
cursorLineStartOffset = cursorLineStart
cursorLineEndOffset = cursorLineEnd
# Limit analysis window to avoid processing entire long lines
# +3 provides safety buffer beyond cursor position to catch edge cases
if cursorLineEnd > cursorLineStart + self.env['screen']['newCursor']['x'] + 3:
cursorLineEndOffset = cursorLineStart + self.env['screen']['newCursor']['x'] + 3
# Extract just the relevant text sections for character-level diff
oldScreenText = self.env['screen']['oldContentText'][cursorLineStartOffset:cursorLineEndOffset]
newScreenText = self.env['screen']['newContentText'][cursorLineStartOffset:cursorLineEndOffset]
# Character-level diff for typing detection (not line-level)
diff = self.differ.compare(oldScreenText, newScreenText)
diffList = list(diff)
typing = True
# Validate typing assumption by checking if detected changes match cursor movement
tempNewDelta = ''.join(x[2:] for x in diffList if x[0] == '+')
if tempNewDelta.strip() != '':
if tempNewDelta != ''.join(newScreenText[self.env['screen']['oldCursor']['x']:self.env['screen']['newCursor']['x']].rstrip()):
# Compare diff result against expected typing pattern
# Expected: characters between old and new cursor positions
expectedTyping = ''.join(newScreenText[self.env['screen']['oldCursor']['x']:self.env['screen']['newCursor']['x']].rstrip())
# If diff doesn't match expected typing pattern, treat as general screen change
if tempNewDelta != expectedTyping:
# Fallback: treat entire current line as new content
diffList = ['+ ' + self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] +'\n']
typing = False
else:
# GENERAL SCREEN CHANGE DETECTION
# Not typing - handle as line-by-line content change
# This catches: incoming messages, screen updates, application output, etc.
diff = self.differ.compare(oldScreenText.split('\n'),\
newScreenText.split('\n'))
diffList = list(diff)
# Extract added and removed content from diff results
# Output format depends on whether this was detected as typing or general change
if not typing:
# Line-based changes: join with newlines for proper speech cadence
self.env['screen']['newDelta'] = '\n'.join(x[2:] for x in diffList if x[0] == '+')
else:
# Character-based changes: no newlines for smooth typing echo
self.env['screen']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+')
# Negative delta (removed content) - used for backspace/delete detection
self.env['screen']['newNegativeDelta'] = ''.join(x[2:] for x in diffList if x[0] == '-')
# track highlighted