From dac91047444e5c907226b1cae39bb3ce428bc441 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 15 Jul 2018 20:39:48 +0200 Subject: [PATCH] Support for jedi-vim's call signatures Adds s:getline() and s:prevnonblank() wrappers to use b:_jedi_callsig_orig for the original line contents. Requires https://github.com/davidhalter/jedi-vim/pull/652. --- indent/python.vim | 71 +++++++++++++++++++++++++++----------- spec/indent/indent_spec.rb | 14 ++++++-- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/indent/python.vim b/indent/python.vim index aca216e..e135c1e 100644 --- a/indent/python.vim +++ b/indent/python.vim @@ -67,9 +67,9 @@ endif let s:stop_statement = '^\s*\(break\|continue\|raise\|return\|pass\)\>' let s:skip_after_opening_paren = 'synIDattr(synID(line("."), col("."), 0), "name") ' . - \ '=~? "\\vcomment|jedi\\S"' + \ '=~? "\\vcomment"' -let s:special_chars_syn_pattern = "\\vstring|comment|^pythonbytes%(contents)=$|pythonTodo|jedi\\S" +let s:special_chars_syn_pattern = "\\vstring|comment|^pythonbytes%(contents)=$|pythonTodo" if !get(g:, 'python_pep8_indent_skip_concealed', 0) || !has('conceal') " Skip strings and comments. Return 1 for chars to skip. @@ -136,8 +136,8 @@ endfunction function! s:find_start_of_multiline_statement(lnum) let lnum = a:lnum while lnum > 0 - if getline(lnum - 1) =~# '\\$' - let lnum = prevnonblank(lnum - 1) + if s:getline(lnum - 1) =~# '\\$' + let lnum = s:prevnonblank(lnum - 1) else let [paren_lnum, _] = s:find_opening_paren(lnum, 1) if paren_lnum < 1 @@ -163,7 +163,7 @@ function! s:find_start_of_block(lnum, types, skip, multiple) abort while lnum > 0 && last_indent > 0 let indent = indent(lnum) if indent < last_indent - let line = getline(lnum) + let line = s:getline(lnum) if !empty(re_skip) && line =~# re_skip let last_indent = indent elseif line =~# re @@ -176,7 +176,7 @@ function! s:find_start_of_block(lnum, types, skip, multiple) abort let last_indent = indent endif endif - let lnum = prevnonblank(lnum - 1) + let lnum = s:prevnonblank(lnum - 1) endwhile return r endfunction @@ -184,7 +184,7 @@ endfunction " Is "expr" true for every position in "lnum", beginning at "start"? " (optionally up to a:1 / 4th argument) function! s:match_expr_on_line(expr, lnum, start, ...) - let text = getline(a:lnum) + let text = s:getline(a:lnum) let end = a:0 ? a:1 : len(text) if a:start > end return 1 @@ -208,12 +208,12 @@ function! s:indent_like_opening_paren(lnum) if paren_lnum <= 0 return -2 endif - let text = getline(paren_lnum) + let text = s:getline(paren_lnum) let base = indent(paren_lnum) let nothing_after_opening_paren = s:match_expr_on_line( \ s:skip_after_opening_paren, paren_lnum, paren_col+1) - let starts_with_closing_paren = getline(a:lnum) =~# '^\s*[])}]' + let starts_with_closing_paren = s:getline(a:lnum) =~# '^\s*[])}]' let hang_closing = get(b:, 'python_pep8_indent_hang_closing', \ get(g:, 'python_pep8_indent_hang_closing', 0)) @@ -249,7 +249,7 @@ endfunction " Match indent of first block of this type. function! s:indent_like_block(lnum) - let text = getline(a:lnum) + let text = s:getline(a:lnum) for [multiple, block_rules] in [ \ [0, s:block_rules], \ [1, s:block_rules_multiple], @@ -281,15 +281,45 @@ function! s:indent_like_block(lnum) return -2 endfunction +" Wrapper around getline that looks up jedi-vim's b:_jedi_callsig_orig to get +" the original line. +function! s:getline(lnum) abort + let line = get(get(b:, '_jedi_callsig_orig', {}), a:lnum, 0) + if line is 0 + return getline(a:lnum) + endif + return line +endfunction + +" Wrapper around prevnonblank that looks up jedi-vim's b:_jedi_callsig_orig to +" check the original line's contents additionally. +function! s:prevnonblank(lnum) abort + let lnum = a:lnum + while 1 + let lnum = prevnonblank(lnum) + if lnum < 1 + return lnum + endif + let orig_line = get(get(b:, '_jedi_callsig_orig', {}), lnum, 0) + if orig_line is 0 + return lnum + endif + if !empty(orig_line) + return lnum + endif + let lnum -= 1 + endwhile +endfunction + function! s:indent_like_previous_line(lnum) - let lnum = prevnonblank(a:lnum - 1) + let lnum = s:prevnonblank(a:lnum - 1) " No previous line, keep current indent. if lnum < 1 return -1 endif - let text = getline(lnum) + let text = s:getline(lnum) let start = s:find_start_of_multiline_statement(lnum) let base = indent(start) let current = indent(a:lnum) @@ -314,7 +344,7 @@ function! s:indent_like_previous_line(lnum) " If this line is the continuation of a control statement " indent further to distinguish the continuation line " from the next logical line. - if getline(start) =~# b:control_statement + if s:getline(start) =~# b:control_statement return base + s:sw() * 2 endif @@ -322,17 +352,17 @@ function! s:indent_like_previous_line(lnum) return base + s:sw() endif - let empty = getline(a:lnum) =~# '^\s*$' + let empty = s:getline(a:lnum) =~# '^\s*$' " Current and prev line are empty, next is not -> indent like next. if empty && a:lnum > 1 && - \ (getline(a:lnum - 1) =~# '^\s*$') && - \ !(getline(a:lnum + 1) =~# '^\s*$') + \ (s:getline(a:lnum - 1) =~# '^\s*$') && + \ !(s:getline(a:lnum + 1) =~# '^\s*$') return indent(a:lnum + 1) endif " If the previous statement was a stop-execution statement or a pass - if getline(start) =~# s:stop_statement + if s:getline(start) =~# s:stop_statement " Remove one level of indentation if the user hasn't already dedented if empty || current > base - s:sw() return base - s:sw() @@ -358,11 +388,10 @@ endfunction " Is the syntax at lnum (and optionally cnum) a python string? function! s:is_python_string(lnum, ...) - let line = getline(a:lnum) if a:0 let cols = type(a:1) != type([]) ? [a:1] : a:1 else - let cols = range(1, max([1, len(line)])) + let cols = range(1, max([1, len(s:getline(a:lnum))])) endif for cnum in cols if match(map(synstack(a:lnum, cnum), @@ -379,8 +408,8 @@ function! GetPythonPEPIndent(lnum) return 0 endif - let line = getline(a:lnum) - let prevline = getline(a:lnum-1) + let line = s:getline(a:lnum) + let prevline = s:getline(a:lnum-1) " Multilinestrings: continous, docstring or starting. if s:is_python_string(a:lnum-1, max([1, len(prevline)])) diff --git a/spec/indent/indent_spec.rb b/spec/indent/indent_spec.rb index 55e2fba..96c740d 100644 --- a/spec/indent/indent_spec.rb +++ b/spec/indent/indent_spec.rb @@ -436,15 +436,25 @@ end describe "when jedi-vim call signatures are used" do - before { vim.command 'syn match jediFunction "JEDI_CALL_SIGNATURE" keepend extend' } + before { + # jedi-vim uses a buffer variable that holds the original line contents + # for concealed lines. + vim.command 'let b:_jedi_callsig_orig = {3: "if True:", 4: "def f("}' + } + after { + vim.command 'unlet b:_jedi_callsig_orig' + } it "ignores the call signature after a colon" do + # Assert that we are in line 3. + vim.echo("getcurpos()[1]").to_i.should == 3 vim.feedkeys 'iif True: JEDI_CALL_SIGNATURE\' indent.should == shiftwidth end it "ignores the call signature after a function" do - vim.feedkeys 'idef f( JEDI_CALL_SIGNATURE\' + vim.echo("getcurpos()[1]").to_i.should == 3 + vim.feedkeys 'odef f( JEDI_CALL_SIGNATURE\' indent.should == shiftwidth end end