Skip to content

On Linux, only the help function respects the PAGER env var. #26375

@sebastiancarlos

Description

@sebastiancarlos

Prerequisites

Steps to reproduce

I think ideally, Out-Host -Paging should use the same logic as the help function.

For what it's worth, I think the help implementation has the correct logic:

`help` implementation
PS> (Get-Command help).Definition

    {
        # By default use more on Windows and less on Linux.
        $pagerCommand = 'less'
        $pagerArgs = '-s','-P','Page %db?B of %D:.\. Press h for help or q to quit\.'

        # Respect PAGER environment variable which allows user to specify a custom pager.
        # Ignore a pure whitespace PAGER value as that would cause the tokenizer to return 0 tokens.
        if (![string]::IsNullOrWhitespace($env:PAGER)) {
            if (Get-Command $env:PAGER -ErrorAction Ignore) {
                # Entire PAGER value corresponds to a single command.
                $pagerCommand = $env:PAGER
                $pagerArgs = $null
            }
            else {
                # PAGER value is not a valid command, check if PAGER command and arguments have been specified.
                # Tokenize the specified $env:PAGER value. Ignore tokenizing errors since any errors may be valid
                # argument syntax for the paging utility.
                $errs = $null
                $tokens = [System.Management.Automation.PSParser]::Tokenize($env:PAGER, [ref]$errs)

                $customPagerCommand = $tokens[0].Content
                if (!(Get-Command $customPagerCommand -ErrorAction Ignore)) {
                    # Custom pager command is invalid, issue a warning.
                    Write-Warning "Custom-paging utility command not found. Ignoring command specified in `$env:PAGER: $env:PAGER"
                }
                else {
                    # This approach will preserve all the pagers args.
                    $pagerCommand = $customPagerCommand
                    $pagerArgs = if ($tokens.Count -gt 1) {$env:PAGER.Substring($tokens[1].Start)} else {$null}
                }
            }
        }

        $pagerCommandInfo = Get-Command -Name $pagerCommand -ErrorAction Ignore
        if ($pagerCommandInfo -eq $null) {
            $help
        }
        elseif ($pagerCommandInfo.CommandType -eq 'Application') {
            # If the pager is an application, format the output width before sending to the app.
            $consoleWidth = [System.Math]::Max([System.Console]::WindowWidth, 20)

            if ($pagerArgs) {
                $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand $pagerArgs
            }
            else {
                $help | Out-String -Stream -Width ($consoleWidth - 1) | & $pagerCommand
            }
        }
        else {
            # The pager command is a PowerShell function, script or alias, so pipe directly into it.
            $help | & $pagerCommand $pagerArgs
        }
    }

Expected behavior

$ PAGER='bat --paging=always' pwsh # or any other custom pager
PS> help help
# output using the bat pager
<CTRL-D>

$ PAGER='bat --paging=always' pwsh
PS> Get-Process | Out-Host -Paging
# output using the bat pager

# Note how 'more' and 'less' are hardcoded applications. This might be fine
# actually
PS> (Get-Command more).Definition
/usr/bin/more
PS> (Get-Command less).Definition
/usr/bin/less

Actual behavior

$ PAGER='bat --paging=always' pwsh # or any other custom pager
PS> help help
# output using the bat pager
<CTRL-D>
$ PAGER='bat --paging=always' pwsh

PS> Get-Process | Out-Host -Paging
# The main pager always use 'more' no matter what (!!)
# output using 'more' pager

# Note how 'more' and 'less' are hardcoded applications. This might be fine
# actually
PS> (Get-Command more).Definition
/usr/bin/more
PS> (Get-Command less).Definition
/usr/bin/less

Error details

Environment data

Name                           Value
----                           -----
PSVersion                      7.5.4
PSEdition                      Core
GitCommitId                    7.5.4-0-g7c8d9e7e0ed2fc1f2caf50746fe9fef720ca2a0a
OS                             Arch Linux
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs-TriageThe issue is new and needs to be triaged by a work group.WG-Cmdletsgeneral cmdlet issuesWG-NeedsReviewNeeds a review by the labeled Working Group

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions