|
| 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 | + |
1 | 50 | 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 |
4 | 64 | return 0 |
5 | 65 | endif |
6 | | - let l:indent = 0 |
| 66 | + let l:shift = 0 |
7 | 67 | 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 |
12 | 82 | 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 |
18 | 103 | 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 |
20 | 107 | endfunction |
21 | 108 |
|
22 | 109 | function! fish#Format() |
|
0 commit comments