summaryrefslogtreecommitdiffstats
path: root/indent/rust.vim
diff options
context:
space:
mode:
Diffstat (limited to 'indent/rust.vim')
-rw-r--r--indent/rust.vim66
1 files changed, 63 insertions, 3 deletions
diff --git a/indent/rust.vim b/indent/rust.vim
index 5c43d2e2..ee7f6cf6 100644
--- a/indent/rust.vim
+++ b/indent/rust.vim
@@ -85,8 +85,17 @@ function! s:is_string_comment(lnum, col)
endif
endfunction
-function GetRustIndent(lnum)
+if exists('*shiftwidth')
+ function! s:shiftwidth()
+ return shiftwidth()
+ endfunc
+else
+ function! s:shiftwidth()
+ return &shiftwidth
+ endfunc
+endif
+function GetRustIndent(lnum)
" Starting assumption: cindent (called at the end) will do it right
" normally. We just want to fix up a few cases.
@@ -132,14 +141,65 @@ function GetRustIndent(lnum)
let prevline = s:get_line_trimmed(prevlinenum)
endwhile
+ " A standalone '{', '}', or 'where'
+ let l:standalone_open = line =~# '\V\^\s\*{\s\*\$'
+ let l:standalone_close = line =~# '\V\^\s\*}\s\*\$'
+ let l:standalone_where = line =~# '\V\^\s\*where\s\*\$'
+ if l:standalone_open || l:standalone_close || l:standalone_where
+ " ToDo: we can search for more items than 'fn' and 'if'.
+ let [l:found_line, l:col, l:submatch] =
+ \ searchpos('\<\(fn\)\|\(if\)\>', 'bnWp')
+ if l:found_line !=# 0
+ " Now we count the number of '{' and '}' in between the match
+ " locations and the current line (there is probably a better
+ " way to compute this).
+ let l:i = l:found_line
+ let l:search_line = strpart(getline(l:i), l:col - 1)
+ let l:opens = 0
+ let l:closes = 0
+ while l:i < a:lnum
+ let l:search_line2 = substitute(l:search_line, '\V{', '', 'g')
+ let l:opens += strlen(l:search_line) - strlen(l:search_line2)
+ let l:search_line3 = substitute(l:search_line2, '\V}', '', 'g')
+ let l:closes += strlen(l:search_line2) - strlen(l:search_line3)
+ let l:i += 1
+ let l:search_line = getline(l:i)
+ endwhile
+ if l:standalone_open || l:standalone_where
+ if l:opens ==# l:closes
+ return indent(l:found_line)
+ endif
+ else
+ " Expect to find just one more close than an open
+ if l:opens ==# l:closes + 1
+ return indent(l:found_line)
+ endif
+ endif
+ endif
+ endif
+
+ " A standalone 'where' adds a shift.
+ let l:standalone_prevline_where = prevline =~# '\V\^\s\*where\s\*\$'
+ if l:standalone_prevline_where
+ return indent(prevlinenum) + 4
+ endif
+
" Handle where clauses nicely: subsequent values should line up nicely.
if prevline[len(prevline) - 1] ==# ","
\ && prevline =~# '^\s*where\s'
return indent(prevlinenum) + 6
endif
- if prevline[len(prevline) - 1] ==# ","
- \ && s:get_line_trimmed(a:lnum) !~# '^\s*[\[\]{}]'
+ let l:last_prevline_character = prevline[len(prevline) - 1]
+
+ " A line that ends with '.<expr>;' is probably an end of a long list
+ " of method operations.
+ if prevline =~# '\V\^\s\*.' && l:last_prevline_character ==# ';'
+ return indent(prevlinenum) - s:shiftwidth()
+ endif
+
+ if l:last_prevline_character ==# ","
+ \ && s:get_line_trimmed(a:lnum) !~# '^\s*[\[\]{})]'
\ && prevline !~# '^\s*fn\s'
\ && prevline !~# '([^()]\+,$'
\ && s:get_line_trimmed(a:lnum) !~# '^\s*\S\+\s*=>'