Skip to content

Check whether less pager exists before trying to pipe content through it#6020

Merged
swissspidy merged 14 commits intowp-cli:mainfrom
benlk:fix/5333-benlk-only-more
Mar 10, 2026
Merged

Check whether less pager exists before trying to pipe content through it#6020
swissspidy merged 14 commits intowp-cli:mainfrom
benlk:fix/5333-benlk-only-more

Conversation

@benlk
Copy link
Copy Markdown
Contributor

@benlk benlk commented Nov 24, 2024

Problem

in the corner case where:

  1. wp-cli is running on a non-Windows system
  2. the PAGER environment variable is not set
  3. the command less is not installed
  4. the user triggers output of the wp help command:
    • by running that command explicitly
    • by running an invalid wp-cli command

wp-cli crashes, as documented in #5333

An example of an environment without less is many "minimalist" Docker server containers.

Changes

  • Fixes Command less not available on the current machine #5333 by removing the assumption that less exists in non-Windows environments when the environment variable $PAGER is not set. Instead, in all environments, invocations of wp help will first check to see if less exists, and use that, before falling back to more. The previous behavior was to pipe output through less -R on non-Windows systems without first checking if less exists.
  • Adds a docblock to Help_Command::pass_through_pager()

Alternatives considered

Replacing less -R with cat

This would replace a pager with a non-pager, which seems like a feature regression

Replacing less -R with more in all cases

Ruled out by @mrsdizzie at #6020 (comment), and removed in b88c438

Accurately checking whether less exists

I started a branch with this intent, at benlk@832bb1e , but this approach proved nonviable.

To accurately test whether less exists:

  • On Windows, we would need to add a test to wp-cli to determine whether wp-cli is running in cmd.exe or Powershell, as cmd.exe can use where to determine whether a command exists, but Powershell needs to use a different command
  • On POSIX systems, where command -v accurately determines whether a command exists, we would also need to check for the existence of an alias, which is a separate can of worms
  • In all cases, we would need to perform extensive checks on the return of the check, because proc_close() isn't guaranteed to return the command's exit code

This seemed like way too much scope creep, introducing too much code, requiring too much testing, for a fallback scenario around displaying a help message.

Testing

The existing tests in https://github.com/wp-cli/wp-cli/blob/main/features/help.feature do not care about whether more or less is used.

If additional tests are needed for this change, I'm open to suggestions on what should be tested.

For local testing, on all OS:

  1. Set up this branch according to https://make.wordpress.org/cli/handbook/contributions/pull-requests/#working-on-the-project-as-a-whole
  2. Run echo $PAGER to check what your local shell's PAGER variable is. If it is set to any value, including an emptystring, run unset PAGER to unset it.
  3. Run less to determine whether less exists on your system. If it does, run command -v less (POSIX) or where less (Windows) to determine whether it exists as a binary or as an alias.
  4. Run wp without any other commands or options
  5. Expect that the output of wp help is displayed. If less exists on your system, it should be paged in less. If less does not exist, but more does exist in your system, the output should be paged in more.

@benlk benlk requested a review from a team as a code owner November 24, 2024 21:45
@benlk
Copy link
Copy Markdown
Contributor Author

benlk commented Nov 24, 2024

Noting that, due to Thanksgiving, I will respond to comments on this PR in December.

@mrsdizzie
Copy link
Copy Markdown
Member

Thank you for the pull request.

I don't think it works to change the default pager since it would be a downgrade and create new issues for the majority of users:

  • more isn't guaranteed to have search (and when it does it isn't as good)
  • It doesn't process escape sequences which docs use heavily and we rely on less -R handling

So replacing less -R as a default would be a breaking change and is a no-go imo.

The standard PAGER env var already allows people to override this which seems like a fine tradeoff here given the small percent of overall users that are on linux and don't have less available. I agree it would be nice if it told users that instead of saying less: not found but I wouldn't consider that a crash or particularly cryptic error. less is just an intentional requirement unless you override it.

I think if you wanted to attempt to detect less it is OK if it isn't 100% reliable in every corner case, since if it works in 95% of an already small error case then it is that much better than it was without downgrading behavior for most existing users. We already have similar stuff elsewhere.

@benlk benlk changed the title Remove erroneous assumption that less exists on non-Windows systems Check whether less pager exists before trying to pipe content through it Dec 6, 2024
@benlk
Copy link
Copy Markdown
Contributor Author

benlk commented Dec 6, 2024

@mrsdizzie I've updated this to use the same Process-based mechanism you mentioned to detect whether less exists, with a conditional to use where on Windows.

Unfortunately, I don't have a Windows machine handy to test this change.

@codecov
Copy link
Copy Markdown

codecov bot commented Nov 2, 2025

Codecov Report

❌ Patch coverage is 73.68421% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
php/commands/src/Help_Command.php 73.68% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash in wp help when PAGER is unset and less is not installed by selecting an available pager at runtime instead of assuming less exists.

Changes:

  • Adds pager discovery logic (less -R if available, otherwise more) and reuses it when PAGER is unset.
  • Introduces a helper to detect whether a given binary exists using a platform-specific command.
  • Adds a docblock to Help_Command::pass_through_pager().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +160 to +170
public static function locate_pager() {
static $pager = null;

if ( empty( $pager ) ) {
if ( self::binary_exists( 'less' ) ) {
// less is not available in all systems
$pager = 'less -R';
} else {
// more is part of the POSIX definition, and is also available on Windows.
$pager = 'more';
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes a crash when PAGER is unset and less is missing, but the existing features/help.feature scenarios don’t exercise that environment (they’ll typically run on hosts where less exists). Consider adding a regression test that runs wp help with PAGER unset and a PATH that makes less unavailable, to prevent this from reappearing.

Copilot uses AI. Check for mistakes.
benlk and others added 5 commits February 3, 2026 12:57
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@swissspidy

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a crash that occurs when the less command is unavailable by implementing a check for its existence and providing a fallback to more. The changes are well-structured, introducing binary_exists() and locate_pager() helper methods to encapsulate the logic. The approach is sound and effectively resolves the reported issue. I have one minor suggestion to improve code conciseness.

Comment on lines +142 to +149
if ( 0 !== $result->return_code ) {
// We could not reliably determine that the binary exists
return false;
} else {
// POSIX binaries: command -v will return the path and exit 0
// aliases: command -v may return the alias command and exit 0
return true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This if/else block can be simplified to a single return statement. This will make the code more concise and easier to read.

        return 0 === $result->return_code;

@swissspidy swissspidy merged commit 891114f into wp-cli:main Mar 10, 2026
68 checks passed
@swissspidy swissspidy added this to the 3.0.0 milestone Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Command less not available on the current machine

5 participants