diff options
Diffstat (limited to 'autoload/julia')
| -rw-r--r-- | autoload/julia/doc.vim | 246 | 
1 files changed, 246 insertions, 0 deletions
| diff --git a/autoload/julia/doc.vim b/autoload/julia/doc.vim new file mode 100644 index 00000000..8a9cab52 --- /dev/null +++ b/autoload/julia/doc.vim @@ -0,0 +1,246 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'julia') == -1 +   +" path to the julia binary to communicate with +if has('win32') || has('win64') +  if exists('g:julia#doc#juliapath') +    " use assigned g:julia#doc#juliapath +  elseif executable('julia') +    " use julia command in PATH +    let g:julia#doc#juliapath = 'julia' +  else +    " search julia binary in the default installation paths +    let pathlist = sort(glob($LOCALAPPDATA . '\Julia-*\bin\julia.exe', 1, 1)) +    let g:julia#doc#juliapath = get(pathlist, -1, 'julia') +  endif +else +  let g:julia#doc#juliapath = get(g:, 'julia#doc#juliapath', 'julia') +endif + +function! s:version() abort +  let VERSION = {'major': 0, 'minor': 0} +  if !executable(g:julia#doc#juliapath) +    return VERSION +  endif + +  let cmd = printf('%s -v', g:julia#doc#juliapath) +  let output = system(cmd) +  let versionstr = matchstr(output, '\C^julia version \zs\d\+\.\d\+\ze') +  let [major, minor] = map(split(versionstr, '\.'), 'str2nr(v:val)') +  let VERSION.major = major +  let VERSION.minor = minor +  return VERSION +endfunction + +let s:VERSION = s:version() +let s:NODOCPATTERN = '\C\VNo documentation found.' + +function! julia#doc#lookup(keyword, ...) abort +  let juliapath = get(a:000, 0, g:julia#doc#juliapath) +  let keyword = escape(a:keyword, '"\') +  let cmd = printf('%s -E "@doc %s"', juliapath, keyword) +  return systemlist(cmd) +endfunction + +function! julia#doc#open(keyword) abort +  if empty(a:keyword) +    call s:warn('Not an appropriate keyword.') +    return +  endif + +  if !executable(g:julia#doc#juliapath) +    call s:warn('%s command is not executable', g:julia#doc#juliapath) +    return +  endif + +  let doc = julia#doc#lookup(a:keyword, g:julia#doc#juliapath) +  if empty(doc) || match(doc[0], s:NODOCPATTERN) > -1 +    call s:warn('No documentation found for "%s".', a:keyword) +    return +  endif + +  " workaround for * and ? since a buffername cannot include them +  let keyword = a:keyword +  let keyword = substitute(keyword, '\*', ':asterisk:', 'g') +  let keyword = substitute(keyword, '?', ':question:', 'g') +  let buffername = printf('juliadoc: %s', keyword) + +  call s:write_to_preview_window(doc, "juliadoc", buffername) + +  call filter(s:HELPHISTORY, 'v:val isnot# a:keyword') +  call add(s:HELPHISTORY, a:keyword) +endfunction + +function! s:write_to_preview_window(content, ftype, buffername) +  " Are we in the preview window from the outset? If not, best to close any +  " preview windows that might exist. +  let pvw = &previewwindow +  if !pvw +    silent! pclose! +  endif +  execute "silent! pedit +setlocal\\ nobuflisted\\ noswapfile\\" +        \ "buftype=nofile\\ bufhidden=wipe" a:buffername +  silent! wincmd P +  if &previewwindow +    setlocal modifiable noreadonly +    silent! %delete _ +    call append(0, a:content) +    silent! $delete _ +    normal! ggj +    setlocal nomodified readonly nomodifiable +    execute "setfiletype" a:ftype +    " Only return to a normal window if we didn't start in a preview window. +    if !pvw +      silent! wincmd p +    endif +  else +    " We couldn't make it to the preview window, so as a fallback we dump the +    " contents in the status area. +    execute printf("echo '%s'", join(a:content, "\n")) +  endif +endfunction + +function! s:warn(...) abort +  if a:0 == 0 +    return +  endif + +  echohl WarningMsg +  try +    if a:0 == 1 +      echo a:1 +    else +      echo call('printf', a:000) +    endif +  finally +    echohl None +  endtry +endfunction + + + +let s:KEYWORDPATTERN = '\m@\?\h\k*!\?' + +" This function is called in normal mode or visual mode. +function! julia#doc#keywordprg(word) abort +  if a:word is# '' +    return +  endif + +  let word = s:unfnameescape(a:word) +  if word is# expand('<cword>') +    " 'K' in normal mode +    " NOTE: Because ! and @ is not in 'iskeyword' option, this func ignore +    "       the argument to recognize keywords like "@time" and "push!" +    let view = winsaveview() +    let lnum = line('.') +    let tail = searchpos(s:KEYWORDPATTERN, 'ce', lnum) +    let head = searchpos(s:KEYWORDPATTERN, 'bc', lnum) +    call winrestview(view) +    if head == [0, 0] || tail == [0, 0] +      return +    else +      let start = head[1] - 1 +      let end = tail[1] - 1 +      let word = getline(lnum)[start : end] +    endif +  endif +  call julia#doc#open(word) +endfunction + +if exists('+shellslash') +  let s:ESCAPEDCHARS = " \t\n\"#%'*<?`|" +else +  let s:ESCAPEDCHARS = " \t\n*?[{`$\\%#'\"|!<" +endif +let s:FNAMEESCAPEPATTERN = '\\\ze[' . escape(s:ESCAPEDCHARS, ']^-\') . ']' + +" this function reproduces an original string escaped by fnameescape() +function! s:unfnameescape(str) abort +  if a:str is# '' +    return '' +  endif + +  " NOTE: We cannot determine the original string if a:str starts from '\-', +  "       '\+' or '\>' because fnameescape('-') ==# fnameescape('\-'). +  if a:str is# '\-' +    " Remove escape anyway. +    return '-' +  endif + +  if a:str =~# '^\\[+>]' +    let str = a:str[1:] +  else +    let str = a:str +  endif +  return substitute(str, s:FNAMEESCAPEPATTERN, '', 'g') +endfunction + + + +let s:HELPPROMPT = 'help?> ' +let s:HELPHISTORY = [] + +function! julia#doc#prompt() abort +  let inputhist = s:savehistory('input') +  echohl MoreMsg +  try +    call s:restorehistory('input', s:HELPHISTORY) +    let keyword = input(s:HELPPROMPT, '', 'customlist,julia#doc#complete') + +    " Clear the last prompt +    normal! : +  finally +    echohl None +    call s:restorehistory('input', inputhist) +  endtry + +  if empty(keyword) +    return +  endif + +  call julia#doc#open(keyword) +endfunction + +function! s:savehistory(name) abort +  if histnr(a:name) == -1 +    return [] +  endif + +  let history = [] +  for i in range(1, histnr(a:name)) +    let item = histget(a:name, i) +    if !empty(item) +      call add(history, item) +    endif +  endfor +  return history +endfunction + +function! s:restorehistory(name, history) abort +  call histdel(a:name) +  for item in a:history +    call histadd(a:name, item) +  endfor +endfunction + + + +if s:VERSION.major == 0 && s:VERSION.minor <= 6 +  let s:REPL_SEARCH = 'Base.Docs.repl_search' +else +  let s:REPL_SEARCH = 'import REPL.repl_search; repl_search' +endif + +function! julia#doc#complete(ArgLead, CmdLine, CursorPos) abort +  return s:likely(a:ArgLead) +endfunction + +function! s:likely(str) abort +  " escape twice +  let str = escape(escape(a:str, '"\'), '"\') +  let cmd = printf('%s -E "%s(\"%s\")"', g:julia#doc#juliapath, s:REPL_SEARCH, str) +  let output = systemlist(cmd) +  return split(matchstr(output[0], '\C^search: \zs.*')) +endfunction + +endif | 
