Skip to content

Commit 80a33ad

Browse files
committed
Improve fish#Indent()
- Fix: multiline strings should not be modified. - Fix: "end" is always decreased by one. - Fix: "case" and "else" are always decreased by one. - Fix: continued lines are not treated differently. - Fix: "if", "while", etc followed by "begin" should increment next line by two instead of by one. - Fix: "case" should be one more than "switch". - Fix: multiline strings and continued lines are considered in the calculations for the next line.
1 parent 825853f commit 80a33ad

2 files changed

Lines changed: 101 additions & 13 deletions

File tree

autoload/fish.vim

Lines changed: 100 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,109 @@
1+
function! s:IsString(lnum, col)
2+
" Returns "true" if syntax item at the given position is part of fishString.
3+
let l:stack = map(synstack(a:lnum, a:col), 'synIDattr(v:val, "name")')
4+
return len(filter(l:stack, 'v:val ==# "fishString"'))
5+
endfunction
6+
7+
function! s:IsContinuedLine(lnum)
8+
" Returns "true" if the given line is a continued line.
9+
return getline(a:lnum - 1) =~ '\v\\$'
10+
endfunction
11+
12+
function! s:FindPrevLnum(lnum)
13+
" Starting on the given line, search backwards for a line that is not
14+
" empty, not part of a string and not a continued line.
15+
if a:lnum < 1 || a:lnum > line('$')
16+
" First line or wrong value, follow prevnonblank() behaviour and
17+
" return zero.
18+
return 0
19+
endif
20+
let l:lnum = prevnonblank(a:lnum)
21+
while l:lnum > 0 && ( s:IsContinuedLine(l:lnum) || s:IsString(l:lnum, 1) )
22+
let l:lnum = prevnonblank(l:lnum - 1)
23+
endwhile
24+
return l:lnum
25+
endfunction
26+
27+
function! s:IsSwitch(lnum)
28+
" Returns "true" if the given line is part of a switch block.
29+
let l:lnum = a:lnum
30+
let l:line = getline(l:lnum)
31+
let l:in_block = 0
32+
let l:stop_pat = '\v^\s*%(if|else|while|for|begin)>'
33+
let l:block_start_pat = '\v^\s*%(if|while|for|switch|begin)>'
34+
while l:lnum > 0
35+
let l:lnum = prevnonblank(l:lnum - 1)
36+
let l:line = getline(l:lnum)
37+
if l:line =~# '\v^\s*end>'
38+
let l:in_block += 1
39+
elseif l:in_block && l:line =~# l:block_start_pat
40+
let l:in_block -= 1
41+
elseif !l:in_block && l:line =~# l:stop_pat
42+
return 0
43+
elseif !l:in_block && l:line =~# '\v^\s*switch>'
44+
return 1
45+
endif
46+
endwhile
47+
return 0
48+
endfunction
49+
150
function! fish#Indent()
2-
let l:prevlnum = prevnonblank(v:lnum - 1)
3-
if l:prevlnum ==# 0
51+
let l:line = getline(v:lnum)
52+
if s:IsString(v:lnum, 1)
53+
return indent(v:lnum)
54+
endif
55+
" shiftwidth can be misleading in recent versions, use shiftwidth() if
56+
" it is available.
57+
if exists('*shiftwidth')
58+
let l:shiftwidth = shiftwidth()
59+
else
60+
let l:shiftwidth = &shiftwidth
61+
endif
62+
let l:prevlnum = s:FindPrevLnum(v:lnum - 1)
63+
if l:prevlnum == 0
464
return 0
565
endif
6-
let l:indent = 0
66+
let l:shift = 0
767
let l:prevline = getline(l:prevlnum)
8-
if l:prevline =~# '\v^\s*switch>'
9-
let l:indent = &shiftwidth * 2
10-
elseif l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|case)>'
11-
let l:indent = &shiftwidth
68+
let l:previndent = indent(l:prevlnum)
69+
if s:IsContinuedLine(v:lnum)
70+
" It is customary to increment indentation of continued lines by three
71+
" or a custom value defined by the user if available.
72+
let l:previndent = indent(v:lnum - 1)
73+
if s:IsContinuedLine(v:lnum - 1)
74+
return l:previndent
75+
elseif exists('g:fish_indent_cont')
76+
return l:previndent + g:fish_indent_cont
77+
elseif exists('g:indent_cont')
78+
return l:previndent + g:indent_cont
79+
else
80+
return l:previndent + 3
81+
endif
1282
endif
13-
let l:line = getline(v:lnum)
14-
if l:line =~# '\v^\s*end>'
15-
return indent(v:lnum) - (l:indent ==# 0 ? &shiftwidth : l:indent)
16-
elseif l:line =~# '\v^\s*%(case|else)>'
17-
return indent(v:lnum) - &shiftwidth
83+
if l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|case|switch)>'
84+
" First line inside a block, increase by one.
85+
let l:shift += 1
86+
endif
87+
if l:line =~# '\v^\s*%(end|case|else)>'
88+
" "end", "case" or "else", decrease by one.
89+
let l:shift -= 1
90+
endif
91+
if l:line =~# '\v^\s*<case>' && l:prevline =~# '\v<switch>'
92+
" "case" following "switch", increase by one.
93+
let l:shift += 1
94+
endif
95+
if l:line =~# '\v\s*end>' && s:IsSwitch(v:lnum)
96+
" "end" ends switch block, decrease by one more so it matches
97+
" the indentation of "switch".
98+
let l:shift -= 1
99+
endif
100+
if l:prevline =~# '\v^\s*%(if|while|for|else|switch|end)>.*<begin>'
101+
" "begin" after start of block, increase by one.
102+
let l:shift += 1
18103
endif
19-
return indent(l:prevlnum) + l:indent
104+
let l:indent = l:previndent + l:shift * l:shiftwidth
105+
" Only return zero or positive numbers.
106+
return l:indent < 0 ? 0 : l:indent
20107
endfunction
21108

22109
function! fish#Format()

indent/fish.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
setlocal indentexpr=fish#Indent()
2+
setlocal indentkeys=!^F,o,O
23
setlocal indentkeys+==end,=else,=case

0 commit comments

Comments
 (0)