Vim: How to indent to an open paren or bracket whe

2019-02-06 11:54发布

问题:

I've been programming Python with Vim for a while but one thing I haven't been able to figure out how to do it set it to auto indent to the level of the last open paren.

According to pep8 if you have an open paren and you need to break the line to fit in 80 columns then you're supposed to continue the next line at that open paren. Example:

calling_some_really_long_function(that, has, way, too, many, arguments, to, fit,
                                  on, one, line)

Obviously this is a crazy example, but that's how you're supposed to break your lines in python.

What I'd really like to be able to do is set up Vim so that when I type fit,<cr> and it will place my cursor on the next line just to the right of the open paren, so I can just type on, etc. instead of some combination of <tab> and <space> keys beforehand.

I don't think I'll ever trust the auto-formatter for python code in Vim but bonus points if that works too.

回答1:

This can be refined a bit, but should work 99% of the time. Add this in your .vimrc:

function! PythonEnterFunc()
  let l:li = getline('.')
  execute "normal! a\<Cr>"
  if l:li =~ '([^)]*$'
    let l:pos = stridx(l:li, '(') + 1
    for i in range(l:pos)
      execute "normal! a\<Space>"
    endfor
  endif
endfunction

au FileType python inoremap <Cr> <Esc>:call PythonEnterFunc()<CR>a


回答2:

Use gq, either over the whole selection with a VISUAL block, or with a movement, like gqq or gqj



回答3:

It has been included in Vim since V7.0 at least:

See the following snippet from usr/share/vim/vim80/indent/python.vim (line 74) https://github.com/vim/vim/blob/master/runtime/indent/python.vim

function GetPythonIndent(lnum)
  ...
  " When inside parenthesis: If at the first line below the parenthesis add
  " two 'shiftwidth', otherwise same as previous line.
  " i = (a
  "       + b
  "       + c)
  call cursor(a:lnum, 1)
  let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
      \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
      \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
      \ . " =~ '\\(Comment\\|Todo\\|String\\)$'")
  if p > 0
    if p == plnum
      " When the start is inside parenthesis, only indent one 'shiftwidth'.
      let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
      \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
      \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
      \ . " =~ '\\(Comment\\|Todo\\|String\\)$'")
      if pp > 0
    return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth())
      endif
      return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2))
    endif
    if plnumstart == p
      return indent(plnum)
    endif
    return plindent
  endif
  ...