Forward PAGER parameters to the temp file pager and tokenize less raw-mode detection
Summary
_tempfilepager now receives cmd_params and runs the pager as [cmd_path, *cmd_params, tempfile]. Before, it ran [cmd_path, tempfile] and dropped flags from PAGER. On Windows, PAGER="less -R" now runs less -R on the temporary file.
_pipepager now decides whether less already shows raw color through a new helper, _less_uses_raw_mode. The helper shlex-splits LESS, appends cmd_params, and accepts only dash-prefixed short-option clusters containing r/R or the exact --raw-control-chars token. The old check matched any r or R anywhere in the joined string. The less match now compares cmd_path.stem, so less.exe counts, and it casefolds on Windows. LESS=-R is still injected only when both LESS and cmd_params are empty.
Changes
-
Modified src/click/_termui_impl.py +50 −11
_pager_contextmanagerpassescmd_paramsto_tempfilepager._tempfilepagergains acmd_paramsargument and adds it to thesubprocess.callargv before the file name. Adds_less_uses_raw_mode(less_env, cmd_params)._pipepagermatches less oncmd_path.stem, casefolded underWIN, and calls the new helper instead of a substring check.- What
_pager_contextmanagerpassescmd_paramsto_tempfilepager._tempfilepagergains acmd_paramsargument and adds it to thesubprocess.callargv before the file name. Adds_less_uses_raw_mode(less_env, cmd_params)._pipepagermatches less oncmd_path.stem, casefolded underWIN, and calls the new helper instead of a substring check.- Why
- Users get their
PAGERflags on the temp file backend. Fewer filenames and option values falsely enable color. Inputs that do not fit the token rules no longer enable color, including dash-lessLESSvalues and abbreviated long options.
-
Modified tests/test_termui.py +171 −1 Adds
test_pipepager_less_detection_matches_stem,test_pipepager_less_detection_case_insensitive_on_windows, a parametrizedtest_pipepager_less_raw_mode_detectionwith a_FakePagerProcessPopen stub, andtest_tempfile_pager_passes_pager_paramsusinghead -n 1._force_tempfile_pagernow runsshutil.whichon only the first shlex token ofpager_cmd.- What
- Adds
test_pipepager_less_detection_matches_stem,test_pipepager_less_detection_case_insensitive_on_windows, a parametrizedtest_pipepager_less_raw_mode_detectionwith a_FakePagerProcessPopen stub, andtest_tempfile_pager_passes_pager_paramsusinghead -n 1._force_tempfile_pagernow runsshutil.whichon only the first shlex token ofpager_cmd. - Why
- Covers stem matching, token-based detection, and forwarding of parameters. The helper change lets
pager_cmdcarry arguments.
-
Modified CHANGES.md +6 −0 Adds two Unreleased entries: temp file pager forwards
PAGERparameters, and raw mode detection parses option tokens.- What
- Adds two Unreleased entries: temp file pager forwards
PAGERparameters, and raw mode detection parses option tokens. - Why
- Changelog only.
Flow
Rendering diagram…
get_pager_file resolves PAGER into a command path and params. _pager_contextmanager routes them to either the pipe backend or the temp file backend. The pipe backend asks _less_uses_raw_mode whether to enable color.Components and connections
Components
- get_pager_file entry point
-
_pager_contextmanager
function, changed
src/click/_termui_impl.py -
_pipepager
function, changed
src/click/_termui_impl.py -
_less_uses_raw_mode
function, changed
src/click/_termui_impl.py -
_tempfilepager
function, changed
src/click/_termui_impl.py - pager subprocess external service
Connections
- get_pager_file → _pager_contextmanager (color)
- _pager_contextmanager → _pipepager (cmd_path, cmd_params)
- _pager_contextmanager → _tempfilepager (cmd_path, cmd_params)
- _pipepager → _less_uses_raw_mode (LESS, cmd_params)
- _pipepager → pager subprocess (Popen with env LESS)
- _tempfilepager → pager subprocess (argv params + file)
Risks
0 high · 1 medium · 2 low
-
Mediumsrc/click/_termui_impl.py:537–543
Dash-less LESS values like
FRXno longer enable colorlessaccepts option letters inLESSwithout a leading dash; git, for example, setsLESS=FRX. The old check foundRin that string and setcolor = True. The new loop skips tokens that do not start with-, soFRXreturns False.LESSis non-empty, so-Ris not injected either. ANSI codes are then stripped where they used to be shown. -
Lowsrc/click/_termui_impl.py:538–540
Abbreviated
--rawlong option not detectedlessaccepts unambiguous long-option prefixes such as--raw. The new code requires the exact--raw-control-charstoken, soPAGER="less --raw"leaves color off. The old substring check enabled it. -
Lowsrc/click/_termui_impl.py:541–543
Option arguments in short clusters cause false positives
Any dash token containing
rcounts, including values attached to options such as-pError(search pattern) or-+R(reset R to default). These report raw mode as on when less does not use it, so ANSI output passes through unfiltered.