fix: robust terminal size detection + resize handling
- Try ioctl on stdin/stdout/stderr, then /dev/tty, then os/shutil - Add SIGWINCH handler to re-render on terminal resize - Clamp scroll position after resize Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
briefing
43
briefing
@@ -495,11 +495,36 @@ def fetch_task_content(nid):
|
|||||||
# ── Terminal helpers ────────────────────────────────────────────────
|
# ── Terminal helpers ────────────────────────────────────────────────
|
||||||
|
|
||||||
def get_terminal_size():
|
def get_terminal_size():
|
||||||
|
"""Get terminal rows, cols using multiple methods."""
|
||||||
|
# Try ioctl on multiple fds
|
||||||
|
for fd_try in [sys.stdout, sys.stdin, sys.stderr]:
|
||||||
|
try:
|
||||||
|
result = struct.unpack('hh', fcntl.ioctl(fd_try, termios.TIOCGWINSZ, b'\0' * 4))
|
||||||
|
if result[0] > 0 and result[1] > 0:
|
||||||
|
return result[0], result[1]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# Try /dev/tty directly
|
||||||
try:
|
try:
|
||||||
result = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, b'\0' * 4))
|
with open('/dev/tty', 'r') as tty_fd:
|
||||||
return result[0], result[1] # rows, cols
|
result = struct.unpack('hh', fcntl.ioctl(tty_fd, termios.TIOCGWINSZ, b'\0' * 4))
|
||||||
|
if result[0] > 0 and result[1] > 0:
|
||||||
|
return result[0], result[1]
|
||||||
except Exception:
|
except Exception:
|
||||||
return 40, 80
|
pass
|
||||||
|
# Try os/shutil
|
||||||
|
try:
|
||||||
|
sz = os.get_terminal_size()
|
||||||
|
return sz.lines, sz.columns
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
import shutil
|
||||||
|
sz = shutil.get_terminal_size()
|
||||||
|
return sz.lines, sz.columns
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return 40, 80
|
||||||
|
|
||||||
|
|
||||||
def read_key(fd):
|
def read_key(fd):
|
||||||
@@ -546,6 +571,12 @@ def tui_viewer(range_days, client):
|
|||||||
input_mode = False
|
input_mode = False
|
||||||
input_buf = ""
|
input_buf = ""
|
||||||
status_msg = ""
|
status_msg = ""
|
||||||
|
needs_redraw = [False] # mutable for signal handler
|
||||||
|
|
||||||
|
# Handle terminal resize
|
||||||
|
def on_resize(signum, frame):
|
||||||
|
needs_redraw[0] = True
|
||||||
|
signal.signal(signal.SIGWINCH, on_resize)
|
||||||
|
|
||||||
def split_lines(content):
|
def split_lines(content):
|
||||||
return content.split('\n')
|
return content.split('\n')
|
||||||
@@ -626,11 +657,17 @@ def tui_viewer(range_days, client):
|
|||||||
load_briefing()
|
load_briefing()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
if needs_redraw[0]:
|
||||||
|
needs_redraw[0] = False
|
||||||
render()
|
render()
|
||||||
key = read_key(fd)
|
key = read_key(fd)
|
||||||
|
if not key:
|
||||||
|
continue
|
||||||
rows, cols = get_terminal_size()
|
rows, cols = get_terminal_size()
|
||||||
view_height = rows - 1
|
view_height = rows - 1
|
||||||
max_scroll = max(0, len(lines) - view_height)
|
max_scroll = max(0, len(lines) - view_height)
|
||||||
|
# Clamp scroll after resize
|
||||||
|
scroll = min(scroll, max_scroll)
|
||||||
|
|
||||||
if input_mode:
|
if input_mode:
|
||||||
if key == 'ESC':
|
if key == 'ESC':
|
||||||
|
|||||||
Reference in New Issue
Block a user