diff options
Diffstat (limited to 'indent')
-rw-r--r-- | indent/blade.vim | 94 | ||||
-rw-r--r-- | indent/eelixir.vim | 5 | ||||
-rw-r--r-- | indent/elixir.vim | 53 | ||||
-rw-r--r-- | indent/swift.vim | 30 | ||||
-rw-r--r-- | indent/typescript.vim | 524 |
5 files changed, 548 insertions, 158 deletions
diff --git a/indent/blade.vim b/indent/blade.vim index 8327f451..78a8a78c 100644 --- a/indent/blade.vim +++ b/indent/blade.vim @@ -1,66 +1,50 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'blade') == -1 -" Language: Blade -" Author: Barry Deeney <sitemaster16@gmail.com> -" Version: 0.1 -" Description: BLADE indent file based on HTML indentation... +" Vim indent file +" Language: Blade (Laravel) +" Maintainer: Jason Walton <jwalton512@gmail.com> -" Check if this file has already been loaded if exists("b:did_indent") - finish + finish endif - -" Include HTML runtime! indent/html.vim -runtime! indent/php.vim -silent! unlet b:did_indent - -" What function do we need to use to detect indentation? -setlocal indentexpr=BladeIndent() - -" What keys would trigger indentation? -setlocal indentkeys=o,O,<Return>,<>>,{,},!^F,0{,0},0),:,!^F,o,O,e,*<Return>,=?>,=<?,=*/ - -" THE MAIN INDENT FUNCTION. Return the amount of indent for v:lnum. -func! BladeIndent() - " What is the current line? - let current_line = v:lnum - - " What is the current text? - let current_text = tolower(getline(current_line)) - - " What was the last non blank line? - let previous_line = prevnonblank(current_line) - - " What was the last non blank text? - let previous_text = tolower(getline(previous_line)) - - " How large are indents?? - let indent_size = &sw - - " Check if we have a PHPIndent value... - let indent = GetPhpIndent() - - " check if we have indent - if indent == -1 - " Check if we have BLADE - if current_text =~ '^\s*@' || previous_text =~ '^\s*@' - " We need to add to the indent - return indent_size * indent(previous_text) - endif +unlet! b:did_indent +let b:did_indent = 1 - " Check if we have HTML - if current_text =~ '^\s*<' || previous_text =~ '^\s*<' - " We now give the honors to HtmlIndent() - let indent = HtmlIndent() - endif - endif +setlocal autoindent +setlocal indentexpr=GetBladeIndent() +setlocal indentkeys=o,O,*<Return>,<>>,!^F,=@else,=@end,=@empty - " Give the indent back! - return indent -endfunc +" Only define the function once. +if exists("*GetBladeIndent") + finish +endif -" Make sure we store that flag! -let b:did_indent = 1 +function! GetBladeIndent() + let lnum = prevnonblank(v:lnum-1) + if lnum == 0 + return 0 + endif + + let line = substitute(substitute(getline(lnum), '\s\+$', '', ''), '^\s\+', '', '') + let cline = substitute(substitute(getline(v:lnum), '\s\+$', '', ''), '^\s\+', '', '') + let indent = indent(lnum) + let cindent = indent(v:lnum) + if cline =~# '@\%(else\|elseif\|empty\|end\)' + let indent = cindent < indent ? cindent : indent - &sw + elseif HtmlIndent() > -1 + let indent = HtmlIndent() + endif + let increase = indent + &sw + if indent = indent(lnum) + let indent = cindent <= indent ? -1 : increase + endif + + if line =~# '@\%(if\|elseif\|else\|unless\|foreach\|forelse\|for\|while\)\%(.*\s*@end\)\@!' + return increase + else + return indent + endif +endfunction endif diff --git a/indent/eelixir.vim b/indent/eelixir.vim index c5e2491e..d9538425 100644 --- a/indent/eelixir.vim +++ b/indent/eelixir.vim @@ -1,10 +1,5 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'elixir') == -1 -" Vim indent file -" Language: Embedded Elixir -" URL: https://github.com/elixir-lang/vim-elixir - - if exists("b:did_indent") finish endif diff --git a/indent/elixir.vim b/indent/elixir.vim index 863104d3..58179973 100644 --- a/indent/elixir.vim +++ b/indent/elixir.vim @@ -1,10 +1,5 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'elixir') == -1 -" Vim indent file -" Language: Elixir -" Maintainer: Carlos Galdino <carloshsgaldino@gmail.com> -" Last Change: 2013 Apr 24 - if exists("b:did_indent") finish endif @@ -13,7 +8,7 @@ let b:did_indent = 1 setlocal nosmartindent setlocal indentexpr=GetElixirIndent() -setlocal indentkeys+=0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue +setlocal indentkeys+=0),0],0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue if exists("*GetElixirIndent") finish @@ -22,17 +17,23 @@ endif let s:cpo_save = &cpo set cpo&vim -let s:skip_syntax = '\%(Comment\|String\)$' -let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . s:skip_syntax . "'" -let s:block_start = 'do\|fn' -let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue' -let s:block_end = 'end' -let s:symbols_end = '\]\|}' -let s:arrow = '^.*->$' -let s:pipeline = '^\s*|>.*$' +let s:no_colon_before = ':\@<!' +let s:no_colon_after = ':\@!' +let s:symbols_end = '\]\|}' +let s:arrow = '^.*->$' +let s:pipeline = '^\s*|>.*$' +let s:skip_syntax = '\%(Comment\|String\)$' +let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '".s:skip_syntax."'" +let s:block_start = 'do\|fn' +let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue' +let s:block_end = 'end' + +let s:indent_keywords = '\<'.s:no_colon_before.'\%('.s:block_start.'\|'.s:block_middle.'\)$'.'\|'.s:arrow +let s:deindent_keywords = '^\s*\<\%('.s:block_end.'\|'.s:block_middle.'\)\>'.'\|'.s:arrow -let s:indent_keywords = '\<\%(' . s:block_start . '\|' . s:block_middle . '\)$' . '\|' . s:arrow -let s:deindent_keywords = '^\s*\<\%(' . s:block_end . '\|' . s:block_middle . '\)\>' . '\|' . s:arrow +let s:pair_start = '\<\%('.s:no_colon_before.s:block_start.'\)\>'.s:no_colon_after +let s:pair_middle = '\<\%('.s:block_middle.'\)\>'.s:no_colon_after.'\zs' +let s:pair_end = '\<\%('.s:no_colon_before.s:block_end.'\)\>\zs' function! GetElixirIndent() let lnum = prevnonblank(v:lnum - 1) @@ -60,20 +61,16 @@ function! GetElixirIndent() let opened_symbol += count(splited_line, '[') - count(splited_line, ']') let opened_symbol += count(splited_line, '{') - count(splited_line, '}') - let ind += opened_symbol * &sw + let ind += (opened_symbol * &sw) - if last_line =~ '^\s*\(' . s:symbols_end . '\)' + if last_line =~ '^\s*\('.s:symbols_end.'\)' || last_line =~ s:indent_keywords let ind += &sw endif - if current_line =~ '^\s*\(' . s:symbols_end . '\)' + if current_line =~ '^\s*\('.s:symbols_end.'\)' let ind -= &sw endif - if last_line =~ s:indent_keywords - let ind += &sw - endif - " if line starts with pipeline " and last line contains pipeline(s) " align them @@ -99,11 +96,13 @@ function! GetElixirIndent() endif if current_line =~ s:deindent_keywords - let bslnum = searchpair( '\<\%(' . s:block_start . '\):\@!\>', - \ '\<\%(' . s:block_middle . '\):\@!\>\zs', - \ '\<:\@<!' . s:block_end . '\>\zs', + let bslnum = searchpair( + \ s:pair_start, + \ s:pair_middle, + \ s:pair_end, \ 'nbW', - \ s:block_skip ) + \ s:block_skip + \ ) let ind = indent(bslnum) endif diff --git a/indent/swift.vim b/indent/swift.vim index ba6d65ea..773e6451 100644 --- a/indent/swift.vim +++ b/indent/swift.vim @@ -14,7 +14,6 @@ let s:cpo_save = &cpo set cpo&vim setlocal nosmartindent -setlocal indentkeys-=: setlocal indentkeys-=e setlocal indentkeys+=0] setlocal indentexpr=SwiftIndent() @@ -95,11 +94,13 @@ function! SwiftIndent(...) return -1 endif - return indent(openingSquare) - endif + " - Line starts with closing square, indent as opening square + if line =~ '\v^\s*]' + return indent(openingSquare) + endif - if s:IsExcludedFromIndent() - return previousIndent + " - Line contains closing square and more, indent a level above opening + return indent(openingSquare) + shiftwidth() endif if line =~ ":$" @@ -153,7 +154,8 @@ function! SwiftIndent(...) endif return indent(openingBracket) else - return -1 + " - Current line is blank, and the user presses 'o' + return previousIndent endif endif @@ -195,7 +197,7 @@ function! SwiftIndent(...) endif let previousParen = match(previous, "(") - return previousParen + 1 + return indent(previousParen) + shiftwidth() endif if numOpenBrackets > numCloseBrackets @@ -207,6 +209,11 @@ function! SwiftIndent(...) return indent(openingParen) + shiftwidth() endif + " - Previous line has close then open braces, indent previous + 1 'sw' + if previous =~ "}.*{" + return previousIndent + shiftwidth() + endif + let line = line(".") let column = col(".") call cursor(previousNum, column) @@ -216,9 +223,14 @@ function! SwiftIndent(...) return indent(openingParen) endif + " - Line above has (unmatched) open paren, next line needs indent if numOpenParens > 0 - let previousParen = match(previous, "(") - return previousParen + 1 + let savePosition = getcurpos() + " Must be at EOL because open paren has to be above (left of) the cursor + call cursor(previousNum, col("$")) + let previousParen = searchpair("(", "", ")", "bWn", "s:IsExcludedFromIndent()") + call setpos(".", savePosition) + return indent(previousParen) + shiftwidth() endif return cindent diff --git a/indent/typescript.vim b/indent/typescript.vim index 58dc7d03..ec4781a8 100644 --- a/indent/typescript.vim +++ b/indent/typescript.vim @@ -1,105 +1,505 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'typescript') == -1 -" Vim indent file, taken from indent/java.vim -" Language: Typescript -" Maintainer: None! Wanna improve this? -" Last Change: 2015 Mar 07 +" Vim indent file +" Language: Typescript +" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org -if get(g:, 'typescript_indent_disable') - finish -endif +" 0. Initialization {{{1 +" ================= " Only load this indent file when no other was loaded. if exists("b:did_indent") - finish + finish endif let b:did_indent = 1 -" Use javascript cindent options -setlocal cindent cinoptions& cinoptions+=j1,J1 -setlocal indentkeys& +setlocal nosmartindent -" Load typescript indent function +" Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetTypescriptIndent() +setlocal formatexpr=Fixedgq(v:lnum,v:count) +setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e -let b:undo_indent = "setl cin< cino< indentkeys< indentexpr<" - -" Only define the function once +" Only define the function once. if exists("*GetTypescriptIndent") - finish + finish endif -" Make sure we have vim capabilities -let s:keepcpo = &cpo +let s:cpo_save = &cpo set cpo&vim -function! TypescriptPrevNonBlankOrComment(lnum) - let pnum = prevnonblank(a:lnum) - " skip any comments (either `//`, `/*` or `*`) - while getline(pnum) =~ '^\s*\(\/\/\|\/\*\|\*\)' - let pnum = prevnonblank(pnum-1) - endwhile - return pnum +" 1. Variables {{{1 +" ============ + +let s:ts_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' + +" Regex of syntax group names that are or delimit string or are comments. +let s:syng_strcom = 'string\|regex\|comment\c' + +" Regex of syntax group names that are strings. +let s:syng_string = 'regex\c' + +" Regex of syntax group names that are strings or documentation. +let s:syng_multiline = 'comment\c' + +" Regex of syntax group names that are line comment. +let s:syng_linecom = 'linecomment\c' + +" Expression used to check whether we should skip a match with searchpair(). +let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" + +let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' + +" Regex that defines continuation lines, not including (, {, or [. +let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\|[^=]=[^=].*,\)' . s:line_term + +" Regex that defines continuation lines. +" TODO: this needs to deal with if ...: and so on +let s:msl_regex = s:continuation_regex + +let s:one_line_scope_regex = '\<\%(if\|else\|for\|while\)\>[^{;]*' . s:line_term + +" Regex that defines blocks. +let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +let s:var_stmt = '^\s*var' + +let s:comma_first = '^\s*,' +let s:comma_last = ',\s*$' + +let s:ternary = '^\s\+[?|:]' +let s:ternary_q = '^\s\+?' + +" 2. Auxiliary Functions {{{1 +" ====================== + +" Check if the character at lnum:col is inside a string, comment, or is ascii. +function s:IsInStringOrComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom endfunction -function GetTypescriptIndent() +" Check if the character at lnum:col is inside a string. +function s:IsInString(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string +endfunction + +" Check if the character at lnum:col is inside a multi-line comment. +function s:IsInMultilineComment(lnum, col) + return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline +endfunction + +" Check if the character at lnum:col is a line comment. +function s:IsLineComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom +endfunction - " default value: trust cindent - let ind = cindent(v:lnum) +" Find line above 'lnum' that isn't empty, in a comment, or in a string. +function s:PrevNonBlankNonString(lnum) + let in_block = 0 + let lnum = prevnonblank(a:lnum) + while lnum > 0 + " Go in and out of blocks comments as necessary. + " If the line isn't empty (with opt. comment) or in a string, end search. + let line = getline(lnum) + if line =~ '/\*' + if in_block + let in_block = 0 + else + break + endif + elseif !in_block && line =~ '\*/' + let in_block = 1 + elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line))) + break + endif + let lnum = prevnonblank(lnum - 1) + endwhile + return lnum +endfunction - if getline(v:lnum) =~ '^\s*[{}\*]' - return ind +" Find line above 'lnum' that started the continuation 'lnum' may be part of. +function s:GetMSL(lnum, in_one_line_scope) + " Start on the line we're at and use its indent. + let msl = a:lnum + let lnum = s:PrevNonBlankNonString(a:lnum - 1) + while lnum > 0 + " If we have a continuation line, or we're in a string, use line as MSL. + " Otherwise, terminate search as we have found our MSL already. + let line = getline(lnum) + let col = match(line, s:msl_regex) + 1 + if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line)) + let msl = lnum + else + " Don't use lines that are part of a one line scope as msl unless the + " flag in_one_line_scope is set to 1 + " + if a:in_one_line_scope + break + end + let msl_one_line = s:Match(lnum, s:one_line_scope_regex) + if msl_one_line == 0 + break + endif endif + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + return msl +endfunction + +function s:RemoveTrailingComments(content) + let single = '\/\/\(.*\)\s*$' + let multi = '\/\*\(.*\)\*\/\s*$' + return substitute(substitute(a:content, single, '', ''), multi, '', '') +endfunction + +" Find if the string is inside var statement (but not the first string) +function s:InMultiVarStatement(lnum) + let lnum = s:PrevNonBlankNonString(a:lnum - 1) - " The last non-empty line - let prev = TypescriptPrevNonBlankOrComment(v:lnum-1) +" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name') - " Check if the previous line consists of a single `<variable> : <type>;` - " declaration (e.g. in interface definitions) - if getline(prev) =~ '^\s*\w\+\s*:[^{]\+;\s*$' - return indent(prev) + " loop through previous expressions to find a var statement + while lnum > 0 + let line = getline(lnum) + + " if the line is a ts keyword + if (line =~ s:ts_keywords) + " check if the line is a var stmt + " if the line has a comma first or comma last then we can assume that we + " are in a multiple var statement + if (line =~ s:var_stmt) + return lnum + endif + + " other ts keywords, not a var + return 0 endif - " If the previous line starts with '@', we should have the same indent as - " the previous one - if getline(prev) =~ '^\s*@\S\+\s*$' - return indent(prev) + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + + " beginning of program, not a var + return 0 +endfunction + +" Find line above with beginning of the var statement or returns 0 if it's not +" this statement +function s:GetVarIndent(lnum) + let lvar = s:InMultiVarStatement(a:lnum) + let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1) + + if lvar + let line = s:RemoveTrailingComments(getline(prev_lnum)) + + " if the previous line doesn't end in a comma, return to regular indent + if (line !~ s:comma_last) + return indent(prev_lnum) - &sw + else + return indent(lvar) + &sw endif + endif - " If a var, let, or const was declared and the semicolon omitted, do not - " indent the next line - if getline(prev) =~ '^\s*\(var\|let\|const\)\s\+\w\+' - return indent(prev) + return -1 +endfunction + + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:LineHasOpeningBrackets(lnum) + let open_0 = 0 + let open_2 = 0 + let open_4 = 0 + let line = getline(a:lnum) + let pos = match(line, '[][(){}]', 0) + while pos != -1 + if !s:IsInStringOrComment(a:lnum, pos + 1) + let idx = stridx('(){}[]', line[pos]) + if idx % 2 == 0 + let open_{idx} = open_{idx} + 1 + else + let open_{idx - 1} = open_{idx - 1} - 1 + endif endif + let pos = match(line, '[][(){}]', pos + 1) + endwhile + return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) +endfunction + +function s:Match(lnum, regex) + let col = match(getline(a:lnum), a:regex) + 1 + return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 +endfunction + +function s:IndentWithContinuation(lnum, ind, width) + " Set up variables to use and search for MSL to the previous line. + let p_lnum = a:lnum + let lnum = s:GetMSL(a:lnum, 1) + let line = getline(lnum) - " If the line ended with a ',', we should have the same indent as - " the previous one - if getline(prev) =~ ',\s*$' - return indent(prev) + " If the previous line wasn't a MSL and is continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + if p_lnum != lnum + if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line)) + return a:ind endif + endif - " Try to find out whether the last `}` ended a `<variable> : {` block - if getline(prev) =~ '};\s*$' - " jump to matching `{` bracket - call cursor(prev, 1) - silent normal % + " Set up more variables now that we know we aren't continuation bound. + let msl_ind = indent(lnum) + + " If the previous line ended with [*+/.-=], start a continuation that + " indents an extra level. + if s:Match(lnum, s:continuation_regex) + if lnum == p_lnum + return msl_ind + a:width + else + return msl_ind + endif + endif + + return a:ind +endfunction + +function s:InOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 && s:Match(msl, s:one_line_scope_regex) + return msl + endif + return 0 +endfunction - " See if current line is type annotation without closing ';' but open - " `{` bracket - let lnum = line('.') - if getline(lnum) =~ '^\s*\w\+\s*:[^;]\+{' - let ind = indent(lnum) +function s:ExitingOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 + " if the current line is in a one line scope .. + if s:Match(msl, s:one_line_scope_regex) + return 0 + else + let prev_msl = s:GetMSL(msl - 1, 1) + if s:Match(prev_msl, s:one_line_scope_regex) + return prev_msl + endif + endif + endif + return 0 +endfunction + +" 3. GetTypescriptIndent Function {{{1 +" ========================= + +function GetTypescriptIndent() + " 3.1. Setup {{{2 + " ---------- + + " Set up variables for restoring position in file. Could use v:lnum here. + let vcol = col('.') + + " 3.2. Work on the current line {{{2 + " ----------------------------- + + let ind = -1 + " Get the current line. + let line = getline(v:lnum) + " previous nonblank line number + let prevline = prevnonblank(v:lnum - 1) + + " If we got a closing bracket on an empty line, find its match and indent + " according to it. For parentheses we indent to its column - 1, for the + " others we indent to the containing line's MSL's level. Return -1 if fail. + let col = matchend(line, '^\s*[],})]') + if col > 0 && !s:IsInStringOrComment(v:lnum, col) + call cursor(v:lnum, col) + + let lvar = s:InMultiVarStatement(v:lnum) + if lvar + let prevline_contents = s:RemoveTrailingComments(getline(prevline)) + + " check for comma first + if (line[col - 1] =~ ',') + " if the previous line ends in comma or semicolon don't indent + if (prevline_contents =~ '[;,]\s*$') + return indent(s:GetMSL(line('.'), 0)) + " get previous line indent, if it's comma first return prevline indent + elseif (prevline_contents =~ s:comma_first) + return indent(prevline) + " otherwise we indent 1 level + else + return indent(lvar) + &sw endif + endif endif + + let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) + if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 + if line[col-1]==')' && col('.') != col('$') - 1 + let ind = virtcol('.')-1 + else + let ind = indent(s:GetMSL(line('.'), 0)) + endif + endif return ind + endif + + " If the line is comma first, dedent 1 level + if (getline(prevline) =~ s:comma_first) + return indent(prevline) - &sw + endif + + if (line =~ s:ternary) + if (getline(prevline) =~ s:ternary_q) + return indent(prevline) + else + return indent(prevline) + &sw + endif + endif + + " If we are in a multi-line comment, cindent does the right thing. + if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1) + return cindent(v:lnum) + endif + + " Check for multiple var assignments +" let var_indent = s:GetVarIndent(v:lnum) +" if var_indent >= 0 +" return var_indent +" endif + + " 3.3. Work on the previous line. {{{2 + " ------------------------------- + + " If the line is empty and the previous nonblank line was a multi-line + " comment, use that comment's indent. Deduct one char to account for the + " space in ' */'. + if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1) + return indent(prevline) - 1 + endif + + " Find a non-blank, non-multi-line string line above the current line. + let lnum = s:PrevNonBlankNonString(v:lnum - 1) + + " If the line is empty and inside a string, use the previous line. + if line =~ '^\s*$' && lnum != prevline + return indent(prevnonblank(v:lnum)) + endif + + " At the start of the file use zero indent. + if lnum == 0 + return 0 + endif + + " Set up variables for current line. + let line = getline(lnum) + let ind = indent(lnum) + + " If the previous line ended with a block opening, add a level of indent. + if s:Match(lnum, s:block_regex) + return indent(s:GetMSL(lnum, 0)) + &sw + endif + + " If the previous line contained an opening bracket, and we are still in it, + " add indent depending on the bracket type. + if line =~ '[[({]' + let counts = s:LineHasOpeningBrackets(lnum) + if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + if col('.') + 1 == col('$') + return ind + &sw + else + return virtcol('.') + endif + elseif counts[1] == '1' || counts[2] == '1' + return ind + &sw + else + call cursor(v:lnum, vcol) + end + endif + + " 3.4. Work on the MSL line. {{{2 + " -------------------------- + let ind_con = ind + let ind = s:IndentWithContinuation(lnum, ind_con, &sw) + + " }}}2 + " + " + let ols = s:InOneLineScope(lnum) + if ols > 0 + let ind = ind + &sw + else + let ols = s:ExitingOneLineScope(lnum) + while ols > 0 && ind > 0 + let ind = ind - &sw + let ols = s:InOneLineScope(ols - 1) + endwhile + endif + + return ind endfunction -" Restore compatibility mode -let &cpo = s:keepcpo -unlet s:keepcpo +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save + +function! Fixedgq(lnum, count) + let l:tw = &tw ? &tw : 80; + + let l:count = a:count + let l:first_char = indent(a:lnum) + 1 + + if mode() == 'i' " gq was not pressed, but tw was set + return 1 + endif + + " This gq is only meant to do code with strings, not comments + if s:IsLineComment(a:lnum, l:first_char) || s:IsInMultilineComment(a:lnum, l:first_char) + return 1 + endif + + if len(getline(a:lnum)) < l:tw && l:count == 1 " No need for gq + return 1 + endif + + " Put all the lines on one line and do normal spliting after that + if l:count > 1 + while l:count > 1 + let l:count -= 1 + normal J + endwhile + endif + + let l:winview = winsaveview() + + call cursor(a:lnum, l:tw + 1) + let orig_breakpoint = searchpairpos(' ', '', '\.', 'bcW', '', a:lnum) + call cursor(a:lnum, l:tw + 1) + let breakpoint = searchpairpos(' ', '', '\.', 'bcW', s:skip_expr, a:lnum) + + " No need for special treatment, normal gq handles edgecases better + if breakpoint[1] == orig_breakpoint[1] + call winrestview(l:winview) + return 1 + endif + + " Try breaking after string + if breakpoint[1] <= indent(a:lnum) + call cursor(a:lnum, l:tw + 1) + let breakpoint = searchpairpos('\.', '', ' ', 'cW', s:skip_expr, a:lnum) + endif -" vim: et + + if breakpoint[1] != 0 + call feedkeys("r\<CR>") + else + let l:count = l:count - 1 + endif + + " run gq on new lines + if l:count == 1 + call feedkeys("gqq") + endif + + return 0 +endfunction endif |