MANPAGER won't work on Mandoc's man implementation
Bumbadawg opened this issue · 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
#!/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
.
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"
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.
@lahwaacz's approach of putting it in a separate script is the only solution to having this work with mandoc
.
exec cat "$@" | col -bx | bat --language man --style plain --pager "$PAGER"
Or this for better performance:
#!/bin/sh
if [ -f "$1" ]; then
col -bx < "$1" | bat --language man --plain
else
col -bx | bat --language man --plain
fi
Or this for better performance:
Did you actually measure it?
In any case, [ -f "$1" ]
seems like a wrong condition: if there is no file but stdin, there is no $1
itself.
In any case,
[ -f "$1" ]
seems like a wrong condition: if there is no file but stdin, there is no$1
itself.
what else is the else clause
for?
The code means: if the input
is a file
then take the file, otherwise take the stdin
Did you actually measure it?
Do I have to? One must be processed through cat
and then col
, while the other just goes through col
In any case,
[ -f "$1" ]
seems like a wrong condition: if there is no file but stdin, there is no$1
itself.what else is the
else clause
for? The code means: if theinput
is afile
then take the file, otherwise take thestdin
You should not check if $1
is a file, but if there is actually any input. Find out what $#
is... 😉
Did you actually measure it?
Do I have to? One must be processed through
cat
and thencol
, while the other just goes throughcol
And you have added one shell condition instead. What do you think is faster: cat
or [ -f "$1" ]
?
Hey, so you have so much free time in your life huh?
It just bothered me when you don't understand the code and saying it's wrong. It's not wrong. See, after you figure out what my code means, you already improve it. Good learning for you, right? 😉
I'll take your offer then
#!/bin/sh
if [ $# -eq 0 ]; then
col -bx | "$BAT_BIN" --language man --plain
else
col -bx < "$1" | "$BAT_BIN" --language man --plain
fi
And you have added one shell condition instead. What do you think is faster:
cat
or[ -f "$1" ]
?
Isn't it obvious? But sure, have it your way.. I don't have much time and energy for something like this
For others: In ubuntu, bat
is actually batcat
, so set BAT_BIN
to bat
or batcat
depends on your environment.
I don't have much time and energy for something like this
Yeah it is much easier to claim something without actually verifying that it is true. I can as easily claim that there is no actual benefit in terms of performance.
You are all the way right 😉