Vim: python indenting like C indenting

Computing/vim tips 2012. 2. 12. 18:14

I set cinoptions as "(0,W4" when I have to edit C/C++ source files.

This cinoptions setting adjusts indenting of your sourcecode as follows:

somevalue = function_foo(argument1,  /* you type Enter key here */
                         arg2, /* And the cursor is automatically located right next to below "(" letter */
                         argument3);

Yes, it automtically indents lines inside parentheses to the column where the starting parenthesis is.

Recently, I've been editing lots of python programs. The original python.vim indent file does not provide this feature. It only indents stupid shiftwidth or shiftwidth * 2. So I had to manually align my source codes every time.
Finally, I've come to think I've had enough of it, and I started to modify the default python.vim indenting scheme.

Here goes python.vim that does cinoptions=(0,W4 feature. This scripts has been modified from the original python.vim script, which can be found in the indent directory in your vim installation location.

orchistro.deltabellun:~$ diff -ub  /Applications/MacVim.app/Contents/Resources/vim/runtime/indent/python.vim .vim/indent/python.vim
--- /Applications/MacVim.app/Contents/Resources/vim/runtime/indent/python.vim    2010-08-16 05:04:06.000000000 +0900
+++ .vim/indent/python.vim    2012-02-12 18:01:29.000000000 +0900
@@ -69,34 +69,17 @@
   endif
 
 
-  " When inside parenthesis: If at the first line below the parenthesis add
-  " two 'shiftwidth', otherwise same as previous line.
-  " i = (a
-  "       + b
-  "       + c)
+    " i = (aasdfasf,
+    "      b,
+    "      c)
   call cursor(a:lnum, 1)
-  let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
+    let [l,c] = searchpairpos('(\|{\|\[', '', ')\|}\|\]', 'bW',
       \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
       \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
       \ . " =~ '\\(Comment\\|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\\|String\\)$'")
-      if pp > 0
-    return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : &sw)
-      endif
-      return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (&sw * 2))
+    if l > 0
+        return c
     endif
-    if plnumstart == p
-      return indent(plnum)
-    endif
-    return plindent
-  endif
-
 
   " Get the line and remove a trailing comment.
   " Use syntax highlighting attributes when possible.

Let's compare indending results before applying this script in your .vim/indent/ directory and after applying it.

Original indenting (before):

    avalue = self.some_function(argument1,
            argument2,  # how stupid it is
            argument3)
    blablabla...

Modified indenting (after):

    avalue = self.some_function(argument1,
                                argument2, # it looks good!!
                                argument3)
    blablabla...

For convenience, here is the python.vim file. Put it in your .vim/indent/ directory. If the directory does not exist, create one.

python.vim


----

Edit 1, 2012-04-16
* Fixed some broken English scentences.
* The script works fine most of the time. Sometimes, however, it cannot find correct indenting especially when there's arrays in arguments. I am not going to work on the bug until it starts driving me crazy :$

: