diff --git a/after/syntax/python.vim b/after/syntax/python.vim index 3fa6608..72ca838 100644 --- a/after/syntax/python.vim +++ b/after/syntax/python.vim @@ -1,4 +1,4 @@ -if g:jedi#show_call_signatures == 1 && has('conceal') +if g:jedi#show_call_signatures > 0 && has('conceal') " conceal is normal for vim >= 7.3 let s:e = g:jedi#call_signature_escape diff --git a/autoload/jedi.vim b/autoload/jedi.vim index 159e6e8..54cb533 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -155,10 +155,60 @@ endfunction function! jedi#configure_call_signatures() + if g:jedi#show_call_signatures == 2 " Command line call signatures + " Need to track changes to avoid multiple undo points for a single edit + let b:normaltick = b:changedtick + autocmd TextChanged,InsertLeave,BufWinEnter let b:normaltick = b:changedtick + endif + autocmd InsertEnter let g:jedi#first_col = s:save_first_col() autocmd InsertLeave Python jedi_vim.clear_call_signatures() autocmd CursorMovedI Python jedi_vim.show_call_signatures() endfunction +" Determine where the current window is on the screen for displaying call +" signatures in the correct column. +function! s:save_first_col() + let gutterwidth = &fdc + &number * max([&numberwidth, len(line('$')) + 1]) + if bufname('%') ==# '[Command Line]' | return gutterwidth + 1 | endif + if winnr('$') == 1 | return gutterwidth | endif + + let l:eventignore = &eventignore + set eventignore=all + let startwin = winnr() + let startaltwin = winnr('#') + let winwidth = winwidth(0) + + try + wincmd h + let win_on_left = winnr() == startwin + if win_on_left + return gutterwidth + else + " Walk left and count up window widths until hitting the edge + execute startwin."wincmd w" + let width = 0 + let winnr = winnr() + wincmd h + while winnr != winnr() + let width += winwidth(0) + 1 " Extra column for window divider + let winnr = winnr() + wincmd h + endwhile + return width + gutterwidth + endif + finally + let &eventignore = l:eventignore + execute startaltwin."wincmd w" + execute startwin."wincmd w" + " If the event that triggered InsertEnter made a change (e.g. open a + " new line, substitude a word), join that change with the rest of this + " edit. + if b:normaltick != b:changedtick + undojoin + endif + endtry +endfunction + " Helper function instead of `python vim.eval()`, and `.command()` because " these also return error definitions. function! jedi#_vim_exceptions(str, is_eval) diff --git a/doc/jedi-vim.txt b/doc/jedi-vim.txt index bd55852..8cbfa63 100644 --- a/doc/jedi-vim.txt +++ b/doc/jedi-vim.txt @@ -379,9 +379,10 @@ Default: 1 (Automatically close preview window upon leaving insert mode) Jedi-vim can display a small window detailing the arguments of the currently completed function and highlighting the currently selected argument. This can -be disabled by setting this option to 0. +be disabled by setting this option to 0. Setting this option to 2 shows call +signatures in the command line instead of a popup window. -Options: 0 or 1 +Options: 0, 1, or 2 Default: 1 (Show call signatures window) Note: This setting is ignored if |g:jedi#auto_initialization| is set to 0. In diff --git a/ftplugin/python/jedi.vim b/ftplugin/python/jedi.vim index 938b10c..b2f4104 100644 --- a/ftplugin/python/jedi.vim +++ b/ftplugin/python/jedi.vim @@ -25,7 +25,7 @@ if g:jedi#auto_initialization execute "nnoremap ".g:jedi#documentation_command." :call jedi#show_documentation()" endif - if g:jedi#show_call_signatures == 1 && has('conceal') + if g:jedi#show_call_signatures > 0 && has('conceal') call jedi#configure_call_signatures() endif diff --git a/jedi_vim.py b/jedi_vim.py index f5f9fda..77504f2 100644 --- a/jedi_vim.py +++ b/jedi_vim.py @@ -8,6 +8,10 @@ import re import os import sys from shlex import split as shsplit +try: + from itertools import zip_longest +except ImportError: + from itertools import izip_longest as zip_longest # Python 2 import vim import jedi @@ -228,6 +232,10 @@ def show_documentation(): @catch_and_print_exceptions def clear_call_signatures(): + # Check if using command line call signatures + if vim_eval("g:jedi#show_call_signatures") == '2': + vim_command('echo ""') + return cursor = vim.current.window.cursor e = vim_eval('g:jedi#call_signature_escape') regex = r'%sjedi=([0-9]+), ([^%s]*)%s.*%sjedi%s'.replace('%s', e) @@ -255,6 +263,9 @@ def show_call_signatures(signatures=()): if not signatures: return + if vim_eval("g:jedi#show_call_signatures") == '2': + return cmdline_call_signatures(signatures) + for i, signature in enumerate(signatures): line, column = signature.bracket_start # signatures are listed above each other @@ -310,6 +321,53 @@ def show_call_signatures(signatures=()): vim_eval('setline(%s, %s)' % (line_to_replace, repr(PythonToVimStr(repl)))) +@catch_and_print_exceptions +def cmdline_call_signatures(signatures): + def get_params(s): + return [p.description.replace('\n', '') for p in s.params] + + if len(signatures) > 1: + params = zip_longest(*map(get_params, signatures), fillvalue='_') + params = ['(' + ', '.join(p) + ')' for p in params] + else: + params = get_params(signatures[0]) + text = ', '.join(params) + + # Allow 12 characters for ruler/showcmd - setting noruler/noshowcmd + # here causes incorrect undo history + max_msg_len = int(vim_eval('&columns')) - 12 + max_num_spaces = (max_msg_len - len(signatures[0].call_name) + - len(text) - 2) # 2 accounts for parentheses + if max_num_spaces < 0: + return # No room for the message + _, column = signatures[0].bracket_start + num_spaces = min(int(vim_eval('g:jedi#first_col')) + + column - len(signatures[0].call_name), + max_num_spaces) + spaces = ' ' * num_spaces + + try: + index = [s.index for s in signatures if isinstance(s.index, int)][0] + left = text.index(params[index]) + right = left + len(params[index]) + vim_command(' echon "%s" | ' + 'echohl Function | echon "%s" | ' + 'echohl None | echon "(" | ' + 'echohl jediFunction | echon "%s" | ' + 'echohl jediFat | echon "%s" | ' + 'echohl jediFunction | echon "%s" | ' + 'echohl None | echon ")"' + % (spaces, signatures[0].call_name, text[:left], + text[left:right], text[right:])) + except (TypeError, IndexError): + vim_command(' echon "%s" | ' + 'echohl Function | echon "%s" | ' + 'echohl None | echon "(" | ' + 'echohl jediFunction | echon "%s" | ' + 'echohl None | echon ")"' + % (spaces, signatures[0].call_name, text)) + + @catch_and_print_exceptions def rename(): if not int(vim.eval('a:0')):