]> Cypherpunks repositories - gostls13.git/commitdiff
misc/vim: new Vim indentation script.
authorDavid Symonds <dsymonds@golang.org>
Fri, 13 May 2011 15:29:44 +0000 (08:29 -0700)
committerDavid Symonds <dsymonds@golang.org>
Fri, 13 May 2011 15:29:44 +0000 (08:29 -0700)
This uses a fully custom function for indenting Go code in Vim.
It provides a lot more flexibility than a cindent-based approach,
so this version gets the := operator correct, as well as switch
labels and jump labels.

One outstanding TODO is to handle lines immediately after jump labels.

R=adg, n13m3y3r, jnwhiteh, dchest, rsc, rlight2
CC=golang-dev, rivercheng
https://golang.org/cl/4534047

misc/vim/indent/go.vim

index 2e9f191f5b73a3cdb7e40fd87aa97d498c4f96c1..dbea5a53805e37e07bb09a32862481fca244d85d 100644 (file)
@@ -4,27 +4,68 @@
 "
 " indent/go.vim: Vim indent file for Go.
 "
+" TODO:
+" - function invocations split across lines
+" - general line splits (line ends in an operator)
 
 if exists("b:did_indent")
     finish
 endif
 let b:did_indent = 1
 
-" C indentation is mostly correct
-setlocal cindent
-
-" Options set:
-" +0 -- Don't indent continuation lines (because Go doesn't use semicolons
-"       much)
-" L0 -- Don't move jump labels (NOTE: this isn't correct when working with
-"       gofmt, but it does keep struct literals properly indented.)
-" :0 -- Align case labels with switch statement
-" l1 -- Always align case body relative to case labels
-" J1 -- Indent JSON-style objects (properly indents struct-literals)
-" (0, Ws -- Indent lines inside of unclosed parentheses by one shiftwidth
-" m1 -- Align closing parenthesis line with first non-blank of matching
-"       parenthesis line
-"
-" Known issue: Trying to do a multi-line struct literal in a short variable
-"              declaration will not indent properly.
-setlocal cinoptions+=+0,L0,:0,l1,J1,(0,Ws,m1
+" C indentation is too far off useful, mainly due to Go's := operator.
+" Let's just define our own.
+setlocal nolisp
+setlocal autoindent
+setlocal indentexpr=GoIndent(v:lnum)
+setlocal indentkeys+=<:>,0=},0=)
+
+if exists("*GoIndent")
+  finish
+endif
+
+function! GoIndent(lnum)
+  let prevlnum = prevnonblank(a:lnum-1)
+  if prevlnum == 0
+    " top of file
+    return 0
+  endif
+
+  " grab the previous and current line, stripping comments.
+  let prevl = substitute(getline(prevlnum), '//.*$', '', '')
+  let thisl = substitute(getline(a:lnum), '//.*$', '', '')
+  let previ = indent(prevlnum)
+
+  let ind = previ
+
+  if prevl =~ '[({]\s*$'
+    " previous line opened a block
+    let ind += &sw
+  endif
+  if prevl =~# '^\s*\(case .*\|default\):$'
+    " previous line is part of a switch statement
+    let ind += &sw
+  endif
+  " TODO: handle if the previous line is a label.
+
+  if thisl =~ '^\s*[)}]'
+    " this line closed a block
+    let ind -= &sw
+  endif
+
+  " Colons are tricky.
+  " We want to outdent if it's part of a switch ("case foo:" or "default:"),
+  if thisl =~# '^\s*\(case .*\|default\):$'
+    let ind -= &sw
+  endif
+  " ... and put jump labels in the first column (ignore "default:").
+  if thisl =~ '^\s*\S\+:\s*$' 
+    " ignore "default:" and if there's a string on the line;
+    " the latter will more likely be something like "blah: %v".
+    if thisl !~# '^\s*default:\s*$' && thisl !~# '".*:'
+      return 0
+    endif
+  endif
+
+  return ind
+endfunction