Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show documentation on (neovim) floating window? #973

Open
hungrybirder opened this issue Dec 19, 2019 · 12 comments
Open

Show documentation on (neovim) floating window? #973

hungrybirder opened this issue Dec 19, 2019 · 12 comments

Comments

@hungrybirder
Copy link

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
Copy link
Owner

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

@hungrybirder
Copy link
Author

hungrybirder commented Dec 23, 2019

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
Copy link
Owner

@blueyed

@blayz3r
Copy link

blayz3r commented Feb 9, 2020

@blueyed is the goal to have this:

@blueyed
Copy link
Collaborator

blueyed commented Feb 10, 2020

#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
Copy link

blayz3r commented Feb 21, 2020

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
Copy link

josefson commented Mar 15, 2020

@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
Copy link

montanier commented Aug 14, 2020

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
Copy link

@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

@blayz3r
Copy link

blayz3r commented Dec 31, 2020

@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
Copy link

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

"----- show documentation in floaterm window from https://github.com/neovim/neovim/issues/1004
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(
    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 ==# "\<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, '&wincolor', 'Normal')
	    call setbufvar(winbufnr(winid), '&syntax','rst')
	   call setwinvar(winid, '&winhighlight', 'NormalFloat:Normal')
	endfunction
endif

@BALAJI24092001
Copy link

BALAJI24092001 commented Oct 7, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants