Dynamic spacer and silent append when scrolled up
- Spacer only shows when output is at bottom (disappears when scrolled up) - New content appends silently when user has scrolled up (preserves position) - is_at_bottom() helper to check scroll state Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4dcc726280
commit
45d6eea4ac
1 changed files with 31 additions and 7 deletions
|
|
@ -105,17 +105,35 @@ class OutputBuffer:
|
||||||
self._update_buffer()
|
self._update_buffer()
|
||||||
|
|
||||||
def _update_buffer(self):
|
def _update_buffer(self):
|
||||||
"""Update the buffer content and scroll to bottom."""
|
"""Update the buffer content, preserve scroll position if user scrolled up."""
|
||||||
# Trim if needed
|
# Trim if needed
|
||||||
if len(self._lines) > self.max_lines:
|
if len(self._lines) > self.max_lines:
|
||||||
self._lines = self._lines[-self.max_lines:]
|
self._lines = self._lines[-self.max_lines:]
|
||||||
|
|
||||||
|
# Check if cursor is at end (user hasn't scrolled up)
|
||||||
|
old_text = self.buffer.text
|
||||||
|
was_at_end = self.buffer.cursor_position >= len(old_text)
|
||||||
|
|
||||||
# Update buffer text
|
# Update buffer text
|
||||||
text = "\n".join(self._lines)
|
text = "\n".join(self._lines)
|
||||||
self.buffer.set_document(
|
|
||||||
Document(text=text, cursor_position=len(text)),
|
if was_at_end:
|
||||||
bypass_readonly=True
|
# Stay at bottom - auto-scroll
|
||||||
)
|
self.buffer.set_document(
|
||||||
|
Document(text=text, cursor_position=len(text)),
|
||||||
|
bypass_readonly=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Preserve scroll position - silent append
|
||||||
|
old_pos = self.buffer.cursor_position
|
||||||
|
self.buffer.set_document(
|
||||||
|
Document(text=text, cursor_position=old_pos),
|
||||||
|
bypass_readonly=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_at_bottom(self) -> bool:
|
||||||
|
"""Check if output is scrolled to bottom."""
|
||||||
|
return self.buffer.cursor_position >= len(self.buffer.text)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Clear output."""
|
"""Clear output."""
|
||||||
|
|
@ -245,8 +263,14 @@ class TUIConsole:
|
||||||
right_margins=[ScrollbarMargin(display_arrows=True)],
|
right_margins=[ScrollbarMargin(display_arrows=True)],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Blank line spacer above separator
|
# Dynamic spacer - only show when at bottom of output
|
||||||
spacer = Window(height=1)
|
def get_spacer_height():
|
||||||
|
if self.output.is_at_bottom():
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
from prompt_toolkit.layout.dimension import Dimension
|
||||||
|
spacer = Window(height=lambda: Dimension.exact(get_spacer_height()))
|
||||||
|
|
||||||
# Separator line with status
|
# Separator line with status
|
||||||
def get_separator():
|
def get_separator():
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue