sharkdp/bat

MANPAGER won't work on Mandoc's man implementation

Bumbadawg opened this issue ยท 8 comments

What version of bat are you using?
0.15.4

Describe the bug you encountered:
Using export MANPAGER="sh -c 'col -bx | bat -l man -p'"
results in -bx: 1: Syntax error: Unterminated quoted string

Describe what you expected to happen?
paging with bat

How did you install bat?
Void Linux package manager

** The bug **
It was already reported here for Termux, and it coudl well be the case for Alpine and other Mandoc's man implementations cases.
See termux/termux-packages#4781 (comment)

** Lazy solution **
Instead of recompiling man from GNU (https://www.nongnu.org/man-db/development.html)
one can be using export MANPAGER='nvim +Man!'

Thank you for reporting this.

This is not a bug in bat. This implementation of man is currently not supported. This should probably be documented.

It does not work because mandoc does not do shell tokenization of the $MANPAGER string, it just splits it into a list of words and passes them to execvp. So the error comes from sh which complains about an unterminated quoted string from the word 'col.

bat itself does not have any problems displaying the output of mandoc's man command, you just have to configure the pager appropriately. This can be done by putting the following in a wrapper script and then export MANPAGER="your_wrapper":

#!/bin/sh
cat "$1" | col -bx | bat --language man --style plain
eth-p commented
#!/bin/sh
cat "$1" | col -bx | bat --language man --style plain

Not that performance matters much for a shell script like this, but you can even cut out the cat invocation:

col -bx < "$1" | bat --language man -p

If you don't have col installed, it's shipped as part of heirloom-doctools.

ju1ius commented

col -bx < "$1" | bat --language man -p

Or:

#!/bin/sh
exec col -bx | bat -pl man

col -bx < "$1" | bat --language man -p

Or:

#!/bin/sh
exec col -bx | bat -pl man

These two commands are not equivalent - the former reads from a file denoted by $1 and the latter reads from stdin. The former is required for mandoc, the latter may be required for other things that use $MANPAGER (e.g. using the help function in an ipython shell). The following can be used as a universal solution (note that cat here is not as useless as in #1145 (comment)):

#!/bin/sh

# mandoc passes a file name, other tools write to stdout
# using `cat "$@"` we take care of both reading from file and stdin
exec cat "$@" | col -bx | bat --language man --style plain --pager "$PAGER"

@lahwaacz Thanks, this solution works wonderfully!

As part of my investigation into other man-related issues, I figured out why the mandoc implementation doesn't work:

It does extremely simple shell splitting for the MANPAGER variable, which makes it impossible to escape spaces.

image

@lahwaacz's approach of putting it in a separate script is the only solution to having this work with mandoc.