feat: horizontal scrolling for the stats table (#14)#143
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ce criteria Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndex, ColsWidth bounds, S-key, reviewers rationale Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mp), remove junk lines, fix context paths Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Branch set to feature/horizontal-scroll for implementation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cution plan Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…kers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ment - Reserve edge-marker (‹/›) width in visibleColumns scroll budget and mirror it as blank fillers in data rows, so the visible width of the header row equals every data row (alignment invariant). visibleColumns now returns a columnWindow struct computed once in renderDbstat and passed to the header and data printers (removes the triple call / desync risk). - Conservative marker reservation avoids the budget<->window cycle: left marker reserved when clamped offset > 0, right marker when a full-budget probe already shows columns hidden right (shrinking budget can only keep them hidden). - Tests: mid-offset asserts BOTH markers; new alignment-invariant litmus (ANSI-stripped header width == data width); frozen-bold escape pinned; right marker position pinned to line end; truncation branch covered. Test_visibleColumns updated for the marker-reserved budget. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ions Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ker (issue #14 QA) The visibleColumns window included a scrollable column only if it fit ENTIRELY into the remaining width budget. The activity/statements "query" column is aligned by content and is almost never narrow enough to fit in full, so it was dropped from the window (QA bug 2: query not shown) and, because the last column then fell short of ncols-1, the right edge marker was drawn even on wide screens where everything "essentially" fits (QA bug 1: spurious ›). Change countFit to count a column as visible when its START position is within the budget (partial visibility of the trailing column, truncated by gocui at the screen edge — the pre-scroll behaviour). The same start-in-budget rule applies to the backward walk that computes maxOffset, so maxOffset shrinks consistently and the "last column visible at max offset / nothing hidden right" invariant still holds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… always reachable The backward-walk computing maxOffset measured trailing columns against the full baseBudget, but the forward-walk that builds the window at any non-zero offset measures against baseBudget - markerWidth (the left marker ‹ is always present when clamped > 0). The mismatch let the backward-walk overestimate how many trailing columns fit, so at the maximum clamped offset the forward-walk fell short of the last column: last < ncols-1 and hiddenRight stayed true forever, making the last column unreachable by scrolling. Reserve the guaranteed left marker in the backward-walk whenever scrolling is actually needed (maxOffset > 0), guarding against a non-positive tail budget. Shrinking the budget can only push maxOffset up and keep it > 0, so the left-marker assumption stays consistent in one extra pass. Add property test Test_visibleColumns_maxOffsetReachesLastColumn over ncols 2..8 x width set x termWidth 40..120: at max offset the last column is always visible and no right marker remains. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fset marker reserve) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds by-column horizontal scrolling to the main stats table in
pgcenter top, with a frozen first column — long-requested support for narrow terminals (addresses #14, open since 2015).On narrow screens the stats table no longer silently cuts off-screen columns (e.g.
queryon the activity screen). Users can now scroll the table sideways while keeping the row identifier (PID / datname / table name) in view.What's included
[/]scroll the column window left / right (one column per press).Shift/Ctrl+arrow are not distinguishable by termbox, so printable keys were chosen.‹/›on the header row indicate hidden columns to each side; shown only when there is something to scroll to.query) is shown truncated at the edge, as before, rather than disappearing.←/→) are orthogonal.Scope is confined to the main
dbstattable: extra side panels, the record/report pipeline, and the existingpg_stat_io/pg_stat_statementssub-screen splits are intentionally untouched.Process & quality
Built via the full SDLC pipeline (user-spec → tech-spec → task decomposition → waved implementation), each stage multi-validated. Per-task code/test review (2–3 rounds where needed). Manual QA in a narrow terminal surfaced two bugs (wide last column disappearing; redundant edge markers) — root-caused to the column-window fit semantics, fixed with property-test coverage proving the last column is always reachable.
make build,make lintgreen. (make vulnflags a pre-existing stdlib advisory unrelated to this change.)Full spec/decision trail under
docs/features/009-feat-horizontal-scroll/.🤖 Generated with Claude Code