Using vim as a man-page viewer under Unix

From Vim Tips Wiki

Jump to: navigation, search
Tip 167 Printable Monobook Previous Next

created 2001 · complexity intermediate · author Charles E. Campbell, Jr. · version 7.1


To use Vim as a man-page viewer involves setting an environment variable and adding a line to your .vimrc file.

Add the following line to your vimrc:

let $PAGER=''

You need to do this to clear the PAGER environment variable inside of Vim. This is to handle the case where you start Vim normally and want to use Vim's "Man" function.

bash, ksh, and Bourne variants add to .bashrc, .kshrc, etc.:

export PAGER="/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>' -\""

csh, tcsh, and C-shell variants add to .cshrc:

setenv PAGER /bin/sh\ -c\ \"unset\ PAGER\;col\ -b\ -x\ \|\ vim\ -c\ \'set\ ft=man\ nomod\ nolist\'\ -\"

fish add to .config/functions/config.fish

set -x PAGER "/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>' -\""

The man pages will then be displayed with Vim called as "view" and will use the <man.vim> syntax highlighting. I myself use some additional highlighting which is enabled by putting the following file into <.vim/after/syntax/man.vim>. I usually use the astronaut colorscheme; those who use bright backgrounds may find the colors selected for manSubSectionStart and manSubSection something they'll want to change:

" DrChip's additional man.vim stuff
syn match manSectionHeading "^\s\+[0-9]\+\.[0-9.]*\s\+[A-Z].*$" contains=manSectionNumber
syn match manSectionNumber "^\s\+[0-9]\+\.[0-9]*" contained
syn region manDQString start='[^a-zA-Z"]"[^", )]'lc=1 end='"' contains=manSQString
syn region manSQString start="[ \t]'[^', )]"lc=1 end="'"
syn region manSQString start="^'[^', )]"lc=1 end="'"
syn region manBQString start="[^a-zA-Z`]`[^`, )]"lc=1 end="[`']"
syn region manBQSQString start="``[^),']" end="''"
syn match manBulletZone transparent "^\s\+o\s" contains=manBullet
syn case match
syn keyword manBullet contained o
syn match manBullet contained "\[+*]"
syn match manSubSectionStart "^\*" skipwhite nextgroup=manSubSection
syn match manSubSection ".*$" contained

hi link manSectionNumber Number
hi link manDQString String
hi link manSQString String
hi link manBQString String
hi link manBQSQString String
hi link manBullet Special
hi manSubSectionStart term=NONE cterm=NONE gui=NONE ctermfg=black ctermbg=black guifg=navyblue guibg=navyblue
hi manSubSection term=underline cterm=underline gui=underline ctermfg=green guifg=green

set ts=8

[edit] Comments

As part of the man filetype plugin delivered in Vim 6.0, the user command :Man is setup to view man pages in a similar fashion. (On Unix) I've sym-linked the man.vim filetype plugin from the distribution into the plugin directory. That was the :Man command is available whenever you need it.

runtime ftplugin/man.vim
source $VIMRUNTIME/ftplugin/man.vim
e? :]

I had to use PAGER variable instead of MANPAGER. Version of the man tool I use is 2.3.10. People who would like to try this may like to check tip VimTip121 too.


Some notes:

1. Some versions of sh don't support setting environment variables and exporting on the same line. In that case, you'd have to do:

> MANPAGER="col -b | view -c 'set ft=man nomod nolist' -"
> export MANPAGER

2. Another comment mentioned that their man doesn't support the MANPAGER env var, so they had to use PAGER. You probably don't want to do that on a permanent basis, since PAGER is used for many other things besides man. Instead, you might create a small script in your $HOME/bin that sets it in a subshell, for example (vman.sh):

#!/bin/sh
PAGER="col -b | view -c 'set ft=man nomod nolist' - "
export PAGER
man $*

and then do 'vman ls' or whatever. Replace PAGER with MANPAGER if your man supports it and you want to use the script.

3. You might want to add ignorecase to the list of settings passed to Vim (view) to more closely match the searching of most man pagers (less and more).


Even simpler way

What I did was:

1) renamed my less to less.orig 2) edited the less.sh script :

if test $# = 0; then
 vim -c 'so $VIMRUNTIME/macros/less.vim' -
elif test $* = "-is"; then
 less.orig $*
else
 vim -c 'so $VIMRUNTIME/macros/less.vim' $*
fi

3) symlinked $VIMRUNTIME/macros/less.sh to /usb/bin/less

So as you can see when the man is called, it just passes the parameters to less.orig.


On my Red Hat 7.2 system, view invokes vi (vim in vi compatibility mode), so extra Vim features such as syntax highlighting are not available. To use vim instead of vi for the pager, either manipulate the /bin/view link, or set substitute "vim -R" for "view".


Replace view with less.sh of Vim will maintain the same keystrokes as less. The following set the MANPAGER for sh, ksh and bash:

export MANPAGER="col -b | /usr/share/vim/vim61/macros/less.sh -c 'set ft=man nomod nolist' -"

There's now a while-you're-in-vim solution -- check out script#489 for <Manpageview.vim> for a new :Man command and support for the K normal-mode command.


Using MANPAGER doesn't work so well with script#489 instead, I now use a Korn shell function. Similar functions could be developed for other shells (bash, zsh), I'm sure:

# man:
function man
{
/usr/bin/man $* | col -b | /usr/local/bin/view -c 'set ft=man nomod nolist' -
}

I have done the following to make Vim work as my PAGER and it works really well. Like other people in this thread my man(1) doesn't use MANPAGER, it uses PAGER. I had trouble with vim's filetype autodetection picking up that it was indeed a manpage coming in over the pipe, so I've written a scripts.vim to match manpages by regex and set the filetype accordingly. Otherwise, I got no syntax highlighting. The shell I quote is tcsh-specific, but easily portable to another shell. Also, I assume you already have a ~/bin and that it is in your path and that you already have a ~/.vim. If not, you will need to do these things.

% ln -s /path/to/VIMRUNTIME/macros/less.sh ~/bin/vless
% cat >> ~/.vim/scripts.vim
if did_filetype()
    finish
endif
if getline(1) =~ '^\(.\+\)(\d\{1}).\+\1(\d\{1})$'
    set filetype=man
endif
^D
% cat >> .cshrc
# config pager
if (-X vless && -X col) then
    setenv PAGER 'col -b | vless'
    alias less vless
    alias more vless
else if (-X less) then
    setenv PAGER less
    setenv LESS "-e"
    alias more less
else if (-X more) then
    setenv PAGER more
else
    echo "WARNING: No pager found, PAGER not set."
endif
^D

Actually, here's a smarter way to do that scripts.vim (the original was taken from the Vim manual |new-filetypes-scripts|):

if did_filetype() " filetype already set..
elseif getline(1) =~ '^\(.\+\)(\d\{1}).\+\1(\d\{1})$'
 set filetype=man
endif

The previous example works but wouldn't allow you to add anything else to your scripts.vim.


I've been using brandon's little script for a while but I modified it with the help of this little sh script:

#!/bin/bash
#
# timball

MAN=/usr/bin/man

{
 if [ $1 = "-k" ]; then
 $MAN -k $2
 exit
 else
 if [ $TERM = "screen" ]; then
 screen $MAN -P "col -b | view -R --noplugin -u ~/lib/vim/vman.vim -" $1
 exit
 else
 $MAN -P "col -b | view -R --noplugin -u ~/lib/vim/vman.vim -" $1
 exit
 fi
 fi

}

To avoid the problems with Vim in the PAGER or MANPAGER variable, use the following bash-function:

vman() { man $* | col -b | vim -c 'set ft=man nomod nolist' -; }

If you view a manpage within Vim now, the K-button will work right.


In bash, adding:

alias man='vman'

... after the vman function, in your .bashrc file, will let you use the man command again. Simply renaming the vman function to 'man' gave me a string of errors.


When using UTF-8 as your locale, bad things happen. So this is how to make it work:

function man {
 /usr/bin/man $* | col -bp | iconv -c | view -c 'set ft=man nomod nolist' -
}

, August 21, 2003 23:15


If MANPAGER does not work and PAGER should not be used for the aforementioned good reasons then the lucky ones with GNU man simply write (csh)

 alias man
'/usr/bin/man -P "col -bp | iconv -c | view -c '"'"'set ft=man nomod nolist'"'"' -" \!*'

(this is tick-quotes-tick-quotes-tick in the middle) resp. (sh)

 alias man="/usr/bin/man -P \"col -bp | iconv -c | view -c 'set ft=man nomod nolist' -\""

and the ones without write (csh)

 alias man 'env PAGER="col -bp | iconv -c | view -c '"'"'set ft=man nomod nolist'"'"' -" man \!*'

resp. (sh)

 alias man="env PAGER=\"col -bp | iconv -c | view -c 'set ft=man nomod nolist' -\" /usr/bin/man"

and are done.

And with the SunOS 5 man(1) from SunOS 5 it is:

alias man 'env PAGER="( col -bp | view -c '"'"'set ft=man nomod nolist'"'"' - ) < " /usr/bin/man \!*'

(and analogously for sh) since this man(1) calls PAGER with the name of a temporary file...


If you are following Kerosin's advice above, make sure you use "/usr/bin/man" instead of just "man" so you won't get circular aliasing. That bug brought my machine to it's knees.

vman() { /usr/bin/man $* | col -b | vim -c 'set ft=man nomod nolist' -; }
alias man='vman'

Nice. I added this little tidbit "-c 'nmap q :q<CR>'" so that I can quit with one keystroke like I did in the old days with less...

vman() { /usr/bin/man $* | col -b | vim -c 'set ft=man nomod nolist' -c 'nmap q :q<CR>' -; }
alias man='vman'

There's probably more than one way to handle this, but instead of calling all sorts of bits'n'pieces I prefer this:

# call Vim, ensure that ftplugin/man.vim is loaded, call Man with default manpage=man if no args, make sure this is only window
function vman ()
{
 vim -c "runtime ftplugin/man.vim" -c "Man ${1-man}" +"wincmd o"
}

One may also use manpageview script#489 in a like manner:

function man
{
vim -c "Man $*" -c only
}

For those who have g:manpageview_winopen="only", a preferred way to get command line man is to:

vim -c "Man $*" -c "silent! only".

Avoids a "Already only one window" message.


When using the shell function described above, you launch Vim even when there is no man pages for the words you typed. The following code will correct that:

vman() {
 if [ $# -eq 0 ]; then
 /usr/bin/man
 elif whatis $* ; then
 /usr/bin/man $* | col -b | vim -c 'set ft=man nomod nolist' -
 fi
}
alias man='vman'

This does not work on Debian and Ubuntu Linux systems, but it is trivial to fix. Technically, PAGER and MANPAGER are not guaranteed to be passed to a shell, so you don't know that the pipe from 'col' to 'view' would work. On some systems PAGER is run under a shell, but on others PAGER is executed directly like any external command. The trick is to add a /bin/sh to make sure that the pipe gets interpreted. This works on almost any Linux flavor:

export PAGER="/bin/sh -c \"col -b | view -c 'set ft=man nomod nolist' -\""

Yet another variant. Together with manpageview script I'm using the following function for bash.

function man
{
 /usr/bin/whatis "$@" >/dev/null

 if [ $? -eq 0 ]; then
 vim -c "Man $*" -c 'silent! only' -c 'nmap q :q<CR>'
 else
 man "$@"
 fi
}

Note. I had to modify "whatis" script so that it sets non-zero exit status when it found nothing appropriate.


If you have a error like that ..

Reformatting man(1), please wait...
col: invalid option -- c
usage: col [-bfhpx] [-l nline]
man: command exited with status 256: /usr/bin/zsoelim /tmp/zmanGiFFlw | /usr/bin/tbl
| /usr/bin/nroff -mandoc -rLL=89n -rLT=89n -Tutf8 | col -b | view -c set ft=man
nomod nolist titlestring=MANPAGE -

then the solution is ... this $PAGER definition makes the assumption that it's passed to sh -c (you use pipes and quotes). The man manpage doesn't say that $PAGER is passed to sh -c, it says it will use $PAGER as the program to display the manual page.

I suggest you use:

export PAGER="sh -c \"col -b | view -c 'set ft=man nomod nolist titlestring=MANPAGE' -\""

which explicitely calls sh -c to handle pipes and quotes in the expected way.

You may also use your own /usr/local/bin/pager with:

#!/bin/sh

col -b | view -c 'set ft=man nomod nolist titlestring=MANPAGE' -
and with PAGER=/usr/local/bin/pager.

I am reassigning to man for the man manpage to be clarified with respect to the way $PAGER is called.

copy from http://www.gatago.com/linux/debian/devel/10008053.html


On OS X 10.5, using Terminal.app, append this to your ~/.bash_profile to use vi (Vim) as your MANPAGER.

export MANPAGER='col -bx | vim -c ":set ft=man nonu nolist" -R -'

You might want to add

-c 'set nonumber'

in the export PAGER=... command in your .bashrc file.

Personal tools