mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
Merge pull request #12480 from nhooyr/mansect-trim
man.vim: Refactor verify_exists to unset $MANSECT as needed
This commit is contained in:
commit
e1d1c413f7
@ -52,13 +52,14 @@ function! man#open_page(count, count1, mods, ...) abort
|
||||
let ref = a:2.'('.a:1.')'
|
||||
endif
|
||||
try
|
||||
let [sect, name] = man#extract_sect_and_name_ref(ref)
|
||||
let [sect, name] = s:extract_sect_and_name_ref(ref)
|
||||
if a:count ==# a:count1
|
||||
" v:count defaults to 0 which is a valid section, and v:count1 defaults to
|
||||
" 1, also a valid section. If they are equal, count explicitly set.
|
||||
let sect = string(a:count)
|
||||
endif
|
||||
let [sect, name, path] = s:verify_exists(sect, name)
|
||||
let path = s:verify_exists(sect, name)
|
||||
let [sect, name] = s:extract_sect_and_name_path(path)
|
||||
catch
|
||||
call s:error(v:exception)
|
||||
return
|
||||
@ -82,8 +83,9 @@ endfunction
|
||||
|
||||
function! man#read_page(ref) abort
|
||||
try
|
||||
let [sect, name] = man#extract_sect_and_name_ref(a:ref)
|
||||
let [sect, name, path] = s:verify_exists(sect, name)
|
||||
let [sect, name] = s:extract_sect_and_name_ref(a:ref)
|
||||
let path = s:verify_exists(sect, name)
|
||||
let [sect, name] = s:extract_sect_and_name_path(path)
|
||||
let page = s:get_page(path)
|
||||
catch
|
||||
call s:error(v:exception)
|
||||
@ -194,7 +196,7 @@ endfunction
|
||||
|
||||
" attempt to extract the name and sect out of 'name(sect)'
|
||||
" otherwise just return the largest string of valid characters in ref
|
||||
function! man#extract_sect_and_name_ref(ref) abort
|
||||
function! s:extract_sect_and_name_ref(ref) abort
|
||||
if a:ref[0] ==# '-' " try ':Man -pandoc' with this disabled.
|
||||
throw 'manpage name cannot start with ''-'''
|
||||
endif
|
||||
@ -204,7 +206,7 @@ function! man#extract_sect_and_name_ref(ref) abort
|
||||
if empty(name)
|
||||
throw 'manpage reference cannot contain only parentheses'
|
||||
endif
|
||||
return [get(b:, 'man_default_sects', ''), name]
|
||||
return ['', name]
|
||||
endif
|
||||
let left = split(ref, '(')
|
||||
" see ':Man 3X curses' on why tolower.
|
||||
@ -227,24 +229,62 @@ function! s:get_path(sect, name) abort
|
||||
return substitute(get(split(s:system(['man', s:find_arg, s:section_arg, a:sect, a:name])), 0, ''), '\n\+$', '', '')
|
||||
endfunction
|
||||
|
||||
" s:verify_exists attempts to find the path to a manpage
|
||||
" based on the passed section and name.
|
||||
"
|
||||
" 1. If the passed section is empty, b:man_default_sects is used.
|
||||
" 2. If manpage could not be found with the given sect and name,
|
||||
" then another attempt is made with b:man_default_sects.
|
||||
" 3. If it still could not be found, then we try again without a section.
|
||||
" 4. If still not found but $MANSECT is set, then we try again with $MANSECT
|
||||
" unset.
|
||||
"
|
||||
" This function is careful to avoid duplicating a search if a previous
|
||||
" step has already done it. i.e if we use b:man_default_sects in step 1,
|
||||
" then we don't do it again in step 2.
|
||||
function! s:verify_exists(sect, name) abort
|
||||
let sect = a:sect
|
||||
if empty(sect)
|
||||
let sect = get(b:, 'man_default_sects', '')
|
||||
endif
|
||||
|
||||
try
|
||||
let path = s:get_path(a:sect, a:name)
|
||||
return s:get_path(sect, a:name)
|
||||
catch /^command error (/
|
||||
try
|
||||
let path = s:get_path(get(b:, 'man_default_sects', ''), a:name)
|
||||
catch /^command error (/
|
||||
let path = s:get_path('', a:name)
|
||||
endtry
|
||||
endtry
|
||||
" Extract the section from the path, because sometimes the actual section is
|
||||
" more specific than what we provided to `man` (try `:Man 3 App::CLI`).
|
||||
" Also on linux, name seems to be case-insensitive. So for `:Man PRIntf`, we
|
||||
" still want the name of the buffer to be 'printf'.
|
||||
return s:extract_sect_and_name_path(path) + [path]
|
||||
|
||||
if !empty(get(b:, 'man_default_sects', '')) && sect !=# b:man_default_sects
|
||||
try
|
||||
return s:get_path(b:man_default_sects, a:name)
|
||||
catch /^command error (/
|
||||
endtry
|
||||
endif
|
||||
|
||||
if !empty(sect)
|
||||
try
|
||||
return s:get_path('', a:name)
|
||||
catch /^command error (/
|
||||
endtry
|
||||
endif
|
||||
|
||||
if !empty($MANSECT)
|
||||
try
|
||||
let MANSECT = $MANSECT
|
||||
unset $MANSECT
|
||||
return s:get_path('', a:name)
|
||||
catch /^command error (/
|
||||
finally
|
||||
let $MANSECT = MANSECT
|
||||
endtry
|
||||
endif
|
||||
|
||||
throw 'no manual entry for ' . a:name
|
||||
endfunction
|
||||
|
||||
" extracts the name and sect out of 'path/name.sect'
|
||||
" Extracts the name/section from the 'path/name.sect', because sometimes the actual section is
|
||||
" more specific than what we provided to `man` (try `:Man 3 App::CLI`).
|
||||
" Also on linux, name seems to be case-insensitive. So for `:Man PRIntf`, we
|
||||
" still want the name of the buffer to be 'printf'.
|
||||
function! s:extract_sect_and_name_path(path) abort
|
||||
let tail = fnamemodify(a:path, ':t')
|
||||
if a:path =~# '\.\%([glx]z\|bz2\|lzma\|Z\)$' " valid extensions
|
||||
@ -275,7 +315,7 @@ function! s:error(msg) abort
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
" see man#extract_sect_and_name_ref on why tolower(sect)
|
||||
" see s:extract_sect_and_name_ref on why tolower(sect)
|
||||
function! man#complete(arg_lead, cmd_line, cursor_pos) abort
|
||||
let args = split(a:cmd_line)
|
||||
let cmd_offset = index(args, 'Man')
|
||||
@ -332,15 +372,26 @@ function! s:get_paths(sect, name, do_fallback) abort
|
||||
" callers must try-catch this, as some `man` implementations don't support `s:find_arg`
|
||||
try
|
||||
let mandirs = join(split(s:system(['man', s:find_arg]), ':\|\n'), ',')
|
||||
return globpath(mandirs,'man?/'.a:name.'*.'.a:sect.'*', 0, 1)
|
||||
let paths = globpath(mandirs, 'man?/'.a:name.'*.'.a:sect.'*', 0, 1)
|
||||
try
|
||||
" Prioritize the result from verify_exists as it obeys b:man_default_sects.
|
||||
let first = s:verify_exists(a:sect, a:name)
|
||||
let paths = filter(paths, 'v:val !=# first')
|
||||
let paths = [first] + paths
|
||||
catch
|
||||
endtry
|
||||
return paths
|
||||
catch
|
||||
if !a:do_fallback
|
||||
throw v:exception
|
||||
endif
|
||||
|
||||
" fallback to a single path, with the page we're trying to find
|
||||
let [l:sect, l:name, l:path] = s:verify_exists(a:sect, a:name)
|
||||
return [l:path]
|
||||
" Fallback to a single path, with the page we're trying to find.
|
||||
try
|
||||
return [s:verify_exists(a:sect, a:name)]
|
||||
catch
|
||||
return []
|
||||
endtry
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
@ -379,7 +430,7 @@ function! man#init_pager() abort
|
||||
" know the correct casing, cf. `man glDrawArraysInstanced`).
|
||||
let ref = substitute(matchstr(getline(1), '^[^)]\+)'), ' ', '_', 'g')
|
||||
try
|
||||
let b:man_sect = man#extract_sect_and_name_ref(ref)[0]
|
||||
let b:man_sect = s:extract_sect_and_name_ref(ref)[0]
|
||||
catch
|
||||
let b:man_sect = ''
|
||||
endtry
|
||||
@ -391,7 +442,7 @@ function! man#init_pager() abort
|
||||
endfunction
|
||||
|
||||
function! man#goto_tag(pattern, flags, info) abort
|
||||
let [l:sect, l:name] = man#extract_sect_and_name_ref(a:pattern)
|
||||
let [l:sect, l:name] = s:extract_sect_and_name_ref(a:pattern)
|
||||
|
||||
let l:paths = s:get_paths(l:sect, l:name, v:true)
|
||||
let l:structured = []
|
||||
@ -401,9 +452,6 @@ function! man#goto_tag(pattern, flags, info) abort
|
||||
let l:structured += [{ 'name': l:n, 'path': l:path }]
|
||||
endfor
|
||||
|
||||
" sort by relevance - exact matches first, then the previous order
|
||||
call sort(l:structured, { a, b -> a.name ==? l:name ? -1 : b.name ==? l:name ? 1 : 0 })
|
||||
|
||||
if &cscopetag
|
||||
" return only a single entry so we work well with :cstag (#11675)
|
||||
let l:structured = l:structured[:0]
|
||||
|
@ -6,7 +6,7 @@ if exists('b:did_ftplugin') || &filetype !=# 'man'
|
||||
endif
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
let s:pager = get(s:, 'pager', 0) || !exists('b:man_sect')
|
||||
let s:pager = !exists('b:man_sect')
|
||||
|
||||
if s:pager
|
||||
call man#init_pager()
|
||||
@ -26,7 +26,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
|
||||
nnoremap <silent> <buffer> j gj
|
||||
nnoremap <silent> <buffer> k gk
|
||||
nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
|
||||
if 1 == bufnr('%') || s:pager
|
||||
if s:pager
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
|
||||
else
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
|
||||
|
Loading…
Reference in New Issue
Block a user