feat(positioning): Add configurable PositionStage for positioning modes
- Added PositioningMode enum (ABSOLUTE, RELATIVE, MIXED) - Created PositionStage class with configurable positioning modes - Updated terminal display to support positioning parameter - Updated PipelineParams to include positioning field - Updated DisplayStage to pass positioning to terminal display - Added documentation in docs/positioning-analysis.md Positioning modes: - ABSOLUTE: Each line has cursor positioning codes (\033[row;1H) - RELATIVE: Lines use newlines (no cursor codes, better for scrolling) - MIXED: Base content uses newlines, effects use absolute positioning (default) Usage: # In pipeline or preset: positioning = "absolute" # or "relative" or "mixed" # Via command line (future): --positioning absolute
This commit is contained in:
@@ -83,7 +83,16 @@ class TerminalDisplay:
|
||||
|
||||
return self._cached_dimensions
|
||||
|
||||
def show(self, buffer: list[str], border: bool = False) -> None:
|
||||
def show(
|
||||
self, buffer: list[str], border: bool = False, positioning: str = "mixed"
|
||||
) -> None:
|
||||
"""Display buffer with optional border and positioning mode.
|
||||
|
||||
Args:
|
||||
buffer: List of lines to display
|
||||
border: Whether to apply border
|
||||
positioning: Positioning mode - "mixed" (default), "absolute", or "relative"
|
||||
"""
|
||||
import sys
|
||||
|
||||
from engine.display import get_monitor, render_border
|
||||
@@ -109,8 +118,27 @@ class TerminalDisplay:
|
||||
if border and border != BorderMode.OFF:
|
||||
buffer = render_border(buffer, self.width, self.height, fps, frame_time)
|
||||
|
||||
# Write buffer with cursor home + erase down to avoid flicker
|
||||
output = "\033[H\033[J" + "\n".join(buffer)
|
||||
# Apply positioning based on mode
|
||||
if positioning == "absolute":
|
||||
# All lines should have cursor positioning codes
|
||||
# Join with newlines (cursor codes already in buffer)
|
||||
output = "\033[H\033[J" + "\n".join(buffer)
|
||||
elif positioning == "relative":
|
||||
# Remove cursor positioning codes (except colors) and join with newlines
|
||||
import re
|
||||
|
||||
cleaned_buffer = []
|
||||
for line in buffer:
|
||||
# Remove cursor positioning codes but keep color codes
|
||||
# Pattern: \033[row;colH or \033[row;col;...H
|
||||
cleaned = re.sub(r"\033\[[0-9;]*H", "", line)
|
||||
cleaned_buffer.append(cleaned)
|
||||
output = "\033[H\033[J" + "\n".join(cleaned_buffer)
|
||||
else: # mixed (default)
|
||||
# Current behavior: join with newlines
|
||||
# Effects that need absolute positioning have their own cursor codes
|
||||
output = "\033[H\033[J" + "\n".join(buffer)
|
||||
|
||||
sys.stdout.buffer.write(output.encode())
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user