From 9fb9d2929fb9913105efaad8af6b3ecfbeaf52dc Mon Sep 17 00:00:00 2001 From: Noah Frederick Date: Tue, 16 Feb 2016 17:54:53 -0500 Subject: man.vim: fixes to argument handling and parsing - Define a collection of legal characters when parsing page and section in `s:parse_page_and_section()` instead of relying on 'iskeyword', which is unreliable. - Allow non-numeric section names (e.g., `3c`). - Simplify argument handling in `man#get_page()` to accommodate non-numeric section names. Fixes #4165. --- runtime/autoload/man.vim | 25 ++++++++----------------- runtime/ftplugin/man.vim | 4 ++-- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index 49663d7e5a..f702c39826 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -11,6 +11,8 @@ catch /E145:/ " Ignore the error in restricted mode endtry +" Load man page {page} from {section} +" call man#get_page([{section}, ]{page}) function man#get_page(...) abort let invoked_from_man = (&filetype ==# 'man') @@ -20,21 +22,14 @@ function man#get_page(...) abort elseif a:0 > 2 echoerr 'too many arguments' return - elseif a:0 == 2 - let [page, sect] = [a:2, 0 + a:1] - elseif type(1) == type(a:1) - let [page, sect] = ['', a:1] - else - let [page, sect] = [a:1, ''] endif - if page == '' - let page = expand('') - endif + let sect = get(a:000, 0) + let page = get(a:000, 1, sect) let [page, sect] = s:parse_page_and_section(sect, page) - if 0 + sect > 0 && s:find_page(sect, page) == 0 + if !empty(sect) && s:find_page(sect, page) == 0 let sect = '' endif @@ -118,15 +113,11 @@ endfunction " Expects a string like 'access' or 'access(2)'. function s:parse_page_and_section(sect, str) abort try - let save_isk = &iskeyword - setlocal iskeyword-=(,) - let page = substitute(a:str, '(*\(\k\+\).*', '\1', '') - let sect = substitute(a:str, '\(\k\+\)(\([^()]*\)).*', '\2', '') - if sect == page || -1 == match(sect, '^[0-9 ]\+$') + let [page, sect] = matchlist(a:str, '\v\C([-.[:alnum:]_]+)%(\(([-.[:alnum:]_]+)\))?')[1:2] + if empty(sect) let sect = a:sect endif catch - let &l:iskeyword = save_isk echoerr 'man.vim: failed to parse: "'.a:str.'"' endtry @@ -134,7 +125,7 @@ function s:parse_page_and_section(sect, str) abort endfunction function s:cmd(sect, page) abort - if 0 + a:sect > 0 + if !empty(a:sect) return s:man_sect_arg.' '.a:sect.' '.a:page endif return a:page diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim index 133a28e626..36cd70f203 100644 --- a/runtime/ftplugin/man.vim +++ b/runtime/ftplugin/man.vim @@ -24,11 +24,11 @@ setlocal buftype=nofile noswapfile setlocal nomodifiable readonly bufhidden=hide nobuflisted tabstop=8 if !exists("g:no_plugin_maps") && !exists("g:no_man_maps") - nnoremap :call man#get_page(v:count) + nnoremap :call man#get_page(v:count, expand('')) nnoremap :call man#pop_page() nnoremap q c if &keywordprg !=# ':Man' - nnoremap K :call man#get_page(v:count) + nnoremap K :call man#get_page(v:count, expand('')) endif endif -- cgit From 42e710eacb996cb054ffba020133c1132d47889a Mon Sep 17 00:00:00 2001 From: Noah Frederick Date: Tue, 16 Feb 2016 17:58:21 -0500 Subject: man.vim: clean up regex/string comparisons - Explicitly specify case sensitivity when comparing strings - Clean up unnecessarily complex `if` statements --- runtime/autoload/man.vim | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index f702c39826..f0e9af01a2 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -51,7 +51,7 @@ function man#get_page(...) abort if winnr() > 1 exe "norm! " . thiswin . "\w" while 1 - if &filetype == 'man' + if &filetype ==# 'man' break endif wincmd w @@ -75,10 +75,10 @@ function man#get_page(...) abort endif silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b' " Remove blank lines from top and bottom. - while getline(1) =~ '^\s*$' + while getline(1) =~# '^\s*$' silent keepjumps norm! gg"_dd endwhile - while getline('$') =~ '^\s*$' + while getline('$') =~# '^\s*$' silent keepjumps norm! G"_dd endwhile setlocal nomodified @@ -133,10 +133,5 @@ endfunction function s:find_page(sect, page) abort let where = system('/usr/bin/man '.s:man_find_arg.' '.s:cmd(a:sect, a:page)) - if where !~ "^/" - if matchstr(where, " [^ ]*$") !~ "^ /" - return 0 - endif - endif - return 1 + return (where =~# '^ */') endfunction -- cgit From 091ef2fbe4a1517ce91fade26ebbd50f063e346d Mon Sep 17 00:00:00 2001 From: Noah Frederick Date: Tue, 16 Feb 2016 18:01:03 -0500 Subject: man.vim: prefer cmd-line to normal-mode commands --- runtime/autoload/man.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index f0e9af01a2..0dfcc424e2 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -49,7 +49,7 @@ function man#get_page(...) abort let thiswin = winnr() wincmd b if winnr() > 1 - exe "norm! " . thiswin . "\w" + exec thiswin . 'wincmd w' while 1 if &filetype ==# 'man' break @@ -76,10 +76,10 @@ function man#get_page(...) abort silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b' " Remove blank lines from top and bottom. while getline(1) =~# '^\s*$' - silent keepjumps norm! gg"_dd + silent keepjumps 1delete _ endwhile while getline('$') =~# '^\s*$' - silent keepjumps norm! G"_dd + silent keepjumps $delete _ endwhile setlocal nomodified setlocal filetype=man -- cgit