summaryrefslogtreecommitdiffstats
path: root/runtime/indent/go.vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/indent/go.vim')
-rw-r--r--runtime/indent/go.vim78
1 files changed, 78 insertions, 0 deletions
diff --git a/runtime/indent/go.vim b/runtime/indent/go.vim
new file mode 100644
index 0000000000..412ac871c4
--- /dev/null
+++ b/runtime/indent/go.vim
@@ -0,0 +1,78 @@
+" Vim indent file
+" Language: Go
+" Maintainer: David Barnett (https://github.com/google/vim-ft-go)
+" Last Change: 2014 Aug 16
+"
+" 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 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
+
+" The shiftwidth() function is relatively new.
+" Don't require it to exist.
+if exists('*shiftwidth')
+ function s:sw() abort
+ return shiftwidth()
+ endfunction
+else
+ function s:sw() abort
+ return &shiftwidth
+ endfunction
+endif
+
+function! GoIndent(lnum)
+ let l:prevlnum = prevnonblank(a:lnum-1)
+ if l:prevlnum == 0
+ " top of file
+ return 0
+ endif
+
+ " grab the previous and current line, stripping comments.
+ let l:prevl = substitute(getline(l:prevlnum), '//.*$', '', '')
+ let l:thisl = substitute(getline(a:lnum), '//.*$', '', '')
+ let l:previ = indent(l:prevlnum)
+
+ let l:ind = l:previ
+
+ if l:prevl =~ '[({]\s*$'
+ " previous line opened a block
+ let l:ind += s:sw()
+ endif
+ if l:prevl =~# '^\s*\(case .*\|default\):$'
+ " previous line is part of a switch statement
+ let l:ind += s:sw()
+ endif
+ " TODO: handle if the previous line is a label.
+
+ if l:thisl =~ '^\s*[)}]'
+ " this line closed a block
+ let l:ind -= s:sw()
+ endif
+
+ " Colons are tricky.
+ " We want to outdent if it's part of a switch ("case foo:" or "default:").
+ " We ignore trying to deal with jump labels because (a) they're rare, and
+ " (b) they're hard to disambiguate from a composite literal key.
+ if l:thisl =~# '^\s*\(case .*\|default\):$'
+ let l:ind -= s:sw()
+ endif
+
+ return l:ind
+endfunction
+
+" vim: sw=2 sts=2 et