Using Vim as $MANPAGER

Created On:

The default pager for man is less. Unfortunately when using less as the pager there is no coloring of the man page, no folding of sections and no way to copy text. Reading man pages would be more enjoyable if man could use a pager that had those features.

This can be easily fixed by using vim as the pager for man. If you read the man page for man we can see that setting the $MANPAGER environment variable allows us to change which pager man uses. To use vim as the pager, just place the following code in your ~/.bash_profile:

export MANPAGER="col -b | vim -c 'set ft=man ts=8 nomod nolist nonu' -c 'nnoremap i <nop>' -"

The above command does a few things. First it uses the col utility to remove extra ^H (backspace) characters because they are not handled correctly by vim. Next we pipe the output into vim and we set a few options:

  1. ft=man enables the coloring of the man page.
  2. ts=8 ensures the width of tab characters matches less.
  3. nomod removes the modification warning when trying to quit.
  4. nonu removes line numbers.
  5. nolist disables listchars so trailing whitespace and extra tabs are not highlighted.
  6. nnoremap i <nop> ensures that we do not accidentally enter insert mode when viewing the man page.

This solution is better than others because it does not involve doing crazy things like writing a shell function for man or aliasing man to some other command. This solution instead uses the provided environment variables to modify the behaviour of man.

Before

After

Edit

Thanks to Jamie Wong my snippet can be modified. Instead of doing a little hack to prevent us from entering insert mode with nnoremap i <nop> we can enable the noma setting. This sets the buffer to not be modifiable. Since the buffer is not modifiable we cannot enter insert mode or modify the buffer at all. With this change the $MANPAGER variable is set to:

export MANPAGER="col -b | vim -c 'set ft=man ts=8 nomod nolist nonu noma' -"

Edit 2

As Peter Lundgren and some redditors have discovered this value of $MANPAGER does not work when using GNU man because it does not allow pipes for the command. The above does work for BSD man but if you want it to work for GNU man or both you need to change the value to a single command. The following snippet folds the above value into a single shell command.

export MANPAGER="/bin/sh -c \"col -b | vim -c 'set ft=man ts=8 nomod nolist nonu noma' -\""

Note: Disqus has been removed from this blog, but below is a copy of some of the comments on this post for posterity.


Jamie Wong

Instead of "nnoremap i <nop>", you can just use "nomodifiable" in the options. (shortform is noma).

So the modified command would be:

export MANPAGER="col -b | vim -c 'set ft=man ts=8 nomod nolist nonu noma' -"

this prevents you from going into insert mode completely (which disables more things than just i). See :help noma

qwertyboy

I just set the buftype to nofile, which lets me edit and play but does not change any files.

Nathaniel Bounds

Neat idea, but it wouldn't work for me: http://pastie.org/5603077#2

Peter Lundgren

You can't use pipes in PAGER or MANPAGER. Either put it in a shell script or try this:

export MANPAGER="/bin/sh -c \"col -b | vim -c 'set ft=man ts=8 nomod nolist nonu noma' -\""

Zameer Manji

Good catch, this seems to be a difference between the BSD and GNU versions of man. The BSD version does let you use pipes in MANPAGER but the GNU version does not.

alcarney

Great tip!

How do you get sections of the man page to fold though?
And how do you configure the statusbar to look somewhat like yours?

Zameer Manji

For folding to occur I set the folding method to 'indent'. See :h fdm for more information.

My status bar is a result of the powerline plugin: https://github.com/Lokaltog...

alcarney

Thanks :)

Cliff Erson

Amazing tip!

I got this from #vim. It maps q to :q in insert mode, quick quit. I noticed my muscle memory after having typed 'man' was always q and not :q

export MANPAGER=col -b | vim -c 'set ft=man ts=8 nomod nolist nonu noma' -c 'nmap q :q<cr>' -

Eric Boehs

I ended up coming up with my own. I use -x on col which converts tabs to spaces. I don't think ts=8 is needed then (at least I haven't noticed). nonu didn't seem to work with my config, so I omitted it. And instead of nomod and noma I use -MR. I also used the GNU compatible syntax since I use my dotfiles on both OS X and Linux. Here's the final script:

export MANPAGER="sh -c \"col -bx | vim -c 'set ft=man nolist' -MR -\""

And if you just want OS X:

export MANPAGER="col -bx | vim -c 'set ft=man nolist' -MR -"

I scoured the web for other configs to end up here.

If you like his indent folding add fdm=ident in the set list.

Finally, you may want to set your regular pager to vim:

export PAGER="/usr/share/vim/vim*/macros/less.sh"
Chris O'Neil

Awesome post!

jc00ke

Maybe it's something to do with fish or neovim, but these didn't work for me. However, https://github.com/nhooyr/n... did work. Either way, great idea!

yee-boy

Edit 2's command changes the manpager, but only for that current terminal instance. That is, the change does not persist between terminal instances. I am using gnome-terminal in Ubuntu 16.04. Does anyone have any advice?

Andi Hafner

Showing line numbers

Great stuff so far, thanks.

But I prefer to let vim showing line numbers enabled, as it is one of vim's great features, to be able to jump to a specific line number quite quickly. (e.g.

80gg<cr>

to jump to line number 80 inside the document).

As this is obviously done by leaving out 'nonu' from the options settings, you may then run into an ugly wrapped document, as the manual pager formats its output to page width before vim inserts its line numbers.

As workaround against this issue you can set the MANWIDTH environment variable accordingly. (e.g.

export MANWIDTH=80

inside .bashrc).