33

I want to be able to read man pages in Vim.

For some reason, it seems that Vim isn't able to read the output of programs through piping. E.g (man ls) | vi doesn't seem to work, bonus points for somebody who can explain why.

To get around this, I've been using the following little script:

tempo = `mktemp`
man $1 > $tempo ; vi $tempo

This script uses temporary files which I guess work fine, but I was wondering if there was a good way to read man pages in Vim without resorting to creating temporary files

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
MYV
  • 4,294
  • 6
  • 28
  • 24

11 Answers11

48

Vim includes a man page viewer, :Man, in its runtime files.

Put this line in your vimrc:

runtime! ftplugin/man.vim

Now you can read syntax-highlighted man pages inside Vim by running :Man. For example:

:Man 3 printf

Even better, you can just place your cursor on a word in the buffer and press <Leader>K (\K) to see the man page for that word.

See :h find-manpage for complete usage and installation instructions.

glts
  • 21,808
  • 12
  • 73
  • 94
  • 4
    [Vim SuperMan](https://github.com/Z1MM32M4N) is a convenient vim plugin that wraps this plugin's functionality so that you can also open man pages from the command line (without opening Vim first) – jez Dec 22 '14 at 14:09
  • 1
    That one went private, looks like there's one at jez/vim-superman – John P Jan 24 '17 at 17:18
45

For some reason, it seems that vim isn't able to read the output of programs through piping […]

According to the man-page, you need to specify a file of - to get it to read from standard input; so:

man ls | vi -

If that doesn't work, you might try using process substitution:

vi <(man $1)

which creates a sort of pseudo-file and passes it to vi.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • Thank you, good answer and a good explanation. I'll make sure to read man pages a bit more carefully in the future :) – MYV May 24 '13 at 17:17
  • 3
    @Maksim: You're welcome! Incidentally, many other utilities also use of `-` to mean "standard input". I guess you haven't needed to use that so much, because usually they'll also use standard input as a default if you don't specify *any* filename. `vi` is an exception in that respect, which can be confusing. :-) – ruakh May 24 '13 at 17:56
17

On my system (Mac OS X), I found that the above left control characters in the output. Instead I used:

export MANPAGER="col -b | vim -MR - "

then just e.g.

man vim

The vim options turn off modifying the buffer and make it read-only. This stops vim complaining if you try to exit with ":q" (you can use :q! of course, but you might as well set the options).

This is also handy for general use - I have the following. The -c command names the buffer, just for completeness.

alias vimpager="vim -MR -c 'file [stdin]' -"
Rory Hunter
  • 3,425
  • 1
  • 14
  • 16
  • 1
    I think this should be the answer as it answers the question of how to read man pages in vim. Bonus points for not requiring you to change anything in your normal man invocation. – Jacob Degeling Sep 14 '16 at 03:04
  • 2
    Adapted from [here](https://muru.dev/2015/08/28/vim-for-man.html), making the command work for Neovim on Linux and setting the window title (`titlestring`) to the name of the man page, for example `bash(1)`: `export MANPAGER='nvim -c "%! col -b" -c "set ft=man nomod | let &titlestring=$MAN_PN"'` – Matthias Braun Oct 02 '21 at 11:36
  • Since a few days ago on Arch Linux, the command using `col -b` leaves artifacts like "1m" or "4m22m" in the output. `MANPAGER='nvim +Man!'` works. I learned about that plugin [here](https://unix.stackexchange.com/questions/487415/viewing-man-pages-in-vim#612930). See the plugin's [documentation](https://neovim.io/doc/user/filetype.html#ft-man-plugin) regarding usage (it supports navigation). – Matthias Braun Jul 12 '23 at 12:14
7

Here is what I did: I've made a function in my .bashrc:

vman() { vim <(man $1); }

When I call vman this automatically calls Vim showing the man page. It works great.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
nacholibre
  • 3,874
  • 3
  • 32
  • 35
  • 1
    To set the title of Vim's window to the name of the program whose man page you're looking at (instead of the path of the file descriptor), use this: `vim -c ":set titlestring=$1" <(man "$1")` – Matthias Braun Sep 07 '21 at 19:56
  • I also suggest adding a syntax parameter: `vim -c ":set titlestring=$1" -c ":set syntax=man" <(man "$1")` – yaeuge Dec 20 '22 at 18:46
4

Your example code is wrong.

   tempo=`mktemp`
   man $1 > $tempo; vi $tempo

But you really only need

   man $1 | vi -
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
Otto Allmendinger
  • 27,448
  • 7
  • 68
  • 79
4

By default vim reads vimscripts (=vim commands), not input files, from stdin. That is why you cannot directly pipe man output to vim; as others have mentioned you have to use vim - to make vim read from stdin.

However piping vimscripts can be useful too:

vim test.txt <<EOF
:%s/[aiueo]/X/g
:wq! output.txt
EOF

The above will use vim to open test.txt, replace all vowels with X, write the results to output.txt, and quit (ignoring changes to the original file). It uses a here document but you can of course put the vim commands in a file and use vim test.txt < myscript or cat myscript | vim test.txt to achieve the same result.

I suspect the reason they did it this way was that you can open multiple input files but only execute one script. If input was read from stdin by default, you could only read one buffer that way.

Anders Johansson
  • 3,926
  • 19
  • 19
4

You also can press shift-k on your c function to print the man page

albttx
  • 3,444
  • 4
  • 23
  • 42
2

I combined others answers, I am using

vman() {
    export MANPAGER="col -b" # for FreeBSD/MacOS

    # Make it read-only
    eval 'man $@ | vim -MR +"set filetype=man" -'

    unset MANPAGER
}

Usage:

vman ls
Green Bird
  • 179
  • 2
  • 6
1

I have a better solution, the one that I used, it is like this:

/bin/sh -c "unset PAGER;col -b -x | vim -R -c 'set ft=man nomod nolist' -c 'map q :q<CR>' -c 'map <SPACE> <C-D>' -c 'map b <C-U>' -c 'nmap K :Man <C-R>=expand(\"<cword>\")<CR><CR>' -"

Hope you'll enjoy it.

guitarpoet
  • 395
  • 1
  • 5
  • 12
0

You can always use info command for info pages and do info {cmd} | vim.

andrewgazelka
  • 1,746
  • 1
  • 16
  • 26
0

A lot of good answers, with respect to plugins it's worth to add that vim-man* provides a set of convenience functions to open and read man pages:

Viewing man pages, as per docs.

  • :Man printf - open printf(1) man page in a split
  • :Vman 3 putc - open putc(3) man page in a vertical split
  • :Man pri<Tab> - command completion for man page names

* Available on GitHub: https://github.com/vim-utils/vim-man.

Konrad
  • 17,740
  • 16
  • 106
  • 167