mirror of
https://github.com/davidhalter/jedi-vim.git
synced 2025-12-06 18:54:44 +08:00
This will use CursorHoldI instead of CursorMovedI for displaying call signatures, with a delay of 500ms by default. This greatly enhances the experience with slow call signatures while typing (depending on how fast Jedi is for the given context).
480 lines
14 KiB
VimL
480 lines
14 KiB
VimL
scriptencoding utf-8
|
|
|
|
" ------------------------------------------------------------------------
|
|
" Settings initialization
|
|
" ------------------------------------------------------------------------
|
|
let s:deprecations = {
|
|
\ 'get_definition_command': 'goto_definitions_command',
|
|
\ 'pydoc': 'documentation_command',
|
|
\ 'related_names_command': 'usages_command',
|
|
\ 'autocompletion_command': 'completions_command',
|
|
\ 'show_function_definition': 'show_call_signatures',
|
|
\ }
|
|
|
|
let s:default_settings = {
|
|
\ 'use_tabs_not_buffers': 0,
|
|
\ 'use_splits_not_buffers': 1,
|
|
\ 'auto_initialization': 1,
|
|
\ 'auto_vim_configuration': 1,
|
|
\ 'goto_command': "'<leader>d'",
|
|
\ 'goto_assignments_command': "'<leader>g'",
|
|
\ 'goto_definitions_command': "''",
|
|
\ 'completions_command': "'<C-Space>'",
|
|
\ 'call_signatures_command': "'<leader>n'",
|
|
\ 'usages_command': "'<leader>n'",
|
|
\ 'rename_command': "'<leader>r'",
|
|
\ 'popup_on_dot': 1,
|
|
\ 'documentation_command': "'K'",
|
|
\ 'show_call_signatures': 1,
|
|
\ 'show_call_signatures_delay': 500,
|
|
\ 'call_signature_escape': "'=`='",
|
|
\ 'auto_close_doc': 1,
|
|
\ 'max_doc_height': 30,
|
|
\ 'popup_select_first': 1,
|
|
\ 'quickfix_window_height': 10,
|
|
\ 'completions_enabled': 1,
|
|
\ 'force_py_version': "'auto'",
|
|
\ 'smart_auto_mappings': 1
|
|
\ }
|
|
|
|
for [key, val] in items(s:deprecations)
|
|
if exists('g:jedi#'.key)
|
|
echom "'g:jedi#".key."' is deprecated. Please use 'g:jedi#".val."' instead. Sorry for the inconvenience."
|
|
exe 'let g:jedi#'.val.' = g:jedi#'.key
|
|
endif
|
|
endfor
|
|
|
|
for [key, val] in items(s:default_settings)
|
|
if !exists('g:jedi#'.key)
|
|
exe 'let g:jedi#'.key.' = '.val
|
|
endif
|
|
endfor
|
|
|
|
|
|
" ------------------------------------------------------------------------
|
|
" Python initialization
|
|
" ------------------------------------------------------------------------
|
|
let s:script_path = fnameescape(expand('<sfile>:p:h:h'))
|
|
|
|
function! s:init_python()
|
|
if g:jedi#force_py_version != 'auto'
|
|
" Always use the user supplied version.
|
|
try
|
|
return jedi#force_py_version(g:jedi#force_py_version)
|
|
catch
|
|
throw "Could not setup g:jedi#force_py_version: ".v:exception
|
|
endtry
|
|
endif
|
|
|
|
" Handle "auto" version.
|
|
if has('nvim') || (has('python') && has('python3'))
|
|
" Neovim usually has both python providers. Skipping the `has` check
|
|
" avoids starting both of them.
|
|
|
|
" Get default python version from interpreter in $PATH.
|
|
let s:def_py = system('python -c '.shellescape('import sys; sys.stdout.write(str(sys.version_info[0]))'))
|
|
if v:shell_error != 0 || !len(s:def_py)
|
|
if !exists("g:jedi#squelch_py_warning")
|
|
echohl WarningMsg
|
|
echom "Warning: jedi-vim failed to get Python version from sys.version_info: " . s:def_py
|
|
echom "Falling back to version 2."
|
|
echohl None
|
|
endif
|
|
let s:def_py = 2
|
|
elseif &verbose
|
|
echom "jedi-vim: auto-detected Python: ".s:def_py
|
|
endif
|
|
|
|
" Make sure that the auto-detected version is available in Vim.
|
|
if !has('nvim') || has('python'.(s:def_py == 2 ? '' : s:def_py))
|
|
return jedi#force_py_version(s:def_py)
|
|
endif
|
|
|
|
" Add a warning in case the auto-detected version is not available,
|
|
" usually because of a missing neovim module in a VIRTUAL_ENV.
|
|
if has('nvim')
|
|
echohl WarningMsg
|
|
echom "jedi-vim: the detected Python version (".s:def_py.")"
|
|
\ "is not functional."
|
|
\ "Is the 'neovim' module installed?"
|
|
\ "While jedi-vim will work, it might not use the"
|
|
\ "expected Python path."
|
|
echohl None
|
|
endif
|
|
endif
|
|
|
|
if has('python')
|
|
call jedi#setup_py_version(2)
|
|
elseif has('python3')
|
|
call jedi#setup_py_version(3)
|
|
else
|
|
throw "jedi-vim requires Vim with support for Python 2 or 3."
|
|
endif
|
|
return 1
|
|
endfunction
|
|
|
|
|
|
function! jedi#reinit_python()
|
|
unlet! s:_init_python
|
|
call jedi#init_python()
|
|
endfunction
|
|
|
|
|
|
function! jedi#init_python()
|
|
if !exists('s:_init_python')
|
|
try
|
|
let s:_init_python = s:init_python()
|
|
catch
|
|
if !exists("g:jedi#squelch_py_warning")
|
|
echohl WarningMsg
|
|
echom "Error: jedi-vim failed to initialize Python: ".v:exception." (in ".v:throwpoint.")"
|
|
echohl None
|
|
endif
|
|
let s:_init_python = 0
|
|
endtry
|
|
endif
|
|
return s:_init_python
|
|
endfunction
|
|
|
|
|
|
let s:python_version = 'null'
|
|
function! jedi#setup_py_version(py_version)
|
|
if a:py_version == 2
|
|
let cmd_init = 'pyfile'
|
|
let cmd_exec = 'python'
|
|
let s:python_version = 2
|
|
elseif a:py_version == 3
|
|
let cmd_init = 'py3file'
|
|
let cmd_exec = 'python3'
|
|
let s:python_version = 3
|
|
else
|
|
throw "jedi#setup_py_version: invalid py_version: ".a:py_version
|
|
endif
|
|
|
|
try
|
|
execute cmd_init.' '.s:script_path.'/initialize.py'
|
|
execute 'command! -nargs=1 PythonJedi '.cmd_exec.' <args>'
|
|
return 1
|
|
catch
|
|
throw "jedi#setup_py_version: ".v:exception
|
|
endtry
|
|
endfunction
|
|
|
|
|
|
function! jedi#debug_info()
|
|
echom "Using Python version:" s:python_version
|
|
endfunction
|
|
|
|
|
|
function! jedi#force_py_version(py_version)
|
|
let g:jedi#force_py_version = a:py_version
|
|
return jedi#setup_py_version(a:py_version)
|
|
endfunction
|
|
|
|
|
|
function! jedi#force_py_version_switch()
|
|
if g:jedi#force_py_version == 2
|
|
call jedi#force_py_version(3)
|
|
elseif g:jedi#force_py_version == 3
|
|
call jedi#force_py_version(2)
|
|
else
|
|
throw "Don't know how to switch from ".g:jedi#force_py_version."!"
|
|
endif
|
|
endfunction
|
|
|
|
|
|
" Helper function instead of `python vim.eval()`, and `.command()` because
|
|
" these also return error definitions.
|
|
function! jedi#_vim_exceptions(str, is_eval)
|
|
let l:result = {}
|
|
try
|
|
if a:is_eval
|
|
let l:result.result = eval(a:str)
|
|
else
|
|
execute a:str
|
|
let l:result.result = ''
|
|
endif
|
|
catch
|
|
let l:result.exception = v:exception
|
|
let l:result.throwpoint = v:throwpoint
|
|
endtry
|
|
return l:result
|
|
endfunction
|
|
|
|
|
|
if !jedi#init_python()
|
|
" Do not define any functions when Python initialization failed.
|
|
finish
|
|
endif
|
|
|
|
|
|
" ------------------------------------------------------------------------
|
|
" functions that call python code
|
|
" ------------------------------------------------------------------------
|
|
function! jedi#goto()
|
|
PythonJedi jedi_vim.goto(mode="goto")
|
|
endfunction
|
|
|
|
function! jedi#goto_assignments()
|
|
PythonJedi jedi_vim.goto(mode="assignment")
|
|
endfunction
|
|
|
|
function! jedi#goto_definitions()
|
|
PythonJedi jedi_vim.goto(mode="definition")
|
|
endfunction
|
|
|
|
function! jedi#usages()
|
|
PythonJedi jedi_vim.goto(mode="related_name")
|
|
endfunction
|
|
|
|
function! jedi#rename(...)
|
|
PythonJedi jedi_vim.rename()
|
|
endfunction
|
|
|
|
function! jedi#rename_visual(...)
|
|
PythonJedi jedi_vim.rename_visual()
|
|
endfunction
|
|
|
|
function! jedi#completions(findstart, base)
|
|
PythonJedi jedi_vim.completions()
|
|
endfunction
|
|
|
|
function! jedi#enable_speed_debugging()
|
|
PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False)
|
|
endfunction
|
|
|
|
function! jedi#enable_debugging()
|
|
PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout)
|
|
endfunction
|
|
|
|
function! jedi#disable_debugging()
|
|
PythonJedi jedi_vim.jedi.set_debug_function(None)
|
|
endfunction
|
|
|
|
function! jedi#py_import(args)
|
|
PythonJedi jedi_vim.py_import()
|
|
endfun
|
|
|
|
function! jedi#py_import_completions(argl, cmdl, pos)
|
|
PythonJedi jedi_vim.py_import_completions()
|
|
endfun
|
|
|
|
|
|
" ------------------------------------------------------------------------
|
|
" show_documentation
|
|
" ------------------------------------------------------------------------
|
|
function! jedi#show_documentation()
|
|
PythonJedi if jedi_vim.show_documentation() is None: vim.command('return')
|
|
|
|
let bn = bufnr("__doc__")
|
|
if bn > 0
|
|
let wi=index(tabpagebuflist(tabpagenr()), bn)
|
|
if wi >= 0
|
|
" If the __doc__ buffer is open in the current tab, jump to it
|
|
silent execute (wi+1).'wincmd w'
|
|
else
|
|
silent execute "sbuffer ".bn
|
|
endif
|
|
else
|
|
split '__doc__'
|
|
endif
|
|
|
|
setlocal modifiable
|
|
setlocal noswapfile
|
|
setlocal buftype=nofile
|
|
silent normal! ggdG
|
|
silent $put=l:doc
|
|
silent normal! 1Gdd
|
|
setlocal nomodifiable
|
|
setlocal nomodified
|
|
setlocal filetype=rst
|
|
|
|
if l:doc_lines > g:jedi#max_doc_height " max lines for plugin
|
|
let l:doc_lines = g:jedi#max_doc_height
|
|
endif
|
|
execute "resize ".l:doc_lines
|
|
|
|
" quit comands
|
|
nnoremap <buffer> q ZQ
|
|
execute "nnoremap <buffer> ".g:jedi#documentation_command." ZQ"
|
|
|
|
" highlight python code within rst
|
|
unlet! b:current_syntax
|
|
syn include @rstPythonScript syntax/python.vim
|
|
" 4 spaces
|
|
syn region rstPythonRegion start=/^\v {4}/ end=/\v^( {4}|\n)@!/ contains=@rstPythonScript
|
|
" >>> python code -> (doctests)
|
|
syn region rstPythonRegion matchgroup=pythonDoctest start=/^>>>\s*/ end=/\n/ contains=@rstPythonScript
|
|
let b:current_syntax = "rst"
|
|
endfunction
|
|
|
|
" ------------------------------------------------------------------------
|
|
" helper functions
|
|
" ------------------------------------------------------------------------
|
|
|
|
function! jedi#add_goto_window(len)
|
|
set lazyredraw
|
|
cclose
|
|
let height = min([a:len, g:jedi#quickfix_window_height])
|
|
execute 'belowright copen '.height
|
|
set nolazyredraw
|
|
if g:jedi#use_tabs_not_buffers == 1
|
|
noremap <buffer> <CR> :call jedi#goto_window_on_enter()<CR>
|
|
endif
|
|
au WinLeave <buffer> q " automatically leave, if an option is chosen
|
|
redraw!
|
|
endfunction
|
|
|
|
|
|
function! jedi#goto_window_on_enter()
|
|
let l:list = getqflist()
|
|
let l:data = l:list[line('.') - 1]
|
|
if l:data.bufnr
|
|
" close goto_window buffer
|
|
normal ZQ
|
|
PythonJedi jedi_vim.new_buffer(vim.eval('bufname(l:data.bufnr)'))
|
|
call cursor(l:data.lnum, l:data.col)
|
|
else
|
|
echohl WarningMsg | echo "Builtin module cannot be opened." | echohl None
|
|
endif
|
|
endfunction
|
|
|
|
|
|
function! s:syn_stack()
|
|
if !exists("*synstack")
|
|
return []
|
|
endif
|
|
return map(synstack(line('.'), col('.') - 1), 'synIDattr(v:val, "name")')
|
|
endfunc
|
|
|
|
|
|
function! jedi#do_popup_on_dot_in_highlight()
|
|
let highlight_groups = s:syn_stack()
|
|
for a in highlight_groups
|
|
if a == 'pythonDoctest'
|
|
return 1
|
|
endif
|
|
endfor
|
|
|
|
for a in highlight_groups
|
|
for b in ['pythonString', 'pythonComment', 'pythonNumber']
|
|
if a == b
|
|
return 0
|
|
endif
|
|
endfor
|
|
endfor
|
|
return 1
|
|
endfunc
|
|
|
|
|
|
function! jedi#configure_call_signatures()
|
|
augroup jedi_call_signatures
|
|
au!
|
|
if g:jedi#show_call_signatures == 2 " Command line call signatures
|
|
autocmd InsertEnter <buffer> let g:jedi#first_col = s:save_first_col()
|
|
endif
|
|
autocmd InsertLeave <buffer> PythonJedi jedi_vim.clear_call_signatures()
|
|
if g:jedi#show_call_signatures_delay > 0
|
|
autocmd InsertEnter <buffer> let b:_jedi_orig_updatetime = &updatetime
|
|
\ | let &updatetime = g:jedi#show_call_signatures_delay
|
|
autocmd InsertLeave <buffer> if exists('b:_jedi_orig_updatetime')
|
|
\ | let &updatetime = b:_jedi_orig_updatetime
|
|
\ | unlet b:_jedi_orig_updatetime
|
|
\ | endif
|
|
autocmd CursorHoldI <buffer> PythonJedi jedi_vim.show_call_signatures()
|
|
else
|
|
autocmd CursorMovedI <buffer> PythonJedi jedi_vim.show_call_signatures()
|
|
endif
|
|
augroup END
|
|
endfunction
|
|
|
|
|
|
" Determine where the current window is on the screen for displaying call
|
|
" signatures in the correct column.
|
|
function! s:save_first_col()
|
|
if bufname('%') ==# '[Command Line]' || winnr('$') == 1
|
|
return 0
|
|
endif
|
|
|
|
let startwin = winnr()
|
|
let winwidth = winwidth(0)
|
|
if winwidth == &columns
|
|
return 0
|
|
elseif winnr('$') == 2
|
|
return startwin == 1 ? 0 : (winwidth(1) + 1)
|
|
elseif winnr('$') == 3
|
|
if startwin == 1
|
|
return 0
|
|
endif
|
|
let ww1 = winwidth(1)
|
|
let ww2 = winwidth(2)
|
|
let ww3 = winwidth(3)
|
|
if ww1 + ww2 + ww3 + 2 == &columns
|
|
if startwin == 2
|
|
return ww1 + 1
|
|
else
|
|
return ww1 + ww2 + 2
|
|
endif
|
|
elseif startwin == 2
|
|
if ww2 + ww3 + 1 == &columns
|
|
return 0
|
|
else
|
|
return ww1 + 1
|
|
endif
|
|
else " startwin == 3
|
|
if ww2 + ww3 + 1 == &columns
|
|
return ww2 + 1
|
|
else
|
|
return ww1 + 1
|
|
endif
|
|
endif
|
|
endif
|
|
return 0
|
|
endfunction
|
|
|
|
|
|
function! jedi#complete_string(is_popup_on_dot)
|
|
|
|
if a:is_popup_on_dot && !(g:jedi#popup_on_dot && jedi#do_popup_on_dot_in_highlight())
|
|
return ''
|
|
|
|
endif
|
|
if pumvisible() && !a:is_popup_on_dot
|
|
return "\<C-n>"
|
|
else
|
|
return "\<C-x>\<C-o>\<C-r>=jedi#complete_opened(".a:is_popup_on_dot.")\<CR>"
|
|
endif
|
|
endfunction
|
|
|
|
|
|
function! jedi#complete_opened(is_popup_on_dot)
|
|
if pumvisible()
|
|
" Only go down if it is visible, user-enabled and the longest
|
|
" option is set.
|
|
if g:jedi#popup_select_first && stridx(&completeopt, 'longest') > -1
|
|
return "\<Down>"
|
|
endif
|
|
if a:is_popup_on_dot
|
|
" Prevent completion of the first entry with dot completion.
|
|
return "\<C-p>"
|
|
endif
|
|
endif
|
|
return ""
|
|
endfunction
|
|
|
|
|
|
function! jedi#smart_auto_mappings()
|
|
" Auto put import statement after from module.name<space> and complete
|
|
if search('\<from\s\+[A-Za-z0-9._]\{1,50}\%#\s*$', 'bcn', line('.'))
|
|
" Enter character and start completion.
|
|
return "\<space>import \<C-x>\<C-o>\<C-r>=jedi#complete_opened(1)\<CR>"
|
|
endif
|
|
return "\<space>"
|
|
endfunction
|
|
|
|
|
|
"PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False)
|
|
"PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout)
|
|
|
|
" vim: set et ts=4:
|