davidhalter / jedi-vim

Using the jedi autocompletion library for VIM.
MIT License
5.27k stars 370 forks source link

Show documentation on (neovim) floating window? #973

Open hungrybirder opened 4 years ago

hungrybirder commented 4 years ago

Hello, Do you have a plan to implement show doc on (nvim) floating window? Like vim-go has a setting called g:go_doc_popup_window. Show doc on Floating window or Popup window may be more comfortable than preview~

Thanks.

davidhalter commented 4 years ago

This is what #652 is about. Please try it and let us know if it works.

hungrybirder commented 4 years ago

This is what #652 is about. Please try it and let us know if it works.

I test it on Plug 'blueyed/jedi-vim', {'branch': 'call-signatures'} , and set

let g:jedi#show_call_signatures = 3
let g:jedi#show_call_signatures_modes = 'ni'

It doesn't work. No floating window doc.

Some Info: NVIM v0.4.3 MacOS 10.15.2

davidhalter commented 4 years ago

@blueyed

blayz3r commented 4 years ago

@blueyed is the goal to have this:

blueyed commented 4 years ago

652 is only for call signatures, not docs.

@blayz3r something like this could be done. We should keep that in mind with #652 (so that functions can be shared etc).

blayz3r commented 4 years ago

In the mean time I am using this hack:

image



autocmd FileType python nnoremap <buffer> K :call PyDocVim()<CR>

function! PyDocVim()
python3 << EOF
import jedi

curfile = vim.current.buffer.name
row = vim.current.window.cursor[0]
col= vim.current.window.cursor[1]

script = jedi.Script(
    source=None,
    path=curfile,
    line=row,
    column=col)

try:
    definitions = script.goto_definitions()
except Exception:
    # print to stdout, will be in :messages
    definitions = []
    print("Exception, this shouldn't happen.")
    print(traceback.format_exc())

    if not definitions:
        echo_highlight("No documentation found for that.")
        vim.command("return")

docs = []
for d in definitions:
    doc = d.docstring()
    if doc:
        title = "Docstring for %s" % d.desc_with_module
        underline = "=" * len(title)
        docs.append("%s\n%s\n%s" % (title, underline, doc))
    else:
        docs.append("|No Docstring for %s|" % d)
    text = ("\n" + "-" * 79 + "\n").join(docs)
vim.command("let docWidth = %s" % len(title))
vim.command("let doc_lines = %s" % len(text.split("\n")))
EOF
    "Scroll
    function! s:popup_filter(winid, key)
        if a:key ==# "\<c-k>"
            call win_execute(a:winid, "normal! \<c-y>")
            return v:true
        elseif a:key ==# "\<c-j>"
            call win_execute(a:winid, "normal! \<c-e>")
            return v:true
        elseif a:key ==# 'q' || a:key ==# 'x'
            return popup_filter_menu(a:winid, 'x')
        endif
        return v:false
    endfunction

    let lines = py3eval('text')
    let winid = popup_create(lines->split('\n'), #{
            \ filter: function('s:popup_filter'),
            \ pos: 'botleft',
            \ line: 'cursor-1',
            \ col: 'cursor',
            \ moved: 'any',
            \ border: [1,1,1,1,1,1,1,1],
            \ borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└'],
            \ borderhighlight: ['Todo'],    
            \ padding: [0,1,0,1],
            \ firstline: 1,
            \ scrollbar: 1,
            \ minwidth: docWidth,
            \ maxwidth: 74,
            \ minheight: doc_lines,
            \ maxheight: 20,
            \ mapping: 0,
            \ })

    call setbufvar(winbufnr(winid), '&syntax','rst')
    call setwinvar(winid, '&wincolor', 'Normal')
endfunction
josefson commented 4 years ago

@blayz3r thanks for this hack then. And to think i was on the verge to see what all that cocvim was about. Edit: Although I think it would be better if the fucntion allowed to be called in insertmode, so we could hit a bind, uppon selecting completion options.

montanier commented 4 years ago

Hi, just for the record, here is the hack of @blayz3r for neovim:

if has('nvim')
    autocmd FileType python nnoremap <buffer> K :call PyDocVim()<CR>

   function! PyDocVim()
python3 << EOF
import jedi

curfile = vim.current.buffer.name
row = vim.current.window.cursor[0]
col= vim.current.window.cursor[1]

script = jedi.Script(
   source=None,
   path=curfile,
   line=row,
   column=col)

try:
   definitions = script.goto_definitions()
except Exception:
   # print to stdout, will be in :messages
   definitions = []
   print("Exception, this shouldn't happen.")
   print(traceback.format_exc())

   if not definitions:
       echo_highlight("No documentation found for that.")
       vim.command("return")

docs = []
for d in definitions:
   doc = d.docstring()
   if doc:
       title = "Docstring for %s" % d.desc_with_module
       underline = "=" * len(title)
       docs.append("%s\n%s\n%s" % (title, underline, doc))
   else:
       docs.append("|No Docstring for %s|" % d)
   text = ("\n" + "-" * 79 + "\n").join(docs)
vim.command("let docWidth = %s" % len(title))
vim.command("let doc_lines = %s" % len(text.split("\n")))
EOF
       "Scroll
       function! s:popup_filter(winid, key)
           if a:key ==# "\<c-k>"
               call win_execute(a:winid, "normal! \<c-y>")
               return v:true
           elseif a:key ==# "\<c-j>"
               call win_execute(a:winid, "normal! \<c-e>")
               return v:true
           elseif a:key ==# 'q' || a:key ==# 'x'
               return popup_filter_menu(a:winid, 'x')
           endif
           return v:false
       endfunction

       let $FZF_DEFAULT_OPTS .= ' --border --margin=0,2'
       let width = float2nr(&columns * 0.9)
       let height = float2nr(&lines * 0.6)
       let opts = { 'relative': 'editor',
                  \ 'row': (&lines - height) / 2,
                  \ 'col': (&columns - width) / 2,
                  \ 'width': width,
                  \ 'height': height }

       let buf = nvim_create_buf(v:false, v:true)
       let lines = py3eval('text')
       call nvim_buf_set_lines(buf, 0, -1, v:true, split(lines, '\n'))
       let winid = nvim_open_win(buf, v:true, opts)
       call setwinvar(winid, '&winhighlight', 'NormalFloat:Normal')
    endfunction
endif
BrunoGomesCoelho commented 3 years ago

@montanier / @blayz3r I'm wondering if your hack still work? I'm getting errors when running it on Neovim 0.4.4 even though checkhealth shows my floathing window feture works fine, any ideas what it could be?

Error message

``` Error detected while processing function PyDocVim[38]..provider#python3#Call: line 18: Error invoking 'python_execute' on channel 3 (python3-script-host): Traceback (most recent call last): File "", line 11, in TypeError: __init__() got an unexpected keyword argument 'source' Error detected while processing function PyDocVim[53]..provider#python3#Call: line 18: Error invoking 'python_eval' on channel 3 (python3-script-host): error caught in request handler 'python_eval ['text']': Traceback (most recent call last): File "/home/bruno/.local/lib/python3.6/site-packages/pynvim/plugin/script_host.py", line 169, in python_eval return eval(expr, self.module.__dict__) File "", line 1, in NameError: name 'text' is not defined Error detected while processing function PyDocVim: line 54: E15: Invalid expression: >split('\n'), #{ filter: function('s:popup_filter'), pos: 'botleft', line: 'cursor-1', col: 'cursor', moved: 'any', border: [1,1,1,1,1,1,1,1], borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└'], b orderhighlight: ['Todo'], padding: [0,1,0,1], firstline: 1, scrollbar: 1, minwidth: docWidth, maxwidth: 74, minheight: doc_lines, maxheight: 20, mapping: 0, }) E116: Invalid arguments for function popup_create E15: Invalid expression: popup_create(lines->split('\n'), #{ filter: function('s:popup_filter'), pos: 'botleft', line: 'cursor-1', col: 'cursor', moved: 'any', border: [1,1,1,1,1,1,1,1], borderchars: ['─', '│', '─', '│', '┌' , '┐', '┘', '└'], borderhighlight: ['Todo'], padding: [0,1,0,1], firstline: 1, scrollbar: 1, minwidth: docWi dth, maxwidth: 74, minheight: doc_lines, maxheight: 20, mapping: 0, }) line 73: E121: Undefined variable: winid E116: Invalid arguments for function winbufnr E116: Invalid arguments for function setbufvar line 74: E121: Undefined variable: winid E116: Invalid arguments for function setwinvar ```

blayz3r commented 3 years ago

@montanier / @blayz3r I'm wondering if your hack still work? I'm getting errors when running it on Neovim 0.4.4 even though checkhealth shows my floathing window feture works fine, any ideas what it could be? Error message

Error detected while processing function PyDocVim[38]..provider#python3#Call:                         
line   18:
Error invoking 'python_execute' on channel 3 (python3-script-host):
Traceback (most recent call last):
  File "<string>", line 11, in <module>
TypeError: __init__() got an unexpected keyword argument 'source'
Error detected while processing function PyDocVim[53]..provider#python3#Call:
line   18:
Error invoking 'python_eval' on channel 3 (python3-script-host):
error caught in request handler 'python_eval ['text']':
Traceback (most recent call last):
  File "/home/bruno/.local/lib/python3.6/site-packages/pynvim/plugin/script_host.py", line 169, in python_eval
    return eval(expr, self.module.__dict__)
  File "<string>", line 1, in <module>
NameError: name 'text' is not defined
Error detected while processing function PyDocVim:
line   54:
E15: Invalid expression: >split('\n'), #{ filter: function('s:popup_filter'), pos: 'botleft', line: 'cursor-1', 
col: 'cursor', moved: 'any', border: [1,1,1,1,1,1,1,1], borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└'], b
orderhighlight: ['Todo'],     padding: [0,1,0,1], firstline: 1, scrollbar: 1, minwidth: docWidth, maxwidth: 74, 
minheight: doc_lines, maxheight: 20, mapping: 0, })
E116: Invalid arguments for function popup_create
E15: Invalid expression: popup_create(lines->split('\n'), #{ filter: function('s:popup_filter'), pos: 'botleft',
 line: 'cursor-1', col: 'cursor', moved: 'any', border: [1,1,1,1,1,1,1,1], borderchars: ['─', '│', '─', '│', '┌'
, '┐', '┘', '└'], borderhighlight: ['Todo'],     padding: [0,1,0,1], firstline: 1, scrollbar: 1, minwidth: docWi
dth, maxwidth: 74, minheight: doc_lines, maxheight: 20, mapping: 0, })
line   73:
E121: Undefined variable: winid
E116: Invalid arguments for function winbufnr
E116: Invalid arguments for function setbufvar
line   74:
E121: Undefined variable: winid
E116: Invalid arguments for function setwinvar

Jedi replaced "source" with code

script = jedi.Script(
    code=None,
    path=curfile)

try:
    definitions = script.help(line=row,
    column=col)
except Exception:
    # print to stdout, will be in :messages
    definitions = []
    print("Exception, this shouldn't happen.")
    print(traceback.format_exc())

    if not definitions:
        echo_highlight("No documentation found for that.")
        vim.command("return")
BrunoGomesCoelho commented 3 years ago

Thank you very much, that was indeed the problem!

I also had to change title = "Docstring for %s" % d.desc_with_module to title = "Docstring for %s" % d.full_name to make it work;

I added a line for color support in neovim since it didn't have any color syntaxing without: call setbufvar(winbufnr(winid), '&syntax','rst')

Here's my current full code for nvim if useful

```vim "----- show documentation in floaterm window from https://github.com/neovim/neovim/issues/1004 if has('nvim') autocmd FileType python nnoremap K :call PyDocVim() function! PyDocVim() python3 << EOF import jedi curfile = vim.current.buffer.name row = vim.current.window.cursor[0] col= vim.current.window.cursor[1] script = jedi.Script( code=None, path=curfile) try: definitions = script.help(line=row, column=col) # definitions = script.goto_definitions() except Exception: # print to stdout, will be in :messages definitions = [] print("Exception, this shouldn't happen.") print(traceback.format_exc()) if not definitions: echo_highlight("No documentation found for that.") vim.command("return") docs = [] for d in definitions: doc = d.docstring() if doc: title = "Docstring for %s" % d.full_name underline = "=" * len(title) docs.append("%s\n%s\n%s" % (title, underline, doc)) else: docs.append("|No Docstring for %s|" % d) text = ("\n" + "-" * 79 + "\n").join(docs) vim.command("let docWidth = %s" % len(title)) vim.command("let doc_lines = %s" % len(text.split("\n"))) EOF "Scroll function! s:popup_filter(winid, key) if a:key ==# "\" call win_execute(a:winid, "normal! \") return v:true elseif a:key ==# "\" call win_execute(a:winid, "normal! \") return v:true elseif a:key ==# 'q' || a:key ==# 'x' return popup_filter_menu(a:winid, 'x') endif return v:false endfunction let $FZF_DEFAULT_OPTS .= ' --border --margin=0,2' let width = float2nr(&columns * 0.9) let height = float2nr(&lines * 0.6) let opts = { 'relative': 'editor', \ 'row': (&lines - height) / 2, \ 'col': (&columns - width) / 2, \ 'width': width, \ 'height': height } let buf = nvim_create_buf(v:false, v:true) let lines = py3eval('text') call nvim_buf_set_lines(buf, 0, -1, v:true, split(lines, '\n')) let winid = nvim_open_win(buf, v:true, opts) " call setwinvar(winid, '&wincolor', 'Normal') call setbufvar(winbufnr(winid), '&syntax','rst') call setwinvar(winid, '&winhighlight', 'NormalFloat:Normal') endfunction endif ```

BALAJI24092001 commented 1 year ago

I'm new to neovim, I'm getting this docstring instead of what is shown in the above messages. Can someone help me how to make this right image