diff options
author | Adam Stankiewicz <sheerun@sher.pl> | 2020-12-30 12:16:03 +0100 |
---|---|---|
committer | Adam Stankiewicz <sheerun@sher.pl> | 2020-12-30 12:16:03 +0100 |
commit | 0626cc90a21dbd93806e431a4cff640d2d13c765 (patch) | |
tree | 0d34c8341fd4448131b77a36fc3ee64c998c40ee /autoload/fish.vim | |
parent | 8af4f8e6c04b163d39de4327fca7f69cce78c0ab (diff) | |
download | vim-polyglot-4.17.0.tar.gz vim-polyglot-4.17.0.zip |
Change fish provider, closes #626v4.17.0
Diffstat (limited to 'autoload/fish.vim')
-rw-r--r-- | autoload/fish.vim | 128 |
1 files changed, 99 insertions, 29 deletions
diff --git a/autoload/fish.vim b/autoload/fish.vim index 0ea2e474..92d9f642 100644 --- a/autoload/fish.vim +++ b/autoload/fish.vim @@ -2,44 +2,112 @@ if has_key(g:polyglot_is_disabled, 'fish') finish endif +function! s:IsString(lnum, col) + " Returns "true" if syntax item at the given position is part of fishString. + let l:stack = map(synstack(a:lnum, a:col), 'synIDattr(v:val, "name")') + return len(filter(l:stack, 'v:val ==# "fishString"')) +endfunction + +function! s:IsContinuedLine(lnum) + " Returns "true" if the given line is a continued line. + return getline(a:lnum - 1) =~ '\v\\$' +endfunction + +function! s:FindPrevLnum(lnum) + " Starting on the given line, search backwards for a line that is not + " empty, not part of a string and not a continued line. + if a:lnum < 1 || a:lnum > line('$') + " First line or wrong value, follow prevnonblank() behaviour and + " return zero. + return 0 + endif + let l:lnum = prevnonblank(a:lnum) + while l:lnum > 0 && ( s:IsContinuedLine(l:lnum) || s:IsString(l:lnum, 1) ) + let l:lnum = prevnonblank(l:lnum - 1) + endwhile + return l:lnum +endfunction + +function! s:IsSwitch(lnum) + " Returns "true" if the given line is part of a switch block. + let l:lnum = a:lnum + let l:line = getline(l:lnum) + let l:in_block = 0 + let l:stop_pat = '\v^\s*%(if|else|while|for|begin)>' + let l:block_start_pat = '\v^\s*%(if|while|for|switch|begin)>' + while l:lnum > 0 + let l:lnum = prevnonblank(l:lnum - 1) + let l:line = getline(l:lnum) + if l:line =~# '\v^\s*end>' + let l:in_block += 1 + elseif l:in_block && l:line =~# l:block_start_pat + let l:in_block -= 1 + elseif !l:in_block && l:line =~# l:stop_pat + return 0 + elseif !l:in_block && l:line =~# '\v^\s*switch>' + return 1 + endif + endwhile + return 0 +endfunction + function! fish#Indent() - let l:prevlnum = prevnonblank(v:lnum - 1) - if l:prevlnum ==# 0 + let l:line = getline(v:lnum) + if s:IsString(v:lnum, 1) + return indent(v:lnum) + endif + " shiftwidth can be misleading in recent versions, use shiftwidth() if + " it is available. + if exists('*shiftwidth') + let l:shiftwidth = shiftwidth() + else + let l:shiftwidth = &shiftwidth + endif + let l:prevlnum = s:FindPrevLnum(v:lnum - 1) + if l:prevlnum == 0 return 0 endif + let l:shift = 0 let l:prevline = getline(l:prevlnum) - let l:line = getline(v:lnum) - let l:shiftwidth = shiftwidth() let l:previndent = indent(l:prevlnum) - let l:indent = l:previndent - if l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|switch|case)>' - let l:indent += l:shiftwidth - endif - if l:line =~# '\v^\s*end>' - let l:indent -= l:shiftwidth - " If we're inside a case, dedent twice because it ends the switch. - if l:prevline =~# '\v^\s*case>' - " Previous line starts the case. - let l:indent -= l:shiftwidth + if s:IsContinuedLine(v:lnum) + " It is customary to increment indentation of continued lines by three + " or a custom value defined by the user if available. + let l:previndent = indent(v:lnum - 1) + if s:IsContinuedLine(v:lnum - 1) + return l:previndent + elseif exists('g:fish_indent_cont') + return l:previndent + g:fish_indent_cont + elseif exists('g:indent_cont') + return l:previndent + g:indent_cont else - " Scan back to a dedented line to find whether we're in a case. - let l:i = l:prevlnum - while l:i >= 1 && indent(l:i) >= l:previndent - let l:i = prevnonblank(l:i - 1) - endwhile - if indent(l:i) < l:previndent && getline(l:i) =~# '\v^\s*case>' - let l:indent -= l:shiftwidth - endif + return l:previndent + 3 endif - elseif l:line =~# '\v^\s*else>' - let l:indent -= l:shiftwidth - elseif l:prevline !~# '\v^\s*switch>' && l:line =~# '\v^\s*case>' - let l:indent -= l:shiftwidth endif - if l:indent < 0 - return 0 + if l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|case|switch)>' + " First line inside a block, increase by one. + let l:shift += 1 + endif + if l:line =~# '\v^\s*%(end|case|else)>' + " "end", "case" or "else", decrease by one. + let l:shift -= 1 + endif + if l:line =~# '\v^\s*<case>' && l:prevline =~# '\v<switch>' + " "case" following "switch", increase by one. + let l:shift += 1 + endif + if l:line =~# '\v\s*end>' && s:IsSwitch(v:lnum) + " "end" ends switch block, decrease by one more so it matches + " the indentation of "switch". + let l:shift -= 1 + endif + if l:prevline =~# '\v^\s*%(if|while|for|else|switch|end)>.*<begin>' + " "begin" after start of block, increase by one. + let l:shift += 1 endif - return l:indent + let l:indent = l:previndent + l:shift * l:shiftwidth + " Only return zero or positive numbers. + return l:indent < 0 ? 0 : l:indent endfunction function! fish#Format() @@ -49,6 +117,8 @@ function! fish#Format() let l:command = v:lnum.','.(v:lnum+v:count-1).'!fish_indent' echo l:command execute l:command + " Fix indentation and replace tabs with spaces if necessary. + normal! '[='] endif endfunction |