sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #167: Using vim as a man-page viewer under Unix

 tip karma   Rating 308/102, Viewed by 16312 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   November 21, 2001 7:29      complexity:   intermediate
author:   Charles E. Campbell, Jr.      as of Vim:   6.0

To use vim as a man-page viewer involves setting an environment variable:

    sh, ksh:  export MANPAGER="col -b | view -c 'set ft=man nomod nolist' -"
    csh    :  setenv MANPAGER "col -b | view -c 'set ft=man nomod nolist' -"

Put one of the above two lines into your <.profile> or <.login> file as
appropriate for your shell.

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 (also available from this archive);
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
  ---------------------------------------------------------------------

 rate this tip  Life Changing Helpful Unfulfilling 

<< Mapping caps lock to esc in XWindows | Viewing the actual XPM data in GVIM >>

Additional Notes

Douglas Potts <[email protected]>, November 26, 2001 6:10
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.

Hope that was useful.
Alper Ersoy <[email protected]>, December 1, 2001 0:38
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 #121 too.
[email protected], January 30, 2002 11:24
Two things:

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).

Ok, I lied - 3 things.
supergrass@gmx.net, February 9, 2002 3:36
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

simple, fast works

have phun :)
[email protected], May 16, 2002 20:00
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".
[email protected], August 14, 2002 9:00
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' -"



[email protected], October 3, 2002 19:19
The original tip works great for me (export MANPAGER="col -b | view -c 'set ft=man nomod nolist' -"), however, if I then try ':Man some-man-page' inside vim after executing man from the shell, I get the following in the window:

Vim: Warning: Input is not from a terminal
^M
Error executing formatting or display command.
System command (cd /usr/man && (echo ".pl 11i"; /bin/gunzip -c '/usr/man/man3/puts.3.gz') | /usr/bin/gtbl | /usr/bin/nroff -S -mandoc | col -b | view -c 'set ft=man nomod nolist' -) exited with status 256.
No manual entry for fputc
?47h?1hmH2J24;1H"-stdin-" [RO] 64L, 1791C1;24rmH2J24;1H?1l2J?47lVim: Error reading input, exiting...
Vim: Finished.
24;1HVim: Reading from stdin...

[Somewhat paradoxically, this occurs only if the man page *does* exist, teehee; if it doesn't, I just get a line telling me 'Cannot find a 'foo'.' in the command-line area.]

I assume it's because :Man doesn't like vim/view being in the MANPAGER, so my current messy workaround is 'let $MANPAGER="/usr/bin/less"' in ~/.vimrc; does anyone have a better solution?  Being able to use K to jump around the manpages is the major reason why I want to use vim as the manpager ;)
Anonymous, November 7, 2002 22:41
I'm having the same problem as ajw. Seems that it's either ":Man", or vim as pager for man from the command line. Making sure that MANPAGER is only set for interactive shells, and then doing "let $MANPAGER='/usr/bin/less'" in .vimrc does help some, as ajw suggests, but it means that you're stuck with less once you've jumped out of the first man page via K. Anybody know how to make vim as MANPAGER and ":Man" from man.vim play nice together?
[email protected], November 27, 2002 6:56
There's now a while-you're-in-vim solution -- check out
vimscript#489 for <Manpageview.vim> for a new :Man command
and support for the K normal-mode command.
Anonymous, December 18, 2002 3:04
Great!
[email protected], December 27, 2002 7:25
Using MANPAGER doesn't work so well with vimscript#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' -
}
jhf.remmelzwaal at europe.com, January 2, 2003 3:06
Reading man pages on NT, Win2000 etc.

Windows NT, etc has remote shell client support. This can be used to read the man pages on a unix system. I changed script vimscript#489 in the following way:
-----------------------------------------------
*** manpageview.vim~ Thu Jan  2 11:42:14 2003
--- manpageview.vim Thu Jan  2 11:44:48 2003
***************
*** 87,94 ****
    enew!
    set mod
  "  call Decho("manpagebook<".manpagebook."> topic<".manpagetopic.">")
!   exe "r!man ".manpagebook." ".manpagetopic
!   %!col -b
    setlocal ft=man nomod nolist
    set nolz
  endfunction
--- 87,98 ----
    enew!
    set mod
  "  call Decho("manpagebook<".manpagebook."> topic<".manpagetopic.">")
!   if has('win32')
!    exe "r!rsh g:manpageview_server -l g:manpageview_user man ".manpagebook." ".manpagetopic." | col -b"
!    1
!   else
!    exe "r!man ".manpagebook." ".manpagetopic
!    %!col -b
!   endif
    setlocal ft=man nomod nolist
    set nolz
  endfunction
-----------------------------------------------
Set your unix system (g:manpageview_server) and user account (g:manpageview_user) in your _vimrc.
Set your NT system name and user account in your ~/.rhosts on your unix system.
[email protected], March 15, 2003 0:48
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
Brandon D. Valentine <[email protected]>, March 15, 2003 1:01
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.
[email protected], April 2, 2003 19:07
Does anybody have trouble searching when using less.vim?  I find that if I do "man perlvar" then search for perl, hit 'n' a few times, and it will stop finding new matches.  However if I page down a couple times, there are more matches to be found.  I'm using:

export MANPAGER="col -b | vim -u NONE -U NONE -f -c 'so \$VIMRUNTIME/macros/less.vim | set ft=man nomod nolist laststatus=0 noruler | syn on' -"

Aron
timball at tux dot org, May 20, 2003 7:51
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 @ tux . org

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

}
kerosin at gmx dot de, June 25, 2003 3:25
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.
Anonymous, July 26, 2003 15:16
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.
[email protected], August 21, 2003 23:15
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' -
}
[email protected], October 29, 2003 12:23
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.
[email protected], October 29, 2003 14:42
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...
[email protected], April 27, 2004 18:28
http://vim.sourceforge.net/tips/tip.php?tip_id=167
RogerG, August 27, 2004 17:22
If you'r 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'
rummelc, December 5, 2004 23:20
Nice. I added this little tidbit "-c 'nmap q :q<cr>'" so that I can quite 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'
Anonymous, June 29, 2005 2:31
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"
}


[email protected] - NOSPAM, August 29, 2005 12:32
One may also use manpageview (vimscript#489) in a like manner:

  function man
  {
  vim -c "Man $*" -c only
  }
[email protected] - NOSPAM, November 23, 2005 8:58
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.
arno., January 26, 2006 1:53
When using the shell function described above, you launch vim even when there is no man pages for the words you typed.

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'

corrects that
Anonymous, March 24, 2006 10:07
hm cool?
yeah im in school right now
and its pretty gay
so whatever.
pc!
[email protected], July 10, 2006 12:53
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' -\""

[email protected], September 6, 2006 4:28
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.
anyone@, November 3, 2006 16:34
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 -

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
anyone@, November 3, 2006 16:45
ohh i forget something ..
$VIMRUNTIME/macros/less.sh works better than view
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
   
SourceForge.net Logo