Redraw cleanly when the window is resized

Resizing the terminal during a scan left the screen full of wreckage:
box corners in the middle of a line, borders twice the width of the
window, a "receiver" header printed eight times down the left edge.  Four
separate defects, which is why it looked so bad.

Live rendering works by moving the cursor back over the frame it drew
last time and overwriting it.  That is only correct while the frame is
still where it was put, and none of these programs noticed when it was
not.

1. Nothing detected a resize.  Both the scan display and saunterbrowse
   now compare the console size on every frame and clear the screen when
   it changes -- polled rather than handled as a signal, because the
   display is redrawn several times a second anyway and a signal handler
   that runs in the middle of a write has to be right about far more than
   this does.  Anything printed before the scan started scrolls away at
   that point, which the manual now says.

2. The layout's model of its own height was wrong, in two places that
   cancelled.  The sweep panel was counted as one line shorter than it
   is, the hit list as one line taller.  The sum came out right whenever
   both were drawn and wrong on a terminal too short for the hit list --
   where the frame then overflowed by one line on every refresh and the
   top of it marched down the screen.  That is what the eight headers
   were.  Each panel height is a named constant now, and a test checks
   every one of them against what is actually rendered.

3. Lines inside the panels could wrap.  A band name, a long status line
   or a decoded message made a panel a row taller than the arithmetic
   allowed for, with the same result.  Every one is drawn on a single
   line and ellipsised now.  The receiver panel drops its optional parts
   instead, keeping the tuner and the flags: "SIMULATED" disappearing off
   the end of a narrow line is how somebody comes to believe they are
   listening to the air.

4. saunterbrowse's full-screen views did not fill the screen.  Nothing
   erases the alternate screen between frames -- the cursor is sent home
   and the new frame written over the old one -- so pressing t or ? on a
   tall window left most of the recording list visible underneath.  Both
   are wrapped in a layout now, which fills the terminal exactly.

The layout also gives up the receiver panel on a very short terminal,
which it previously had no way to do: on eight rows the smallest frame it
could describe was nine lines.

Testing this by rendering to a wide Console and reading the text back
cannot work -- whether the cursor lands where it should is a property of
the terminal, not of the renderable.  So tests/terminal.py runs the
program in a pty, resizes the window underneath it the way a window
manager does, and feeds what it writes to a terminal emulator whose
screen is then read.  Every fix above has a test that fails without it,
checked by reverting each one in turn.  pyte is a dev dependency and
those tests skip without it; the arithmetic ones need nothing.

Also: t now opens the reader for a capture that carries decoded data
rather than speech, because the decoded panel already told the reader to
press it.

869 -> 949 tests.
This commit is contained in:
The Dust Council 2026-08-28 15:47:36 -07:00
parent 68b05a031c
commit d6ae6d0c22
12 changed files with 625 additions and 46 deletions

View file

@ -1,5 +1,5 @@
.\" Generated by packaging/make-man.py -- do not edit by hand.
.TH BANDSAUNTER 1 "2026-08-28" "bandsaunter 2026-08-28_02" "User Commands"
.TH BANDSAUNTER 1 "2026-08-28" "bandsaunter 2026-08-28_03" "User Commands"
.SH NAME
bandsaunter \- scan, record and identify radio signals with an RTL-SDR
.SH SYNOPSIS
@ -836,6 +836,22 @@ settings alone; and
.B \-\-simulate
is looking at an invented band, whose frequencies would be nonsense in a real
settings file. Both still lock out for the run in hand, and say so.
.SH THE LIVE DISPLAY
The display is redrawn in place several times a second, so it has to fit the
window. On a short terminal the optional parts are given up in order \[em] the
spectrum row, then the list of recorded signals, then the key hints, and last
of all the receiver panel, which says nothing that changes. What is never
given up is the sweep line and, while one is running, the recording.
.PP
Resizing the window redraws everything from a blank screen. The frame that was
on it was drawn for a window that no longer exists, and the text above it has
been reflowed by the terminal in any case, so what was printed before the scan
started \[em] the sweep plan and the settings summary \[em] scrolls away at that
point.
.PP
.B \-\-plain
prints one line per hit instead and needs none of this, which is what to use
when the output is going into a pipe or a log.
.SH KEYS DURING A SCAN
.TP
.B q

View file

@ -258,6 +258,22 @@ settings alone; and
.B \-\-simulate
is looking at an invented band, whose frequencies would be nonsense in a real
settings file. Both still lock out for the run in hand, and say so.
.SH THE LIVE DISPLAY
The display is redrawn in place several times a second, so it has to fit the
window. On a short terminal the optional parts are given up in order \[em] the
spectrum row, then the list of recorded signals, then the key hints, and last
of all the receiver panel, which says nothing that changes. What is never
given up is the sweep line and, while one is running, the recording.
.PP
Resizing the window redraws everything from a blank screen. The frame that was
on it was drawn for a window that no longer exists, and the text above it has
been reflowed by the terminal in any case, so what was printed before the scan
started \[em] the sweep plan and the settings summary \[em] scrolls away at that
point.
.PP
.B \-\-plain
prints one line per hit instead and needs none of this, which is what to use
when the output is going into a pipe or a log.
.SH KEYS DURING A SCAN
.TP
.B q

View file

@ -1,5 +1,5 @@
.\" Generated by packaging/make-browse-man.py -- do not edit by hand.
.TH SAUNTERBROWSE 1 "2026-08-28" "bandsaunter 2026-08-28_02" "User Commands"
.TH SAUNTERBROWSE 1 "2026-08-28" "bandsaunter 2026-08-28_03" "User Commands"
.SH NAME
saunterbrowse \- read and listen to what a bandsaunter scan collected
.SH SYNOPSIS