" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish doc/viewdoc.txt [[[1 429 *viewdoc.txt* Flexible viewer for any documentation (help/man/perldoc/etc.) Author: Alex Efros For Vim version 7.0 or later. This plugin only works if 'compatible' is not set. Contents: Description |viewdoc| Mappings |viewdoc-mappings| Commands |viewdoc-commands| Settings |viewdoc-settings| Functions |viewdoc-functions| Handlers |viewdoc-handlers| DEFAULT |ViewDoc_DEFAULT| man |ViewDoc_man| help |ViewDoc_help| help_custom |ViewDoc_help_custom| perldoc |ViewDoc_perldoc| pydoc |ViewDoc_pydoc| Source and issue tracker |viewdoc-source| License |viewdoc-license| ============================================================================== DESCRIPTION *viewdoc* Flexible viewer for any documentation source (help/man/perldoc/etc.) for any file type inside Vim in easy to use, consistent, smart and configurable way. * You can configure how (keys/commands) documentation will be open. By default it will replace standard mapping for key and command |:help| plus add mapping for key and new commands |:man|, |:doc|, etc. * You can configure where (buffer/window/tab) documentation will be open. Can open new docs in one dedicated () or new () buffer/window/tab. Support all work styles (see |viewdoc-settings-examples|): - full screen (no tabs, one window, open files/docs are in hidden buffers), - windowed (no tabs, many windows with open files/docs), - tabbed full screen (many tabs, each with one window, open files/docs are in different tabs), - tabbed (many tabs with many windows inside tabs). * You can easily navigate to next/previous topic while viewing documentation using and (or alternative keys and ), just like you use tags for navigation within source code and Vim's help. * Even closing documentation buffer/window/tab is easier, smarter and more configurable than ever before. :) * Smart detection of documentation source and topic when opening documentation for (word under cursor) - can use current syntax highlight (to find topic's context) and surrounding text (when topic doesn't include important special symbols because of 'iskeyword' value). * Smart completion for available documentation topics when opening documentation using command (just like Vim's |:help| command works). (Some documentation sources may not support this.) * Supported documentation sources: - Vim's help - custom documentation in vim help format - man pages - perldoc - pydoc * Support for new documentation sources and file types can be easily added by external plugins or within ~/.vimrc file. * You can have several documentation sources for same file type, and choose which one should be used on-the-fly. * Can be used as console man page viewer instead of /usr/bin/man. Tested only in Linux, but should work in any *NIX. ============================================================================== MAPPINGS *viewdoc-mappings* Global:~ Open doc for (word under cursor) in new [Scratch] buffer. To disable use |g:no_viewdoc_maps|. K Open doc for in existing [Doc] buffer, replacing it current contents (will create [Doc] buffer if it doesn't exists yet). To disable use |g:no_viewdoc_maps|. Local to buffer with documentation:~ q Close this buffer/window/tab, |:quit| from Vim if it was the last one. or Open documentation for in same buffer. or Return to previous documentation in same buffer (after using ). ============================================================================== COMMANDS *viewdoc-commands* General:~ :doc[!] {topic} [{filetype}] *:doc* *:doc!* :doc[!] [{filetype}] Abbrev for |:ViewDoc|. To disable use |g:no_viewdoc_abbrev|. :ViewDoc[!] {topic} [{filetype}] *:ViewDoc* :ViewDoc[!] [{filetype}] Show documentation for word {topic} or for word under cursor (type literally as is, not as "" or as expand("")). Without {filetype} will use 'ft' of current buffer to detect which one of |viewdoc-handlers| (man/help/perldoc/etc.) should be used to show documentation for {topic}/. When used with handler may use smart detection of context when needed - check syntax highlight used for word under cursor or surrounding text (which wasn't included in expand("") because of 'iskeyword' value). By default will open documentation in new [Scratch] buffer, but when [!] is added will open doc in existing [Doc] buffer (will create it if not exists yet). Will this buffer open in current window, new window or new tab depends on |viewdoc-settings|. Examples: > :doc substr perl :doc! " same as pressing Added by man handler:~ :man[!] {sect} {topic} *:man* :man[!] {topic}({sect}) :man[!] {topic} :man[!] {sect} :man[!] Abbrev for |:ViewDocMan|. To disable use |g:no_viewdoc_abbrev|. :ViewDocMan[!] {sect} {topic} *:ViewDocMan* :ViewDocMan[!] {topic}({sect}) :ViewDocMan[!] {topic} :ViewDocMan[!] {sect} :ViewDocMan[!] Show man page for given {topic} and (optional) {sect}. Works in same way as |:ViewDoc| with {filetype}=man, plus: * support {sect} as separate first param * provide auto-complete for {topic} and ({sect}): > :man tim " auto-complete {topic} :man 2 tim " auto-complete {topic} for section 2 only :man time( " auto-complete {sect} Added by help handler:~ :help[!] {topic} :help[!] Abbrev for |:ViewDocHelp|. To disable use |g:no_viewdoc_abbrev|. :ViewDocHelp[!] {topic} *:ViewDocHelp* :ViewDocHelp[!] Show Vim help for given {topic}. Works in same way as |:ViewDoc| with {filetype}=help, plus: * provide same auto-complete and other behaviour as standard |:help|, so it can be used as drop-in replacement Added by perl handler:~ :perldoc[!] {topic} :perldoc[!] Abbrev for |:ViewDocPerl|. To disable use |g:no_viewdoc_abbrev|. :ViewDocPerl[!] {topic} *:ViewDocPerl* :ViewDocPerl[!] Show perl documentation for given {topic}. Works in same way as |:ViewDoc| with {filetype}=perl, plus: * provide auto-complete for variables/function/modules/POD/etc. ============================================================================== SETTINGS *viewdoc-settings* General:~ g:no_viewdoc_abbrev *g:no_viewdoc_abbrev* g:no_plugin_abbrev Set any of these variables to disable abbrev |:help|, |:man|, |:doc|. g:no_viewdoc_maps *g:no_viewdoc_maps* g:no_plugin_maps Set any of these variables to disable mapping , . g:viewdoc_open ="tabnew" (default) *g:viewdoc_open* ="topleft new" ="belowright vnew" Control where documentation will be open by choosing Vim command used to open new window/tab. You can use any similar commands supported by Vim. New documentation buffer will be opened using: > execute g:viewdoc_open " to create new [Scratch] buffer execute g:viewdoc_open [Doc] " to create new [Doc] buffer g:viewdoc_only =0 (default) *g:viewdoc_only* =1 If you open documentation in window (|g:viewdoc_open|!="tabnew"), you can force this window to be the "only" window in current tab by changing this variable to True value. g:viewdoc_prevtabonclose=1 (default) *g:viewdoc_prevtabonclose* =0 If you open documentation in new tab (|g:viewdoc_open|=="tabnew"), then when you close that tab Vim by default will move to next tab. This plugin by default change this behaviour to move to previous tab. If you like original behaviour set this variable to False. g:viewdoc_openempty =1 (default) *g:viewdoc_openempty* =0 If documentation can't be found, empty window with error message will be opened. This is default behaviour to make consistent UI experience ( after will always return to where you was before ). Set this variable to False to avoid opening empty window when documentation can't be found (error message will be shown anyway). g:viewdoc_dontswitch =0 (default) *g:viewdoc_dontswitch* =1 By default after opening documentation you'll be switched to buffer/window/tab with that documentation (except situation when documentation wasn't found and you've set |g:viewdoc_openempty|=0). If you prefer to don't change your current buffer/window/tab then set this variable to True. This may make sense in |viewdoc-windowed| or |viewdoc-tabbed| configurations and probably very bad idea in all other cases. Added by man handler:~ g:viewdoc_man_cmd ="/usr/bin/man" (default) *g:viewdoc_man_cmd* Should contain command to run `man`. You may wanna change it, for ex. to force English manuals: > let g:viewdoc_man_cmd='LANG= /usr/bin/man' < *viewdoc-settings-examples* *viewdoc-fullscreen* Example configuration: full screen~ * no tabs * one window * other open files/docs are in hidden buffers * navigation between files/docs: |:bn| and |:bp|, close: |:bd| > let g:viewdoc_open='new' let g:viewdoc_only=1 < *viewdoc-windowed* Example configuration: windowed~ * no tabs * many windows with open files/docs * navigation/close: CTRL-W something > let g:viewdoc_open='topleft new' < *viewdoc-tabbed-fullscreen* Example configuration: tabbed full screen~ * many tabs * each with one window * open files/docs are in different tabs > " this is default configuration < *viewdoc-tabbed* Example configuration: tabbed~ * many tabs with many windows inside tabs > " same as in windowed example above ============================================================================== FUNCTIONS *viewdoc-functions* This plugin provide global function ViewDoc() and many ViewDoc_{filetype}() functions, but only |ViewDoc()| function may be called by user (other functions are documentation handlers called internally by |ViewDoc()|). ViewDoc({target}, {topic}, {filetype}) *ViewDoc()* ViewDoc({target}, {topic}) ViewDoc({target}, '', {filetype}) ViewDoc({target}, '') This function handle all |viewdoc-commands|. {target} can be "new" or "doc". If it "new", then documentation will be open in new [Scratch] buffer. If it "doc", then documentation will be open in existing [Doc] buffer (new [Doc] buffer will be created if it doesn't exists yet). Using {target}=="doc" is same as using |viewdoc-commands| with [!]. Other parameters documented in |:ViewDoc|. ============================================================================== HANDLERS *viewdoc-handlers* *ViewDoc_{filetype}()* To add documentation handler for new {filetype} it's enough to create one function in ~/.vimrc (or some plugin): > ViewDoc_{filetype}(topic, filetype, synid, have_context) < This function will receive 4 parameters: topic Requested documentation topic ({topic} or param for |:ViewDoc|, if it was then it will be replaced with expand("") before calling this function). filetype Requested documentation type ({filetype} param for |:ViewDoc| or 'ft' if {filetype} param wasn't used). Usually will be same as in this function's name, unless you've used same function for several file type, like: > function g:ViewDoc_sh(topic, ...) | ... | endfunction let g:ViewDoc_tcsh = function('g:ViewDoc_sh') synid Syntax id for requested topic as returned by |synID()|. Can be non-zero only if |:ViewDoc| was called with . have_context True if we've context (|:ViewDoc| was called with ). If true, then this function may try to analyse topic context, like surrounding symbols which wasn't included in topic param. Examples of calling documentation handler functions: 1) User press on word "test" in file "script.sh": > call ViewDoc_man('test', 'sh', 353, 1) < 2) User run command ":help local-additions" > call ViewDoc_help('local-additions', 'help', 0, 0) This function must return Dictionary with these keys (all optional): > 'topic': String modified topic, needed if your altered original topic 'cmd': String shell command which should output doc for topic 'ft': String file type for command output 'line': Number position to move cursor after opening doc 'col': Number position to move cursor after opening doc 'search': String regexp to search (to move cursor) after opening doc 'tags': String path to file with tags for this doc 'docft': String file type for navigating with inside this doc For example, here is implementation of |ViewDoc_pydoc| handler: > function g:ViewDoc_pydoc(topic, ...) return { 'cmd': printf('pydoc %s', shellescape(a:topic,1)), \ 'ft': 'pydoc', \ } endfunction let g:ViewDoc_python = function('g:ViewDoc_pydoc') ------------------------------------------------------------------------------ Handler: DEFAULT *ViewDoc_DEFAULT* If there is no handler for current filetype then |ViewDoc_man| will be used. To change default handler to, for ex., |ViewDoc_help|, add to ~/.vimrc: > autocmd VimEnter * let g:ViewDoc_DEFAULT = function('g:ViewDoc_help') ------------------------------------------------------------------------------ Handler: man *ViewDoc_man* Show doc using |g:viewdoc_man_cmd| command when {filetype} is "sh" or "man". Also used as default handler, see |ViewDoc_DEFAULT|. Added commands: |:man| |:ViewDocMan|. Added settings: |g:viewdoc_man_cmd|. To view man pages in Vim from console add this to ~/.bashrc: > function man() { vim -c "ViewDocMan $*" -c tabonly; } ------------------------------------------------------------------------------ Handler: help *ViewDoc_help* Show standard Vim help when {filetype} is "vim" or "help". Viewing Vim help using this plugin have some advantages: * much better control how and where help window will be opened * smart detection ( on "&opt" will show help for 'opt', etc.) * and, of course, using to close help Added commands: |:help| |:ViewDocHelp|. ------------------------------------------------------------------------------ Handler: help_custom *ViewDoc_help_custom* Show doc for any {filetype} using separate .txt files written in Vim help format and stored in directory 'runtimepath'/ftdoc/{filetype}/ (no such help files provided with this plugin, you should download or write them yourself). Examples of external docs which can be used with this handler: * CSS 2.1, from http://www.vim.org/scripts/script.php?script_id=918 Create directory ~/.vim/ftdoc/css: > :!mkdir -p ~/.vim/ftdoc/css/ < Copy .txt file from archive into ~/.vim/ftdoc/css/css21.txt, and run: > :helptags ~/.vim/ftdoc/css/ < Add to ~/.vimrc: > autocmd VimEnter * let g:ViewDoc_css = function('g:ViewDoc_help_custom') < * CMake, from http://www.vim.org/scripts/script.php?script_id=3045 Create directory ~/.vim/ftdoc/cmake: > :!mkdir -p ~/.vim/ftdoc/cmake/ < Copy *.txt files from archive into ~/.vim/ftdoc/cmake/*.txt, and run: > :helptags ~/.vim/ftdoc/cmake/ < Add to ~/.vimrc: > autocmd VimEnter * let g:ViewDoc_cmake = function('g:ViewDoc_help_custom') < ------------------------------------------------------------------------------ Handler: perldoc *ViewDoc_perldoc* Show doc using `perldoc` command when {filetype} is "perl" or "perldoc". Added commands: |:perldoc| |:ViewDocPerl|. ------------------------------------------------------------------------------ Handler: pydoc *ViewDoc_pydoc* Show doc using `pydoc` command when {filetype} is "python" or "pydoc". ============================================================================== SOURCE AND ISSUE TRACKER *viewdoc-source* https://code.google.com/p/vim-plugin-viewdoc/ ============================================================================== LICENSE *viewdoc-license* Public Domain. ftplugin/vim_viewdoc.vim [[[1 12 if exists('b:did_ftplugin_viewdoc') finish endif let b:did_ftplugin_viewdoc = 1 setlocal iskeyword+=:,\<,\>,- let b:undo_ftplugin = exists('b:undo_ftplugin') ? b:undo_ftplugin . '|' : '' let b:undo_ftplugin .= 'setlocal iskeyword<' \ . '|unlet b:did_ftplugin_viewdoc' ftplugin/perl_viewdoc.vim [[[1 12 if exists('b:did_ftplugin_viewdoc') finish endif let b:did_ftplugin_viewdoc = 1 setlocal iskeyword+=: let b:undo_ftplugin = exists('b:undo_ftplugin') ? b:undo_ftplugin . '|' : '' let b:undo_ftplugin .= 'setlocal iskeyword<' \ . '|unlet b:did_ftplugin_viewdoc' ftplugin/help_viewdoc.vim [[[1 12 if exists('b:did_ftplugin_viewdoc') finish endif let b:did_ftplugin_viewdoc = 1 setlocal iskeyword=!-~,^*,^\|,^\",192-255 let b:undo_ftplugin = exists('b:undo_ftplugin') ? b:undo_ftplugin . '|' : '' let b:undo_ftplugin .= 'setlocal iskeyword<' \ . '|unlet b:did_ftplugin_viewdoc' ftplugin/perldoc_viewdoc.vim [[[1 12 if exists('b:did_ftplugin_viewdoc') finish endif let b:did_ftplugin_viewdoc = 1 setlocal iskeyword+=: let b:undo_ftplugin = exists('b:undo_ftplugin') ? b:undo_ftplugin . '|' : '' let b:undo_ftplugin .= 'setlocal iskeyword<' \ . '|unlet b:did_ftplugin_viewdoc' plugin/viewdoc_perldoc.vim [[[1 101 " Maintainer: see in viewdoc.vim " Version: see in viewdoc.vim " Last Modified: see in viewdoc.vim " License: see in viewdoc.vim " URL: see in viewdoc.vim " Description: ViewDoc handler for perldoc if exists('g:loaded_viewdoc_perldoc') || &cp || version < 700 finish endif let g:loaded_viewdoc_perldoc = 1 """ Interface " - command command -bar -bang -nargs=1 -complete=custom,s:CompletePerl ViewDocPerl \ call ViewDoc(''=='' ? 'new' : 'doc', , 'perl') " - abbrev if !exists('g:no_plugin_abbrev') && !exists('g:no_viewdoc_abbrev') cabbrev perldoc getcmdtype()==':' && getcmdline()=='perldoc' ? 'ViewDocPerl' : 'perldoc' cabbrev perldoc! getcmdtype()==':' && getcmdline()=='perldoc!' ? 'ViewDocPerl' : 'perldoc!' endif """ Handlers function g:ViewDoc_perldoc(topic, filetype, synid, ctx) let h = { 'ft': 'perldoc', \ 'topic': a:topic, \ } let synname = a:ctx ? synIDattr(a:synid,'name') : '' if synname =~# 'SharpBang' let h.topic = 'perlrun' elseif synname =~# 'StatementFiles' && len(h.topic) == 1 let h.topic = '-X' elseif synname =~# 'Conditional\|Repeat\|Label' let h.topic = 'perlsyn' elseif synname =~# 'SubPrototype\|SubAttribute' let h.topic = 'perlsub' elseif h.topic ==# 'AUTOLOAD' let h.topic = 'perlsub' let h.search= '^\s*Autoloading\>' elseif h.topic ==# 'DESTROY' let h.topic = 'perlobj' let h.search= '^\s*Destructors\>' elseif h.topic =~# '^__[A-Z]\+__$' let h.topic = 'perldata' let h.search= '^\s*Special\s\+Literals' elseif h.topic ==# 'tr' || h.topic ==# 'y' let h.topic = 'perlop' let h.search= '^\s*tr\/' elseif h.topic =~# '^q[qxw]\?$' let h.search= '^\s*' . h.topic . '\/' let h.topic = 'perlop' elseif synname =~# 'StringStartEnd\|perlQQ' let h.topic = 'perlop' let h.search= '^\s*Quote\s\+and\s\+Quote-[Ll]ike\s\+Operators\s*$' elseif h.topic =~# '^\(BEGIN\|UNITCHECK\|CHECK\|INIT\|END\)$' let h.topic = 'perlmod' let h.search= '^\s*BEGIN,' elseif synname =~# '^pod[A-Z]\|POD' || h.topic =~# '^=[a-z]' || h.topic =~# '^[A-Z]<' let h.topic = 'perlpod' elseif synname =~# 'Match' let h.topic = 'perlre' elseif synname =~# 'Var' " search for position where current var's name begin (starting with [$@%]) let col = searchpos('[$@%]{\?\^\?\k*\%#\|\%#[$@%]', 'n')[1] " from that position took full var name (plus extra [ or { after it, if any) let var = col == 0 ? '' : matchstr(getline('.'), '^[$@%]{\?^\?.\k*}\?[{\[]\?', col-1) " $a[ -> @a, $a{ -> %a, @a{ -> %a, drop [ or { at end let var = substitute(var, '^$\(.*\)\[$', '@\1', '') let var = substitute(var, '^$\(.*\){$', '%\1', '') let var = substitute(var, '^@\(.*\){$', '%\1', '') let var = substitute(var, '[\[{]$', '', '') " ${a} -> $a, ${^a} -> $^a, but not ${^aa} let var = substitute(var, '^\([$@%]\){\([^^].*\|\^.\)}$', '\1\2', '') let h.topic = var == '' ? h.topic : var endif let t = shellescape(h.topic,1) let h.cmd = printf('perldoc -- %s || perldoc -f %s || perldoc -v %s',t,t,t) return h endfunction let g:ViewDoc_perl = function('g:ViewDoc_perldoc') """ Internal function s:CompletePerl(ArgLead, CmdLine, CursorPos) if exists('s:complete') return s:complete endif let data= "__FILE__\n__LINE__\n__PACKAGE__\n__DATA__\n__END__\n" let mod = "BEGIN\nUNITCHECK\nCHECK\nINIT\nEND\n" let pod = system('grep "^=item C<[=A-Z]" $(perl -e "print for grep{-f}map{qq{\$_/pod/perlpod.pod}}@INC") | sed "s/^=item C].*//;s//" | sort -u') let var = system('grep -E "^=item [\$@%][^ ]*\$|=item [A-Z]+\$" $(perl -e "print for grep{-f}map{qq{\$_/pod/perlvar.pod}}@INC") | sed "s/^=item //" | sort -u') let func= "-X\n".system('grep "^=item [[:lower:]]" $(perl -e "print for grep{-f}map{qq{\$_/pod/perlfunc.pod}}@INC") | sed "s/^=item //" | grep -v " [[:lower:]]" | sed "s/ .*//;s/(\$//" | sort -u') let pkg = system('find $(perl -le "\$s{q{.}}=1;print for grep{(\$a=\$_)=~s{/[^/]*\z}{};-d && !\$s{\$_}++ && !\$s{\$a}}sort@INC") -name "*.pm" -printf "%P\n" | sed "s,^[0-9.]\+/,,;s,^"$(perl -MConfig -e "print \$Config{myarchname}")"/,,;s,.pm$,,;s,/,::,g" | sort -u') let s:complete = data.mod.pod.var.func.pkg return s:complete endfunction plugin/viewdoc_pydoc.vim [[[1 23 " Maintainer: see in viewdoc.vim " Version: see in viewdoc.vim " Last Modified: see in viewdoc.vim " License: see in viewdoc.vim " URL: see in viewdoc.vim " Description: ViewDoc handler for pydoc if exists('g:loaded_viewdoc_pydoc') || &cp || version < 700 finish endif let g:loaded_viewdoc_pydoc = 1 """ Handlers function g:ViewDoc_pydoc(topic, ...) return { 'cmd': printf('pydoc %s', shellescape(a:topic,1)), \ 'ft': 'pydoc', \ } endfunction let g:ViewDoc_python = function('g:ViewDoc_pydoc') plugin/viewdoc_help.vim [[[1 84 " Maintainer: see in viewdoc.vim " Version: see in viewdoc.vim " Last Modified: see in viewdoc.vim " License: see in viewdoc.vim " URL: see in viewdoc.vim " Description: ViewDoc handler for vim help files if exists('g:loaded_viewdoc_help') || &cp || version < 700 finish endif let g:loaded_viewdoc_help = 1 """ Interface " - command command -bar -bang -nargs=1 -complete=help ViewDocHelp \ call ViewDoc(''=='' ? 'new' : 'doc', , 'help') " - abbrev if !exists('g:no_plugin_abbrev') && !exists('g:no_viewdoc_abbrev') cabbrev help getcmdtype()==':' && getcmdline()=='help' ? 'ViewDocHelp' : 'help' cabbrev help! getcmdtype()==':' && getcmdline()=='help!' ? 'ViewDocHelp' : 'help!' endif """ Handlers function g:ViewDoc_help(topic, filetype, synid, ctx) let h = { 'ft': 'help', \ 'topic': a:topic, \ } if a:ctx if h.topic !~ "^'.*'$" && (synIDattr(a:synid,'name') =~# 'Option' || search('&\k*\%#','n')) let h.topic = "'" . h.topic . "'" " auto-detect: 'option' elseif synIDattr(a:synid,'name') =~ 'Command' let h.topic = ':' . h.topic " auto-detect: :command endif endif try let savetabnr = tabpagenr() execute 'tab help ' . h.topic let helpfile = bufname(bufnr('')) let h.cmd = printf('cat %s', shellescape(helpfile,1)) let h.line = line('.') let h.col = col('.') let h.tags = substitute(helpfile, '/[^/]*$', '/tags', '') tabclose execute 'tabnext ' . savetabnr catch endtry return h endfunction let g:ViewDoc_vim = function('g:ViewDoc_help') function g:ViewDoc_help_custom(topic, ft, ...) let h = { 'ft': 'help', \ 'docft': a:ft, \ } let savetabnr = tabpagenr() for helpfile in split(globpath(&runtimepath, 'ftdoc/'.a:ft.'/*.txt'),"\") let tagsfile = substitute(helpfile, '/[^/]*$', '/tags', '') execute 'tabedit ' . helpfile execute 'setlocal tags^=' . tagsfile for tag_guess in [a:topic, "'".a:topic."'", a:ft.'-'.a:topic] try execute 'tag ' . tag_guess catch continue endtry let h.cmd = printf('cat %s', shellescape(helpfile,1)) let h.line = line('.') let h.col = col('.') let h.tags = tagsfile break endfor setlocal bufhidden=delete tabclose if exists('h.cmd') break endif endfor execute 'tabnext ' . savetabnr return h endfunction plugin/viewdoc.vim [[[1 242 " Maintainer: Alex Efros " Version: 1.2 " Last Modified: Jan 19, 2012 " License: This file is placed in the public domain. " URL: http://www.vim.org/scripts/script.php?script_id=3893 " Description: Flexible viewer for any documentation (help/man/perldoc/etc.) if exists('g:loaded_viewdoc') || &cp || version < 700 finish endif let g:loaded_viewdoc = 1 """ Constants let s:bufname = '[Doc]' """ Options if !exists('g:viewdoc_open') let g:viewdoc_open='tabnew' endif if !exists('g:viewdoc_only') let g:viewdoc_only=0 endif if !exists('g:viewdoc_prevtabonclose') let g:viewdoc_prevtabonclose=1 endif if !exists('g:viewdoc_openempty') let g:viewdoc_openempty=1 endif if !exists('g:viewdoc_dontswitch') let g:viewdoc_dontswitch=0 endif """ Interface " - command command -bar -bang -nargs=+ ViewDoc \ call ViewDoc(''=='' ? 'new' : 'doc', ) " - abbrev if !exists('g:no_plugin_abbrev') && !exists('g:no_viewdoc_abbrev') cabbrev doc getcmdtype()==':' && getcmdline()=='doc' ? 'ViewDoc' : 'doc' cabbrev doc! getcmdtype()==':' && getcmdline()=='doc!' ? 'ViewDoc!' : 'doc!' endif " - map if !exists('g:no_plugin_maps') && !exists('g:no_viewdoc_maps') imap :call ViewDoc('new', '') nmap :call ViewDoc('new', '') nmap K :call ViewDoc('doc', '') endif " - function " call ViewDoc('new', '') auto-detect context/syntax and file type " call ViewDoc('doc', 'bash') auto-detect only file type " call ViewDoc('new', ':execute', 'help') no auto-detect function ViewDoc(target, topic, ...) let h = s:GetHandle(a:topic, a:0 > 0 ? a:1 : &ft) if a:target != 'inplace' let prev_tabpagenr = tabpagenr() call s:OpenBuf(a:target) let b:stack = 0 endif setlocal modifiable silent 1,$d if exists('h.cmd') execute 'silent 0r ! ( ' . h.cmd . ' ) 2>/dev/null' silent $d execute 'normal ' . (exists('h.line') ? h.line : 1) . 'G' execute 'normal ' . (exists('h.col') ? h.col : 1) . '|' if exists('h.search') call search(h.search) endif normal zt endif setlocal nomodifiable nomodified execute 'setlocal ft=' . h.ft if exists('h.tags') execute 'setlocal tags^=' . h.tags endif if exists('h.docft') let b:docft = h.docft endif inoremap q :call CloseBuf() nnoremap q :call CloseBuf() vnoremap q :call CloseBuf() inoremap :call Next() inoremap :call Prev() nnoremap :call Next() nnoremap :call Prev() imap imap nmap nmap let is_empty = line('$') == 1 && col('$') == 1 if is_empty && !g:viewdoc_openempty if a:target == 'inplace' call s:Prev() else call s:CloseBuf() unlet! prev_tabpagenr endif endif if g:viewdoc_dontswitch && exists('prev_tabpagenr') if prev_tabpagenr != tabpagenr() execute 'tabnext ' . prev_tabpagenr elseif winnr('$') > 1 execute "normal \p" else execute "normal \" endif endif if is_empty redraw | echohl ErrorMsg | echo 'Sorry, no doc for' h.topic | echohl None endif endfunction """ Internal " let h = s:GetHandle('', 'perl') auto-detect syntax " let h = s:GetHandle('query', 'perl') no auto-detect " Return: { " 'topic': 'query', ALWAYS " 'ft': 'perldoc', ALWAYS " 'cmd': 'cat /path/to/file', OPTIONAL " 'line': 1, OPTIONAL " 'col': 1, OPTIONAL " 'tags': '/path/to/tags', OPTIONAL " 'search': 'regex', OPTIONAL " 'docft': 'perl', OPTIONAL " } function s:GetHandle(topic, ft) let cword = a:topic == '' let topic = cword ? expand('') : a:topic let synid = cword ? synID(line('.'),col('.'),1) : 0 let handler = exists('*g:ViewDoc_{a:ft}') ? a:ft : 'DEFAULT' let h = g:ViewDoc_{handler}(topic, a:ft, synid, cword) let h.topic = exists('h.topic') ? h.topic : topic let h.ft = exists('h.ft') ? h.ft : a:ft return h endfunction " Emulate doc stack a-la tag stack ( and ) function s:Next() let b:stack = exists('b:stack') ? b:stack + 1 : 1 let docft = exists('b:docft') ? b:docft : &ft normal msHmt`s call ViewDoc('inplace', '', docft) endfunction function s:Prev() if exists('b:stack') && b:stack let b:stack -= 1 setlocal modifiable undo setlocal nomodifiable normal 'tzt`s " XXX man page syntax _partially_ switched off after Prev(), " I've no idea why this happens, so just force it again if exists('g:syntax_on') syntax on endif endif endfunction " call s:OpenBuf('doc') open existing '[Doc]' buffer (create if not exists) " call s:OpenBuf('new') create and open new '[Scratch]' buffer function s:OpenBuf(target) let bufname = escape(s:bufname, '[]\') let [tabnr, winnr, bufnr] = s:FindBuf(bufname) if a:target == 'new' execute g:viewdoc_open elseif tabnr == -1 execute g:viewdoc_open . ' ' . bufname else execute 'tabnext ' . tabnr execute winnr . 'wincmd w' endif if g:viewdoc_only only! endif setlocal noswapfile buflisted buftype=nofile bufhidden=hide endfunction " Close buffer with doc, and optionally move to previous tab. " Quit if closing last buffer. function s:CloseBuf() if len(filter( range(1,bufnr('$')), 'buflisted(v:val)' )) == 1 q elseif winnr('$') > 1 || !g:viewdoc_prevtabonclose bwipeout else let tabnr = tabpagenr() bwipeout if tabnr == tabpagenr() tabprevious endif endif endfunction " let [tabnr, winnr, bufnr] = s:FindBuf(bufname) " Return: " [-1, -1, -1] if buf not exists " [-1, -1, Z] if buf not visible " [ X, Y, Z] if buf visible function s:FindBuf(bufname) let bufnr = bufnr('^' . a:bufname . '$') if bufnr == -1 return [-1, -1, -1] endif let tabnr = -1 for t in range(1, tabpagenr('$')) for nr in tabpagebuflist(t) if nr == bufnr let tabnr = t break endif endfor if tabnr != -1 break endif endfor if tabnr == -1 return [-1, -1, bufnr] endif let savetabnr = tabpagenr() execute 'tabnext ' . tabnr let winnr = bufwinnr(bufnr) execute 'tabnext ' . savetabnr return [tabnr, winnr, bufnr] endfunction plugin/viewdoc_man.vim [[[1 83 " Maintainer: see in viewdoc.vim " Version: see in viewdoc.vim " Last Modified: see in viewdoc.vim " License: see in viewdoc.vim " URL: see in viewdoc.vim " Description: ViewDoc handler for man pages (default handler) if exists('g:loaded_viewdoc_man') || &cp || version < 700 finish endif let g:loaded_viewdoc_man = 1 """ Constants let s:re_mansect = '\([0-9n]p\?\)' """ Options if !exists('g:viewdoc_man_cmd') let g:viewdoc_man_cmd='/usr/bin/man' " user may want 'LANG= /usr/bin/man' endif """ Interface " - command command -bar -bang -nargs=1 -complete=custom,s:CompleteMan ViewDocMan \ call ViewDoc(''=='' ? 'new' : 'doc', , 'man') " - abbrev if !exists('g:no_plugin_abbrev') && !exists('g:no_viewdoc_abbrev') cabbrev man getcmdtype()==':' && getcmdline()=='man' ? 'ViewDocMan' : 'man' cabbrev man! getcmdtype()==':' && getcmdline()=='man!' ? 'ViewDocMan' : 'man!' endif """ Handlers " let h = ViewDoc_man('time') " let h = ViewDoc_man('time(2)') " let h = ViewDoc_man('2 time') function g:ViewDoc_man(topic, ...) let sect = '' let name = a:topic let m = matchlist(name, '('.s:re_mansect.')$') if (len(m)) let sect = m[1] let name = substitute(name, '('.s:re_mansect.')$', '', '') endif let m = matchlist(name, '^'.s:re_mansect.'\s\+') if (len(m)) let sect = m[1] let name = substitute(name, '^'.s:re_mansect.'\s\+', '', '') endif return { 'cmd': printf('%s %s %s | sed "s/ \xB7 / * /" | col -b', g:viewdoc_man_cmd, sect, shellescape(name,1)), \ 'ft': 'man', \ } endfunction let g:ViewDoc_DEFAULT = function('g:ViewDoc_man') """ Internal " Autocomplete section: time( ti.*( " Autocomplete command: tim ti.*e " Autocomplete command in section: 2 tim 2 ti.*e function s:CompleteMan(ArgLead, CmdLine, CursorPos) let manpath = substitute(system(printf('%s --path', g:viewdoc_man_cmd)),'\n$','','') if manpath =~ ':' let manpath = '{'.join(map(split(manpath,':'),'shellescape(v:val,1)'),',').'}' else let manpath = shellescape(manpath,1) endif if strpart(a:CmdLine, a:CursorPos - 1) == '(' let m = matchlist(a:CmdLine, '\s\(\S\+\)($') if !len(m) return '' endif return system(printf('find %s/man* -type f -regex ".*/"%s"\.[0-9n]p?\(\.bz2\|\.gz\)?" -printf "%%f\n" 2>/dev/null | sed "s/\.bz2$\|\.gz$//;s/.*\///;s/\.\([^.]\+\)$/(\1)/"', \ manpath, shellescape(m[1],1))) else let m = matchlist(a:CmdLine, '\s'.s:re_mansect.'\s') let sect = len(m) ? m[1] : '*' return system(printf('find %s/man%s -type f -printf "%%f\n" 2>/dev/null | sed "s/\.bz2$\|\.gz$//;s/\.[^.]*$//" | sort -u', \ manpath, sect)) endif endfunction