Skip to content

cli: add --pager for long help / man / markdown output - #397

Merged
helly25 merged 2 commits into
mainfrom
help/pager
Aug 8, 2026
Merged

cli: add --pager for long help / man / markdown output#397
helly25 merged 2 commits into
mainfrom
help/pager

Conversation

@helly25

@helly25 helly25 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Adds a git/bat-style pager for xff's long meta output, building on the help color work (#396).

Design

--pager[=auto|always|never], mirroring --color's tri-state:

  • bare --pager == always, --no-pager == never, default auto (page only on a tty), last-wins.
  • Pages only the meta / doc surfaces: --help, --help=TOPIC, --man, --markdown. It never touches the file listing - that is what a shell pipe to a pager is for (the fd/rg stance).

Why not --help-pager or --help=paged? Paging is a cross-cutting behavior, not a help-specific flag nor a content selector. --help=X picks which reference; whether it pages is governed by --pager. So --help=long stays pure content and xff --pager=always --help=printf can page a short topic too.

Command resolution: $XFF_PAGER, else $PAGER, else the built-in less -FRX (-F quits if it fits one screen so short help never traps you, -R keeps the ANSI color from #396, -X leaves short output on the normal screen). An explicitly-empty env value disables paging (the git / aws convention).

Default auto: because -F no-ops the pager on anything under one screen, only genuinely-long references actually page - no aws-v2-style "why is my --help interactive" surprise on short help.

How

New xff/cli/pager lib: ResolvePagerWhen (raw-arg scan, like --color), ResolvePagerCommand, and EmitPaged which pipes through sh -c (so a $PAGER with args or a pipeline works) feeding the rendered text on the child's stdin, with SIGPIPE ignored during the write and a stdout fallback on any failure. --pager + --no-pager are self-documented global flags; the main.cc meta dispatch routes through EmitPaged.

Tests

  • pager_test (cc): ResolvePagerWhen (bare/values/--no-pager/last-wins) + ResolvePagerCommand (env precedence, empty-disables).
  • pager_test.sh (binary): --pager=never prints, --pager=always pipes verbatim through a cat pass-through, auto stays unpaged off a tty (would deadlock on a sleep pager if it paged), empty env disables, --no-pager accepted on a real search, --help documents it.
  • bazel test //xff/... (87 + 5 skips) and --config=xff_full (92, incl. the regenerated XFF.md drift guard) green.

…wn output

Pages the long meta / doc surfaces (--help, --help=TOPIC, --man, --markdown)
through a pager on a terminal, mirroring --color's tri-state: bare --pager
== always, --no-pager == never, default auto (page only on a tty). It never
touches the file listing - pipe that to a pager yourself.

The pager command is $XFF_PAGER, else $PAGER, else the built-in 'less -FRX'
(-F quits if it fits one screen so short help never traps, -R keeps ANSI
color, -X leaves short output on the normal screen); an explicitly-empty env
value disables paging. Paging runs via 'sh -c' so a $PAGER with args or a
pipeline works, feeding the rendered text on the child's stdin; a missing tty,
empty command, or fork/pipe failure falls back to stdout so output is never
lost.

New xff/cli/pager lib (ResolvePagerWhen / ResolvePagerCommand / EmitPaged),
--pager + --no-pager global flags (self-documented), and the main.cc meta
dispatch routed through EmitPaged. pager_test (resolvers) + pager_test.sh
(binary behavior). XFF.md regenerated for the new flag.
@helly25
helly25 enabled auto-merge (squash) August 8, 2026 14:09
@helly25
helly25 merged commit 568d4ec into main Aug 8, 2026
9 checks passed
@helly25
helly25 deleted the help/pager branch August 8, 2026 14:22
helly25 added a commit that referenced this pull request Aug 8, 2026
…xff (#400)

--man emits roff source; #397 paged it through the plain text pager, which
shows raw roff markup. Make paging surface-aware: --man now resolves a man
pager - $XFF_MANPAGER, else a built-in that formats with mandoc and pages
(honoring $PAGER, else less -FRX). If mandoc is absent the built-in exits
127 so EmitPaged falls back to raw roff (never an empty page).

Gated by the same --pager tri-state: on a tty (auto) or --pager=always,
--man is formatted+paged like 'man xff'; --pager=never and a redirect stay
raw roff (for mandoc / man -l - / installing xff.1). The text surfaces
(--help / --markdown) are unchanged.

PagerKind{kText,kMan} threads through EmitPaged/ResolvePagerCommand; the man
pager is independent of $XFF_PAGER (which needs no formatter). pager_test +
pager_test.sh cover the man resolution and behavior without depending on
mandoc being installed (via an XFF_MANPAGER pass-through).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant