diff options
Diffstat (limited to '')
121 files changed, 17046 insertions, 0 deletions
diff --git a/indent/aap.vim b/indent/aap.vim new file mode 100644 index 00000000..cddf5225 --- /dev/null +++ b/indent/aap.vim @@ -0,0 +1,16 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Aap recipe +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2005 Jun 24 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Works mostly like Python. +runtime! indent/python.vim + +endif diff --git a/indent/ada.vim b/indent/ada.vim new file mode 100644 index 00000000..76d2395a --- /dev/null +++ b/indent/ada.vim @@ -0,0 +1,312 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"------------------------------------------------------------------------------ +"  Description: Vim Ada indent file +"     Language: Ada (2005) +"	   $Id: ada.vim 887 2008-07-08 14:29:01Z krischik $ +"    Copyright: Copyright (C) 2006 Martin Krischik +"   Maintainer: Martin Krischik <krischik@users.sourceforge.net> +"		Neil Bird <neil@fnxweb.com> +"		Ned Okie <nokie@radford.edu> +"      $Author: krischik $ +"	 $Date: 2008-07-08 16:29:01 +0200 (Di, 08 Jul 2008) $ +"      Version: 4.6 +"    $Revision: 887 $ +"     $HeadURL: https://gnuada.svn.sourceforge.net/svnroot/gnuada/trunk/tools/vim/indent/ada.vim $ +"      History: 24.05.2006 MK Unified Headers +"		16.07.2006 MK Ada-Mode as vim-ball +"		15.10.2006 MK Bram's suggestion for runtime integration +"		05.11.2006 MK Bram suggested to save on spaces +"		19.09.2007 NO g: missing before ada#Comment +"    Help Page: ft-vim-indent +"------------------------------------------------------------------------------ +" ToDo: +"  Verify handling of multi-line exprs. and recovery upon the final ';'. +"  Correctly find comments given '"' and "" ==> " syntax. +"  Combine the two large block-indent functions into one? +"------------------------------------------------------------------------------ + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") || version < 700 +   finish +endif + +let b:did_indent = 45 + +setlocal indentexpr=GetAdaIndent() +setlocal indentkeys-=0{,0} +setlocal indentkeys+=0=~then,0=~end,0=~elsif,0=~when,0=~exception,0=~begin,0=~is,0=~record + +" Only define the functions once. +if exists("*GetAdaIndent") +   finish +endif +let s:keepcpo= &cpo +set cpo&vim + +if exists("g:ada_with_gnat_project_files") +   let s:AdaBlockStart = '^\s*\(if\>\|while\>\|else\>\|elsif\>\|loop\>\|for\>.*\<\(loop\|use\)\>\|declare\>\|begin\>\|type\>.*\<is\>[^;]*$\|\(type\>.*\)\=\<record\>\|procedure\>\|function\>\|accept\>\|do\>\|task\>\|package\>\|project\>\|then\>\|when\>\|is\>\)' +else +   let s:AdaBlockStart = '^\s*\(if\>\|while\>\|else\>\|elsif\>\|loop\>\|for\>.*\<\(loop\|use\)\>\|declare\>\|begin\>\|type\>.*\<is\>[^;]*$\|\(type\>.*\)\=\<record\>\|procedure\>\|function\>\|accept\>\|do\>\|task\>\|package\>\|then\>\|when\>\|is\>\)' +endif + +" Section: s:MainBlockIndent {{{1 +" +" Try to find indent of the block we're in +" prev_indent = the previous line's indent +" prev_lnum   = previous line (to start looking on) +" blockstart  = expr. that indicates a possible start of this block +" stop_at     = if non-null, if a matching line is found, gives up! +" No recursive previous block analysis: simply look for a valid line +" with a lesser or equal indent than we currently (on prev_lnum) have. +" This shouldn't work as well as it appears to with lines that are currently +" nowhere near the correct indent (e.g., start of line)! +" Seems to work OK as it 'starts' with the indent of the /previous/ line. +function s:MainBlockIndent (prev_indent, prev_lnum, blockstart, stop_at) +   let lnum = a:prev_lnum +   let line = substitute( getline(lnum), g:ada#Comment, '', '' ) +   while lnum > 1 +      if a:stop_at != ''  &&  line =~ '^\s*' . a:stop_at  &&  indent(lnum) < a:prev_indent +	 return a:prev_indent +      elseif line =~ '^\s*' . a:blockstart +	 let ind = indent(lnum) +	 if ind < a:prev_indent +	    return ind +	 endif +      endif + +      let lnum = prevnonblank(lnum - 1) +      " Get previous non-blank/non-comment-only line +      while 1 +	 let line = substitute( getline(lnum), g:ada#Comment, '', '' ) +	 if line !~ '^\s*$' && line !~ '^\s*#' +	    break +	 endif +	 let lnum = prevnonblank(lnum - 1) +	 if lnum <= 0 +	    return a:prev_indent +	 endif +      endwhile +   endwhile +   " Fallback - just move back one +   return a:prev_indent - shiftwidth() +endfunction MainBlockIndent + +" Section: s:EndBlockIndent {{{1 +" +" Try to find indent of the block we're in (and about to complete), +" including handling of nested blocks. Works on the 'end' of a block. +" prev_indent = the previous line's indent +" prev_lnum   = previous line (to start looking on) +" blockstart  = expr. that indicates a possible start of this block +" blockend    = expr. that indicates a possible end of this block +function s:EndBlockIndent( prev_indent, prev_lnum, blockstart, blockend ) +   let lnum = a:prev_lnum +   let line = getline(lnum) +   let ends = 0 +   while lnum > 1 +      if getline(lnum) =~ '^\s*' . a:blockstart +	 let ind = indent(lnum) +	 if ends <= 0 +	    if ind < a:prev_indent +	       return ind +	    endif +	 else +	    let ends = ends - 1 +	 endif +      elseif getline(lnum) =~ '^\s*' . a:blockend +	 let ends = ends + 1 +      endif + +      let lnum = prevnonblank(lnum - 1) +      " Get previous non-blank/non-comment-only line +      while 1 +	 let line = getline(lnum) +	 let line = substitute( line, g:ada#Comment, '', '' ) +	 if line !~ '^\s*$' +	    break +	 endif +	 let lnum = prevnonblank(lnum - 1) +	 if lnum <= 0 +	    return a:prev_indent +	 endif +      endwhile +   endwhile +   " Fallback - just move back one +   return a:prev_indent - shiftwidth() +endfunction EndBlockIndent + +" Section: s:StatementIndent {{{1 +" +" Return indent of previous statement-start +" (after we've indented due to multi-line statements). +" This time, we start searching on the line *before* the one given (which is +" the end of a statement - we want the previous beginning). +function s:StatementIndent( current_indent, prev_lnum ) +   let lnum  = a:prev_lnum +   while lnum > 0 +      let prev_lnum = lnum +      let lnum = prevnonblank(lnum - 1) +      " Get previous non-blank/non-comment-only line +      while 1 +	 let line = substitute( getline(lnum), g:ada#Comment, '', '' ) + +	 if line !~ '^\s*$' && line !~ '^\s*#' +	    break +	 endif +	 let lnum = prevnonblank(lnum - 1) +	 if lnum <= 0 +	    return a:current_indent +	 endif +      endwhile +      " Leave indent alone if our ';' line is part of a ';'-delineated +      " aggregate (e.g., procedure args.) or first line after a block start. +      if line =~ s:AdaBlockStart || line =~ '(\s*$' +	 return a:current_indent +      endif +      if line !~ '[.=(]\s*$' +	 let ind = indent(prev_lnum) +	 if ind < a:current_indent +	    return ind +	 endif +      endif +   endwhile +   " Fallback - just use current one +   return a:current_indent +endfunction StatementIndent + + +" Section: GetAdaIndent {{{1 +" +" Find correct indent of a new line based upon what went before +" +function GetAdaIndent() +   " Find a non-blank line above the current line. +   let lnum = prevnonblank(v:lnum - 1) +   let ind = indent(lnum) +   let package_line = 0 + +   " Get previous non-blank/non-comment-only/non-cpp line +   while 1 +      let line = substitute( getline(lnum), g:ada#Comment, '', '' ) +      if line !~ '^\s*$' && line !~ '^\s*#' +	 break +      endif +      let lnum = prevnonblank(lnum - 1) +      if lnum <= 0 +	 return ind +      endif +   endwhile + +   " Get default indent (from prev. line) +   let ind = indent(lnum) +   let initind = ind + +   " Now check what's on the previous line +   if line =~ s:AdaBlockStart  ||  line =~ '(\s*$' +      " Check for false matches to AdaBlockStart +      let false_match = 0 +      if line =~ '^\s*\(procedure\|function\|package\)\>.*\<is\s*new\>' +	 " Generic instantiation +	 let false_match = 1 +      elseif line =~ ')\s*;\s*$'  ||  line =~ '^\([^(]*([^)]*)\)*[^(]*;\s*$' +	 " forward declaration +	 let false_match = 1 +      endif +      " Move indent in +      if ! false_match +	 let ind = ind + shiftwidth() +      endif +   elseif line =~ '^\s*\(case\|exception\)\>' +      " Move indent in twice (next 'when' will move back) +      let ind = ind + 2 * shiftwidth() +   elseif line =~ '^\s*end\s*record\>' +      " Move indent back to tallying 'type' preceeding the 'record'. +      " Allow indent to be equal to 'end record's. +      let ind = s:MainBlockIndent( ind+shiftwidth(), lnum, 'type\>', '' ) +   elseif line =~ '\(^\s*new\>.*\)\@<!)\s*[;,]\s*$' +      " Revert to indent of line that started this parenthesis pair +      exe lnum +      exe 'normal! $F)%' +      if getline('.') =~ '^\s*(' +	 " Dire layout - use previous indent (could check for g:ada#Comment here) +	 let ind = indent( prevnonblank( line('.')-1 ) ) +      else +	 let ind = indent('.') +      endif +      exe v:lnum +   elseif line =~ '[.=(]\s*$' +      " A statement continuation - move in one +      let ind = ind + shiftwidth() +   elseif line =~ '^\s*new\>' +      " Multiple line generic instantiation ('package blah is\nnew thingy') +      let ind = s:StatementIndent( ind - shiftwidth(), lnum ) +   elseif line =~ ';\s*$' +      " Statement end (but not 'end' ) - try to find current statement-start indent +      let ind = s:StatementIndent( ind, lnum ) +   endif + +   " Check for potential argument list on next line +   let continuation = (line =~ '[A-Za-z0-9_]\s*$') + + +   " Check current line; search for simplistic matching start-of-block +   let line = getline(v:lnum) +   if line =~ '^\s*#' +      " Start of line for ada-pp +      let ind = 0 +   elseif continuation && line =~ '^\s*(' +      " Don't do this if we've already indented due to the previous line +      if ind == initind +	 let ind = ind + shiftwidth() +      endif +   elseif line =~ '^\s*\(begin\|is\)\>' +      let ind = s:MainBlockIndent( ind, lnum, '\(procedure\|function\|declare\|package\|task\)\>', 'begin\>' ) +   elseif line =~ '^\s*record\>' +      let ind = s:MainBlockIndent( ind, lnum, 'type\>\|for\>.*\<use\>', '' ) + shiftwidth() +   elseif line =~ '^\s*\(else\|elsif\)\>' +      let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' ) +   elseif line =~ '^\s*when\>' +      " Align 'when' one /in/ from matching block start +      let ind = s:MainBlockIndent( ind, lnum, '\(case\|exception\)\>', '' ) + shiftwidth() +   elseif line =~ '^\s*end\>\s*\<if\>' +      " End of if statements +      let ind = s:EndBlockIndent( ind, lnum, 'if\>', 'end\>\s*\<if\>' ) +   elseif line =~ '^\s*end\>\s*\<loop\>' +      " End of loops +      let ind = s:EndBlockIndent( ind, lnum, '\(\(while\|for\)\>.*\)\?\<loop\>', 'end\>\s*\<loop\>' ) +   elseif line =~ '^\s*end\>\s*\<record\>' +      " End of records +      let ind = s:EndBlockIndent( ind, lnum, '\(type\>.*\)\=\<record\>', 'end\>\s*\<record\>' ) +   elseif line =~ '^\s*end\>\s*\<procedure\>' +      " End of procedures +      let ind = s:EndBlockIndent( ind, lnum, 'procedure\>.*\<is\>', 'end\>\s*\<procedure\>' ) +   elseif line =~ '^\s*end\>\s*\<case\>' +      " End of case statement +      let ind = s:EndBlockIndent( ind, lnum, 'case\>.*\<is\>', 'end\>\s*\<case\>' ) +   elseif line =~ '^\s*end\>' +      " General case for end +      let ind = s:MainBlockIndent( ind, lnum, '\(if\|while\|for\|loop\|accept\|begin\|record\|case\|exception\|package\)\>', '' ) +   elseif line =~ '^\s*exception\>' +      let ind = s:MainBlockIndent( ind, lnum, 'begin\>', '' ) +   elseif line =~ '^\s*then\>' +      let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' ) +   endif + +   return ind +endfunction GetAdaIndent + +let &cpo = s:keepcpo +unlet s:keepcpo + +finish " 1}}} + +"------------------------------------------------------------------------------ +"   Copyright (C) 2006	Martin Krischik +" +"   Vim is Charityware - see ":help license" or uganda.txt for licence details. +"------------------------------------------------------------------------------ +" vim: textwidth=78 wrap tabstop=8 shiftwidth=3 softtabstop=3 noexpandtab +" vim: foldmethod=marker + +endif diff --git a/indent/ant.vim b/indent/ant.vim new file mode 100644 index 00000000..b555c6a2 --- /dev/null +++ b/indent/ant.vim @@ -0,0 +1,16 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    ANT files +" Maintainer:  David Fishburn <fishburn@ianywhere.com> +" Last Change: Thu May 15 2003 10:02:54 PM + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Use XML formatting rules +runtime! indent/xml.vim + +endif diff --git a/indent/automake.vim b/indent/automake.vim new file mode 100644 index 00000000..3ec6f83c --- /dev/null +++ b/indent/automake.vim @@ -0,0 +1,15 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    	    automake +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-04-19 + +if exists("b:did_indent") +  finish +endif + +" same as makefile indenting for now. +runtime! indent/make.vim + +endif diff --git a/indent/awk.vim b/indent/awk.vim new file mode 100644 index 00000000..8637dd53 --- /dev/null +++ b/indent/awk.vim @@ -0,0 +1,236 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"  vim: set sw=3 sts=3: + +" Awk indent script. It can handle multi-line statements and expressions. +" It works up to the point where the distinction between correct/incorrect +" and personal taste gets fuzzy. Drop me an e-mail for bug reports and +" reasonable style suggestions. +" +" Bugs: +" ===== +" - Some syntax errors may cause erratic indentation. +" - Same for very unusual but syntacticly correct use of { } +" - In some cases it's confused by the use of ( and { in strings constants +" - This version likes the closing brace of a multiline pattern-action be on +"   character position 1 before the following pattern-action combination is +"   formatted + +" Author: +" ======= +" Erik Janssen, ejanssen@itmatters.nl +" +" History: +" ======== +" 26-04-2002 Got initial version working reasonably well +" 29-04-2002 Fixed problems in function headers and max line width +"	     Added support for two-line if's without curly braces +" Fixed hang: 2011 Aug 31 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif + +let b:did_indent = 1 + +setlocal indentexpr=GetAwkIndent() +" Mmm, copied from the tcl indent program. Is this okay? +setlocal indentkeys-=:,0# + +" Only define the function once. +if exists("*GetAwkIndent") +    finish +endif + +" This function contains a lot of exit points. It checks for simple cases +" first to get out of the function as soon as possible, thereby reducing the +" number of possibilities later on in the difficult parts + +function! GetAwkIndent() + +   " Find previous line and get it's indentation +   let prev_lineno = s:Get_prev_line( v:lnum ) +   if prev_lineno == 0 +      return 0 +   endif +   let prev_data = getline( prev_lineno ) +   let ind = indent( prev_lineno ) + +   " Increase indent if the previous line contains an opening brace. Search +   " for this brace the hard way to prevent errors if the previous line is a +   " 'pattern { action }' (simple check match on /{/ increases the indent then) + +   if s:Get_brace_balance( prev_data, '{', '}' ) > 0 +      return ind + shiftwidth() +   endif + +   let brace_balance = s:Get_brace_balance( prev_data, '(', ')' ) + +   " If prev line has positive brace_balance and starts with a word (keyword +   " or function name), align the current line on the first '(' of the prev +   " line + +   if brace_balance > 0 && s:Starts_with_word( prev_data ) +      return s:Safe_indent( ind, s:First_word_len(prev_data), getline(v:lnum)) +   endif + +   " If this line starts with an open brace bail out now before the line +   " continuation checks. + +   if getline( v:lnum ) =~ '^\s*{' +      return ind +   endif + +   " If prev line seems to be part of multiline statement: +   " 1. Prev line is first line of a multiline statement +   "    -> attempt to indent on first ' ' or '(' of prev line, just like we +   "       indented the positive brace balance case above +   " 2. Prev line is not first line of a multiline statement +   "    -> copy indent of prev line + +   let continue_mode = s:Seems_continuing( prev_data ) +   if continue_mode > 0 +     if s:Seems_continuing( getline(s:Get_prev_line( prev_lineno )) ) +       " Case 2 +       return ind +     else +       " Case 1 +       if continue_mode == 1 +	  " Need continuation due to comma, backslash, etc +	  return s:Safe_indent( ind, s:First_word_len(prev_data), getline(v:lnum)) +       else +	 " if/for/while without '{' +	 return ind + shiftwidth() +       endif +     endif +   endif + +   " If the previous line doesn't need continuation on the current line we are +   " on the start of a new statement.  We have to make sure we align with the +   " previous statement instead of just the previous line. This is a bit +   " complicated because the previous statement might be multi-line. +   " +   " The start of a multiline statement can be found by: +   " +   " 1 If the previous line contains closing braces and has negative brace +   "   balance, search backwards until cumulative brace balance becomes zero, +   "   take indent of that line +   " 2 If the line before the previous needs continuation search backward +   "   until that's not the case anymore. Take indent of one line down. + +   " Case 1 +   if prev_data =~ ')' && brace_balance < 0 +      while brace_balance != 0 && prev_lineno > 0 +	 let prev_lineno = s:Get_prev_line( prev_lineno ) +	 let prev_data = getline( prev_lineno ) +	 let brace_balance=brace_balance+s:Get_brace_balance(prev_data,'(',')' ) +      endwhile +      let ind = indent( prev_lineno ) +   else +      " Case 2 +      if s:Seems_continuing( getline( prev_lineno - 1 ) ) +	 let prev_lineno = prev_lineno - 2 +	 let prev_data = getline( prev_lineno ) +	 while prev_lineno > 0 && (s:Seems_continuing( prev_data ) > 0) +	    let prev_lineno = s:Get_prev_line( prev_lineno ) +	    let prev_data = getline( prev_lineno ) +	 endwhile +	 let ind = indent( prev_lineno + 1 ) +      endif +   endif + +   " Decrease indent if this line contains a '}'. +   if getline(v:lnum) =~ '^\s*}' +      let ind = ind - shiftwidth() +   endif + +   return ind +endfunction + +" Find the open and close braces in this line and return how many more open- +" than close braces there are. It's also used to determine cumulative balance +" across multiple lines. + +function! s:Get_brace_balance( line, b_open, b_close ) +   let line2 = substitute( a:line, a:b_open, "", "g" ) +   let openb = strlen( a:line ) - strlen( line2 ) +   let line3 = substitute( line2, a:b_close, "", "g" ) +   let closeb = strlen( line2 ) - strlen( line3 ) +   return openb - closeb +endfunction + +" Find out whether the line starts with a word (i.e. keyword or function +" call). Might need enhancements here. + +function! s:Starts_with_word( line ) +  if a:line =~ '^\s*[a-zA-Z_0-9]\+\s*(' +     return 1 +  endif +  return 0 +endfunction + +" Find the length of the first word in a line. This is used to be able to +" align a line relative to the 'print ' or 'if (' on the previous line in case +" such a statement spans multiple lines. +" Precondition: only to be used on lines where 'Starts_with_word' returns 1. + +function! s:First_word_len( line ) +   let white_end = matchend( a:line, '^\s*' ) +   if match( a:line, '^\s*func' ) != -1 +     let word_end = matchend( a:line, '[a-z]\+\s\+[a-zA-Z_0-9]\+[ (]*' ) +   else +     let word_end = matchend( a:line, '[a-zA-Z_0-9]\+[ (]*' ) +   endif +   return word_end - white_end +endfunction + +" Determine if 'line' completes a statement or is continued on the next line. +" This one is far from complete and accepts illegal code. Not important for +" indenting, however. + +function! s:Seems_continuing( line ) +  " Unfinished lines +  if a:line =~ '\(--\|++\)\s*$' +    return 0 +  endif +  if a:line =~ '[\\,\|\&\+\-\*\%\^]\s*$' +    return 1 +  endif +  " if/for/while (cond) eol +  if a:line =~ '^\s*\(if\|while\|for\)\s*(.*)\s*$' || a:line =~ '^\s*else\s*' +      return 2 +   endif +  return 0 +endfunction + +" Get previous relevant line. Search back until a line is that is no +" comment or blank and return the line number + +function! s:Get_prev_line( lineno ) +   let lnum = a:lineno - 1 +   let data = getline( lnum ) +   while lnum > 0 && (data =~ '^\s*#' || data =~ '^\s*$') +      let lnum = lnum - 1 +      let data = getline( lnum ) +   endwhile +   return lnum +endfunction + +" This function checks whether an indented line exceeds a maximum linewidth +" (hardcoded 80). If so and it is possible to stay within 80 positions (or +" limit num of characters beyond linewidth) by decreasing the indent (keeping +" it > base_indent), do so. + +function! s:Safe_indent( base, wordlen, this_line ) +   let line_base = matchend( a:this_line, '^\s*' ) +   let line_len = strlen( a:this_line ) - line_base +   let indent = a:base +   if (indent + a:wordlen + line_len) > 80 +     " Simple implementation good enough for the time being +     let indent = indent + 3 +   endif +   return indent + a:wordlen +endfunction + +endif diff --git a/indent/bib.vim b/indent/bib.vim new file mode 100644 index 00000000..413591f6 --- /dev/null +++ b/indent/bib.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:      BibTeX +" Maintainer:    Dorai Sitaram <ds26@gte.com> +" URL:		 http://www.ccs.neu.edu/~dorai/vimplugins/vimplugins.html +" Last Change:   2005 Mar 28 + +" Only do this when not done yet for this buffer +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/bst.vim b/indent/bst.vim new file mode 100644 index 00000000..b11924b9 --- /dev/null +++ b/indent/bst.vim @@ -0,0 +1,79 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	bst +" Author:	Tim Pope <vimNOSPAM@tpope.info> +" $Id: bst.vim,v 1.1 2007/05/05 18:11:12 vimboss Exp $ + +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal expandtab +setlocal indentexpr=GetBstIndent(v:lnum) +"setlocal smartindent +setlocal cinkeys& +setlocal cinkeys-=0# +setlocal indentkeys& +"setlocal indentkeys+=0% + +" Only define the function once. +if exists("*GetBstIndent") +    finish +endif + +function! s:prevgood(lnum) +    " Find a non-blank line above the current line. +    " Skip over comments. +    let lnum = a:lnum +    while lnum > 0 +        let lnum = prevnonblank(lnum - 1) +        if getline(lnum) !~ '^\s*%.*$' +            break +        endif +    endwhile +    return lnum +endfunction + +function! s:strip(lnum) +    let line = getline(a:lnum) +    let line = substitute(line,'"[^"]*"','""','g') +    let line = substitute(line,'%.*','','') +    let line = substitute(line,'^\s\+','','') +    return line +endfunction + +function! s:count(string,char) +    let str = substitute(a:string,'[^'.a:char.']','','g') +    return strlen(str) +endfunction + +function! GetBstIndent(lnum) abort +    if a:lnum == 1 +        return 0 +    endif +    let lnum = s:prevgood(a:lnum) +    if lnum <= 0 +        return indent(a:lnum - 1) +    endif +    let line = s:strip(lnum) +    let cline = s:strip(a:lnum) +    if cline =~ '^}' && exists("b:current_syntax") +        call cursor(a:lnum,indent(a:lnum)) +        if searchpair('{','','}','bW',"synIDattr(synID(line('.'),col('.'),1),'name') =~? 'comment\\|string'") +            if col('.')+1 == col('$') +                return indent('.') +            else +                return virtcol('.')-1 +            endif +        endif +    endif +    let fakeline = substitute(line,'^}','','').matchstr(cline,'^}') +    let ind = indent(lnum) +    let ind = ind + shiftwidth() * s:count(line,'{') +    let ind = ind - shiftwidth() * s:count(fakeline,'}') +    return ind +endfunction + +endif diff --git a/indent/bzl.vim b/indent/bzl.vim new file mode 100644 index 00000000..838cf006 --- /dev/null +++ b/indent/bzl.vim @@ -0,0 +1,98 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Bazel (http://bazel.io) +" Maintainer:	David Barnett (https://github.com/google/vim-ft-bzl) +" Last Change:	2017 Jun 13 + +if exists('b:did_indent') +  finish +endif + +" Load base python indent. +if !exists('*GetPythonIndent') +  runtime! indent/python.vim +endif + +let b:did_indent = 1 + +" Only enable bzl google indent if python google indent is enabled. +if !get(g:, 'no_google_python_indent') +  setlocal indentexpr=GetBzlIndent(v:lnum) +endif + +if exists('*GetBzlIndent') +  finish +endif + +let s:save_cpo = &cpo +set cpo-=C + +" Maximum number of lines to look backwards. +let s:maxoff = 50 + +"" +" Determine the correct indent level given an {lnum} in the current buffer. +function GetBzlIndent(lnum) abort +  let l:use_recursive_indent = !get(g:, 'no_google_python_recursive_indent') +  if l:use_recursive_indent +    " Backup and override indent setting variables. +    if exists('g:pyindent_nested_paren') +      let l:pyindent_nested_paren = g:pyindent_nested_paren +    endif +    if exists('g:pyindent_open_paren') +      let l:pyindent_open_paren = g:pyindent_open_paren +    endif +    let g:pyindent_nested_paren = 'shiftwidth() * 2' +    let g:pyindent_open_paren = 'shiftwidth() * 2' +  endif + +  let l:indent = -1 + +  " Indent inside parens. +  " Align with the open paren unless it is at the end of the line. +  " E.g. +  "   open_paren_not_at_EOL(100, +  "                         (200, +  "                          300), +  "                         400) +  "   open_paren_at_EOL( +  "       100, 200, 300, 400) +  call cursor(a:lnum, 1) +  let [l:par_line, l:par_col] = searchpairpos('(\|{\|\[', '', ')\|}\|\]', 'bW', +      \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" . +      \ " synIDattr(synID(line('.'), col('.'), 1), 'name')" . +      \ " =~ '\\(Comment\\|String\\)$'") +  if l:par_line > 0 +    call cursor(l:par_line, 1) +    if l:par_col != col('$') - 1 +      let l:indent = l:par_col +    endif +  endif + +  " Delegate the rest to the original function. +  if l:indent == -1 +    let l:indent = GetPythonIndent(a:lnum) +  endif + +  if l:use_recursive_indent +    " Restore global variables. +    if exists('l:pyindent_nested_paren') +      let g:pyindent_nested_paren = l:pyindent_nested_paren +    else +      unlet g:pyindent_nested_paren +    endif +    if exists('l:pyindent_open_paren') +      let g:pyindent_open_paren = l:pyindent_open_paren +    else +      unlet g:pyindent_open_paren +    endif +  endif + +  return l:indent +endfunction + +let &cpo = s:save_cpo +unlet s:save_cpo + +endif diff --git a/indent/c.vim b/indent/c.vim new file mode 100644 index 00000000..2237af3e --- /dev/null +++ b/indent/c.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	C +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2005 Mar 27 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" C indenting is built-in, thus this is very simple +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/cdl.vim b/indent/cdl.vim new file mode 100644 index 00000000..76716666 --- /dev/null +++ b/indent/cdl.vim @@ -0,0 +1,133 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Description:	Comshare Dimension Definition Language (CDL) +" Author:	Raul Segura Acevedo <raulseguraaceved@netscape.net> +" Last Change:	Fri Nov 30 13:35:48  2001 CST + +if exists("b:did_indent") +    "finish +endif +let b:did_indent = 1 + +setlocal indentexpr=CdlGetIndent(v:lnum) +setlocal indentkeys& +setlocal indentkeys+==~else,=~endif,=~then,;,),= + +" Only define the function once. +if exists("*CdlGetIndent") +    "finish +endif + +" find out if an "...=..." expresion is an assignment (or a conditional) +" it scans 'line' first, and then the previos lines +fun! CdlAsignment(lnum, line) +  let f = -1 +  let lnum = a:lnum +  let line = a:line +  while lnum > 0 && f == -1 +    " line without members [a] of [b]:[c]... +    let inicio = 0 +    while 1 +      " keywords that help to decide +      let inicio = matchend(line, '\c\<\(expr\|\a*if\|and\|or\|not\|else\|then\|memberis\|\k\+of\)\>\|[<>;]', inicio) +      if inicio < 0 +	break +      endif +      " it's formula if there's a ';', 'elsE', 'theN', 'enDif' or 'expr' +      " conditional if there's a '<', '>', 'elseif', 'if', 'and', 'or', 'not', +      " 'memberis', 'childrenof' and other \k\+of funcions +      let f = line[inicio-1] =~? '[en;]' || strpart(line, inicio-4, 4) =~? 'ndif\|expr' +    endw +    let lnum = prevnonblank(lnum-1) +    let line = substitute(getline(lnum), '\c\(\[[^]]*]\(\s*of\s*\|:\)*\)\+', ' ', 'g') +  endw +  " if we hit the start of the file then f = -1, return 1 (formula) +  return f != 0 +endf + +fun! CdlGetIndent(lnum) +  let thisline = getline(a:lnum) +  if match(thisline, '^\s*\(\k\+\|\[[^]]*]\)\s*\(,\|;\s*$\)') >= 0 +    " it's an attributes line +    return shiftwidth() +  elseif match(thisline, '^\c\s*\([{}]\|\/[*/]\|dimension\|schedule\|group\|hierarchy\|class\)') >= 0 +    " it's a header or '{' or '}' or a comment +    return 0 +  end + +  let lnum = prevnonblank(a:lnum-1) +  " Hit the start of the file, use zero indent. +  if lnum == 0 +    return 0 +  endif + +  " PREVIOUS LINE +  let ind = indent(lnum) +  let line = getline(lnum) +  let f = -1 " wether a '=' is a conditional or a asignment, -1 means we don't know yet +  " one 'closing' element at the beginning of the line has already reduced the +  "   indent, but 'else', 'elseif' & 'then' increment it for the next line +  " '=' at the beginning has already de right indent (increased for asignments) +  let inicio = matchend(line, '^\c\s*\(else\a*\|then\|endif\|/[*/]\|[);={]\)') +  if inicio > 0 +    let c = line[inicio-1] +    " ')' and '=' don't change indent and are useless to set 'f' +    if c == '{' +      return shiftwidth() +    elseif c != ')' && c != '=' +      let f = 1 " all but 'elseif' are followed by a formula +      if c ==? 'n' || c ==? 'e' " 'then', 'else' +	let ind = ind + shiftwidth() +      elseif strpart(line, inicio-6, 6) ==? 'elseif' " elseif, set f to conditional +	let ind = ind + shiftwidth() +	let f = 0 +      end +    end +  end + +  " remove members [a] of [b]:[c]... (inicio remainds valid) +  let line = substitute(line, '\c\(\[[^]]*]\(\s*of\s*\|:\)*\)\+', ' ', 'g') +  while 1 +    " search for the next interesting element +    let inicio=matchend(line, '\c\<if\|endif\|[()=;]', inicio) +    if inicio < 0 +      break +    end + +    let c = line[inicio-1] +    " 'expr(...)' containing the formula +    if strpart(line, inicio-5, 5) ==? 'expr(' +      let ind = 0 +      let f = 1 +    elseif c == ')' || c== ';' || strpart(line, inicio-5, 5) ==? 'endif' +      let ind = ind - shiftwidth() +    elseif c == '(' || c ==? 'f' " '(' or 'if' +      let ind = ind + shiftwidth() +    else " c == '=' +      " if it is an asignment increase indent +      if f == -1 " we don't know yet, find out +	let f = CdlAsignment(lnum, strpart(line, 0, inicio)) +      end +      if f == 1 " formula increase it +	let ind = ind + shiftwidth() +      end +    end +  endw + +  " CURRENT LINE, if it starts with a closing element, decrease indent +  " or if it starts with '=' (asignment), increase indent +  if match(thisline, '^\c\s*\(else\|then\|endif\|[);]\)') >= 0 +    let ind = ind - shiftwidth() +  elseif match(thisline, '^\s*=') >= 0 +    if f == -1 " we don't know yet if is an asignment, find out +      let f = CdlAsignment(lnum, "") +    end +    if f == 1 " formula increase it +      let ind = ind + shiftwidth() +    end +  end + +  return ind +endfun + +endif diff --git a/indent/ch.vim b/indent/ch.vim new file mode 100644 index 00000000..bdaf531a --- /dev/null +++ b/indent/ch.vim @@ -0,0 +1,22 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Ch +" Maintainer:	SoftIntegration, Inc. <info@softintegration.com> +" URL:		http://www.softintegration.com/download/vim/indent/ch.vim +" Last change:	2006 Apr 30 +"		Created based on cpp.vim +" +" Ch is a C/C++ interpreter with many high level extensions + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" Ch indenting is built-in, thus this is very simple +setlocal cindent + +endif diff --git a/indent/chaiscript.vim b/indent/chaiscript.vim new file mode 100644 index 00000000..9c8b2283 --- /dev/null +++ b/indent/chaiscript.vim @@ -0,0 +1,54 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     ChaiScript +" Maintainer:	Jason Turner <lefticus 'at' gmail com> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetChaiScriptIndent() +setlocal autoindent + +" Only define the function once. +if exists("*GetChaiScriptIndent") +  finish +endif + +function! GetChaiScriptIndent() +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " Hit the start of the file, use zero indent. +  if lnum == 0 +    return 0 +  endif + +  " Add a 'shiftwidth' after lines that start a block: +  " lines containing a { +  let ind = indent(lnum) +  let flag = 0 +  let prevline = getline(lnum) +  if prevline =~ '^.*{.*' +    let ind = ind + shiftwidth() +    let flag = 1 +  endif + +  " Subtract a 'shiftwidth' after lines containing a { followed by a } +  " to keep it balanced +  if flag == 1 && prevline =~ '.*{.*}.*' +    let ind = ind - shiftwidth() +  endif + +  " Subtract a 'shiftwidth' on lines ending with } +  if getline(v:lnum) =~ '^\s*\%(}\)' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/changelog.vim b/indent/changelog.vim new file mode 100644 index 00000000..872692dd --- /dev/null +++ b/indent/changelog.vim @@ -0,0 +1,18 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	generic Changelog file +" Maintainer:	noone +" Last Change:	2005 Mar 29 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +setlocal ai + +let b:undo_indent = "setl ai<" + +endif diff --git a/indent/clojure.vim b/indent/clojure.vim index f538195a..5d982e4a 100644 --- a/indent/clojure.vim +++ b/indent/clojure.vim @@ -1,3 +1,401 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     Clojure +" Author:       Meikel Brandmeyer <mb@kotka.de> +" URL:          http://kotka.de/projects/clojure/vimclojure.html +" +" Maintainer:   Sung Pae <self@sungpae.com> +" URL:          https://github.com/guns/vim-clojure-static +" License:      Same as Vim +" Last Change:  18 July 2016 + +if exists("b:did_indent") +	finish +endif +let b:did_indent = 1 + +let s:save_cpo = &cpo +set cpo&vim + +let b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<' + +setlocal noautoindent nosmartindent +setlocal softtabstop=2 shiftwidth=2 expandtab +setlocal indentkeys=!,o,O + +if exists("*searchpairpos") + +	if !exists('g:clojure_maxlines') +		let g:clojure_maxlines = 100 +	endif + +	if !exists('g:clojure_fuzzy_indent') +		let g:clojure_fuzzy_indent = 1 +	endif + +	if !exists('g:clojure_fuzzy_indent_patterns') +		let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let'] +	endif + +	if !exists('g:clojure_fuzzy_indent_blacklist') +		let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$'] +	endif + +	if !exists('g:clojure_special_indent_words') +		let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn' +	endif + +	if !exists('g:clojure_align_multiline_strings') +		let g:clojure_align_multiline_strings = 0 +	endif + +	if !exists('g:clojure_align_subforms') +		let g:clojure_align_subforms = 0 +	endif + +	function! s:syn_id_name() +		return synIDattr(synID(line("."), col("."), 0), "name") +	endfunction + +	function! s:ignored_region() +		return s:syn_id_name() =~? '\vstring|regex|comment|character' +	endfunction + +	function! s:current_char() +		return getline('.')[col('.')-1] +	endfunction + +	function! s:current_word() +		return getline('.')[col('.')-1 : searchpos('\v>', 'n', line('.'))[1]-2] +	endfunction + +	function! s:is_paren() +		return s:current_char() =~# '\v[\(\)\[\]\{\}]' && !s:ignored_region() +	endfunction + +	" Returns 1 if string matches a pattern in 'patterns', which may be a +	" list of patterns, or a comma-delimited string of implicitly anchored +	" patterns. +	function! s:match_one(patterns, string) +		let list = type(a:patterns) == type([]) +		           \ ? a:patterns +		           \ : map(split(a:patterns, ','), '"^" . v:val . "$"') +		for pat in list +			if a:string =~# pat | return 1 | endif +		endfor +	endfunction + +	function! s:match_pairs(open, close, stopat) +		" Stop only on vector and map [ resp. {. Ignore the ones in strings and +		" comments. +		if a:stopat == 0 +			let stopat = max([line(".") - g:clojure_maxlines, 0]) +		else +			let stopat = a:stopat +		endif + +		let pos = searchpairpos(a:open, '', a:close, 'bWn', "!s:is_paren()", stopat) +		return [pos[0], col(pos)] +	endfunction + +	function! s:clojure_check_for_string_worker() +		" Check whether there is the last character of the previous line is +		" highlighted as a string. If so, we check whether it's a ". In this +		" case we have to check also the previous character. The " might be the +		" closing one. In case the we are still in the string, we search for the +		" opening ". If this is not found we take the indent of the line. +		let nb = prevnonblank(v:lnum - 1) + +		if nb == 0 +			return -1 +		endif + +		call cursor(nb, 0) +		call cursor(0, col("$") - 1) +		if s:syn_id_name() !~? "string" +			return -1 +		endif + +		" This will not work for a " in the first column... +		if s:current_char() == '"' +			call cursor(0, col("$") - 2) +			if s:syn_id_name() !~? "string" +				return -1 +			endif +			if s:current_char() != '\\' +				return -1 +			endif +			call cursor(0, col("$") - 1) +		endif + +		let p = searchpos('\(^\|[^\\]\)\zs"', 'bW') + +		if p != [0, 0] +			return p[1] - 1 +		endif + +		return indent(".") +	endfunction + +	function! s:check_for_string() +		let pos = getpos('.') +		try +			let val = s:clojure_check_for_string_worker() +		finally +			call setpos('.', pos) +		endtry +		return val +	endfunction + +	function! s:strip_namespace_and_macro_chars(word) +		return substitute(a:word, "\\v%(.*/|[#'`~@^,]*)(.*)", '\1', '') +	endfunction + +	function! s:clojure_is_method_special_case_worker(position) +		" Find the next enclosing form. +		call search('\S', 'Wb') + +		" Special case: we are at a '(('. +		if s:current_char() == '(' +			return 0 +		endif +		call cursor(a:position) + +		let next_paren = s:match_pairs('(', ')', 0) + +		" Special case: we are now at toplevel. +		if next_paren == [0, 0] +			return 0 +		endif +		call cursor(next_paren) + +		call search('\S', 'W') +		let w = s:strip_namespace_and_macro_chars(s:current_word()) +		if g:clojure_special_indent_words =~# '\V\<' . w . '\>' +			return 1 +		endif + +		return 0 +	endfunction + +	function! s:is_method_special_case(position) +		let pos = getpos('.') +		try +			let val = s:clojure_is_method_special_case_worker(a:position) +		finally +			call setpos('.', pos) +		endtry +		return val +	endfunction + +	" Check if form is a reader conditional, that is, it is prefixed by #? +	" or @#? +	function! s:is_reader_conditional_special_case(position) +		if getline(a:position[0])[a:position[1] - 3 : a:position[1] - 2] == "#?" +			return 1 +		endif + +		return 0 +	endfunction + +	" Returns 1 for opening brackets, -1 for _anything else_. +	function! s:bracket_type(char) +		return stridx('([{', a:char) > -1 ? 1 : -1 +	endfunction + +	" Returns: [opening-bracket-lnum, indent] +	function! s:clojure_indent_pos() +		" Get rid of special case. +		if line(".") == 1 +			return [0, 0] +		endif + +		" We have to apply some heuristics here to figure out, whether to use +		" normal lisp indenting or not. +		let i = s:check_for_string() +		if i > -1 +			return [0, i + !!g:clojure_align_multiline_strings] +		endif + +		call cursor(0, 1) + +		" Find the next enclosing [ or {. We can limit the second search +		" to the line, where the [ was found. If no [ was there this is +		" zero and we search for an enclosing {. +		let paren = s:match_pairs('(', ')', 0) +		let bracket = s:match_pairs('\[', '\]', paren[0]) +		let curly = s:match_pairs('{', '}', bracket[0]) + +		" In case the curly brace is on a line later then the [ or - in +		" case they are on the same line - in a higher column, we take the +		" curly indent. +		if curly[0] > bracket[0] || curly[1] > bracket[1] +			if curly[0] > paren[0] || curly[1] > paren[1] +				return curly +			endif +		endif + +		" If the curly was not chosen, we take the bracket indent - if +		" there was one. +		if bracket[0] > paren[0] || bracket[1] > paren[1] +			return bracket +		endif + +		" There are neither { nor [ nor (, ie. we are at the toplevel. +		if paren == [0, 0] +			return paren +		endif + +		" Now we have to reimplement lispindent. This is surprisingly easy, as +		" soon as one has access to syntax items. +		" +		" - Check whether we are in a special position after a word in +		"   g:clojure_special_indent_words. These are special cases. +		" - Get the next keyword after the (. +		" - If its first character is also a (, we have another sexp and align +		"   one column to the right of the unmatched (. +		" - In case it is in lispwords, we indent the next line to the column of +		"   the ( + sw. +		" - If not, we check whether it is last word in the line. In that case +		"   we again use ( + sw for indent. +		" - In any other case we use the column of the end of the word + 2. +		call cursor(paren) + +		if s:is_method_special_case(paren) +			return [paren[0], paren[1] + shiftwidth() - 1] +		endif + +		if s:is_reader_conditional_special_case(paren) +			return paren +		endif + +		" In case we are at the last character, we use the paren position. +		if col("$") - 1 == paren[1] +			return paren +		endif + +		" In case after the paren is a whitespace, we search for the next word. +		call cursor(0, col('.') + 1) +		if s:current_char() == ' ' +			call search('\v\S', 'W') +		endif + +		" If we moved to another line, there is no word after the (. We +		" use the ( position for indent. +		if line(".") > paren[0] +			return paren +		endif + +		" We still have to check, whether the keyword starts with a (, [ or {. +		" In that case we use the ( position for indent. +		let w = s:current_word() +		if s:bracket_type(w[0]) == 1 +			return paren +		endif + +		" Test words without namespace qualifiers and leading reader macro +		" metacharacters. +		" +		" e.g. clojure.core/defn and #'defn should both indent like defn. +		let ww = s:strip_namespace_and_macro_chars(w) + +		if &lispwords =~# '\V\<' . ww . '\>' +			return [paren[0], paren[1] + shiftwidth() - 1] +		endif + +		if g:clojure_fuzzy_indent +			\ && !s:match_one(g:clojure_fuzzy_indent_blacklist, ww) +			\ && s:match_one(g:clojure_fuzzy_indent_patterns, ww) +			return [paren[0], paren[1] + shiftwidth() - 1] +		endif + +		call search('\v\_s', 'cW') +		call search('\v\S', 'W') +		if paren[0] < line(".") +			return [paren[0], paren[1] + (g:clojure_align_subforms ? 0 : shiftwidth() - 1)] +		endif + +		call search('\v\S', 'bW') +		return [line('.'), col('.') + 1] +	endfunction + +	function! GetClojureIndent() +		let lnum = line('.') +		let orig_lnum = lnum +		let orig_col = col('.') +		let [opening_lnum, indent] = s:clojure_indent_pos() + +		" Account for multibyte characters +		if opening_lnum > 0 +			let indent -= indent - virtcol([opening_lnum, indent]) +		endif + +		" Return if there are no previous lines to inherit from +		if opening_lnum < 1 || opening_lnum >= lnum - 1 +			call cursor(orig_lnum, orig_col) +			return indent +		endif + +		let bracket_count = 0 + +		" Take the indent of the first previous non-white line that is +		" at the same sexp level. cf. src/misc1.c:get_lisp_indent() +		while 1 +			let lnum = prevnonblank(lnum - 1) +			let col = 1 + +			if lnum <= opening_lnum +				break +			endif + +			call cursor(lnum, col) + +			" Handle bracket counting edge case +			if s:is_paren() +				let bracket_count += s:bracket_type(s:current_char()) +			endif + +			while 1 +				if search('\v[(\[{}\])]', '', lnum) < 1 +					break +				elseif !s:ignored_region() +					let bracket_count += s:bracket_type(s:current_char()) +				endif +			endwhile + +			if bracket_count == 0 +				" Check if this is part of a multiline string +				call cursor(lnum, 1) +				if s:syn_id_name() !~? '\vstring|regex' +					call cursor(orig_lnum, orig_col) +					return indent(lnum) +				endif +			endif +		endwhile + +		call cursor(orig_lnum, orig_col) +		return indent +	endfunction + +	setlocal indentexpr=GetClojureIndent() + +else + +	" In case we have searchpairpos not available we fall back to +	" normal lisp indenting. +	setlocal indentexpr= +	setlocal lisp +	let b:undo_indent .= '| setlocal lisp<' + +endif + +let &cpo = s:save_cpo +unlet! s:save_cpo + +" vim:sts=8:sw=8:ts=8:noet + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'clojure') == -1  " Vim indent file diff --git a/indent/cmake.vim b/indent/cmake.vim new file mode 100644 index 00000000..f67a14d2 --- /dev/null +++ b/indent/cmake.vim @@ -0,0 +1,93 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     CMake (ft=cmake) +" Author:       Andy Cedilnik <andy.cedilnik@kitware.com> +" Maintainer:   Dimitri Merejkowsky <d.merej@gmail.com> +" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com> +" Last Change:  2017 Aug 30 +" +" Licence:      The CMake license applies to this file. See +"               https://cmake.org/licensing +"               This implies that distribution with Vim is allowed + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal et +setlocal indentexpr=CMakeGetIndent(v:lnum) +setlocal indentkeys+==ENDIF(,ENDFOREACH(,ENDMACRO(,ELSE(,ELSEIF(,ENDWHILE( + +" Only define the function once. +if exists("*CMakeGetIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +fun! CMakeGetIndent(lnum) +  let this_line = getline(a:lnum) + +  " Find a non-blank line above the current line. +  let lnum = a:lnum +  let lnum = prevnonblank(lnum - 1) +  let previous_line = getline(lnum) + +  " Hit the start of the file, use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) + +  let or = '\|' +  " Regular expressions used by line indentation function. +  let cmake_regex_comment = '#.*' +  let cmake_regex_identifier = '[A-Za-z][A-Za-z0-9_]*' +  let cmake_regex_quoted = '"\([^"\\]\|\\.\)*"' +  let cmake_regex_arguments = '\(' . cmake_regex_quoted . +                    \       or . '\$(' . cmake_regex_identifier . ')' . +                    \       or . '[^()\\#"]' . or . '\\.' . '\)*' + +  let cmake_indent_comment_line = '^\s*' . cmake_regex_comment +  let cmake_indent_blank_regex = '^\s*$' +  let cmake_indent_open_regex = '^\s*' . cmake_regex_identifier . +                    \           '\s*(' . cmake_regex_arguments . +                    \           '\(' . cmake_regex_comment . '\)\?$' + +  let cmake_indent_close_regex = '^' . cmake_regex_arguments . +                    \            ')\s*' . +                    \            '\(' . cmake_regex_comment . '\)\?$' + +  let cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*(' +  let cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*(' + +  " Add +  if previous_line =~? cmake_indent_comment_line " Handle comments +    let ind = ind +  else +    if previous_line =~? cmake_indent_begin_regex +      let ind = ind + &sw +    endif +    if previous_line =~? cmake_indent_open_regex +      let ind = ind + &sw +    endif +  endif + +  " Subtract +  if this_line =~? cmake_indent_end_regex +    let ind = ind - &sw +  endif +  if previous_line =~? cmake_indent_close_regex +    let ind = ind - &sw +  endif + +  return ind +endfun + +let &cpo = s:keepcpo +unlet s:keepcpo + +endif diff --git a/indent/cobol.vim b/indent/cobol.vim new file mode 100644 index 00000000..3d261f15 --- /dev/null +++ b/indent/cobol.vim @@ -0,0 +1,220 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	cobol +" Author:	Tim Pope <vimNOSPAM@tpope.info> +" $Id: cobol.vim,v 1.1 2007/05/05 18:08:19 vimboss Exp $ + +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal expandtab +setlocal indentexpr=GetCobolIndent(v:lnum) +setlocal indentkeys& +setlocal indentkeys+=0<*>,0/,0$,0=01,=~division,=~section,0=~end,0=~then,0=~else,0=~when,*<Return>,. + +" Only define the function once. +if exists("*GetCobolIndent") +    finish +endif + +let s:skip = 'getline(".") =~ "^.\\{6\\}[*/$-]\\|\"[^\"]*\""' + +function! s:prevgood(lnum) +    " Find a non-blank line above the current line. +    " Skip over comments. +    let lnum = a:lnum +    while lnum > 0 +        let lnum = prevnonblank(lnum - 1) +        let line = getline(lnum) +        if line !~? '^\s*[*/$-]' && line !~? '^.\{6\}[*/$CD-]' +            break +        endif +    endwhile +    return lnum +endfunction + +function! s:stripped(lnum) +    return substitute(strpart(getline(a:lnum),0,72),'^\s*','','') +endfunction + +function! s:optionalblock(lnum,ind,blocks,clauses) +    let ind = a:ind +    let clauses = '\c\<\%(\<NOT\s\+\)\@<!\%(NOT\s\+\)\=\%('.a:clauses.'\)' +    let begin = '\c-\@<!\<\%('.a:blocks.'\)\>' +    let beginfull = begin.'\ze.*\%(\n\%(\s*\%([*/$-].*\)\=\n\)*\)\=\s*\%('.clauses.'\)' +    let end   = '\c\<end-\%('.a:blocks.'\)\>\|\%(\.\%( \|$\)\)\@=' +    let cline = s:stripped(a:lnum) +    let line  = s:stripped(s:prevgood(a:lnum)) +    if cline =~? clauses "&& line !~? '^search\>' +        call cursor(a:lnum,1) +        let lastclause = searchpair(beginfull,clauses,end,'bWr',s:skip) +        if getline(lastclause) =~? clauses && s:stripped(lastclause) !~? '^'.begin +            let ind = indent(lastclause) +        elseif lastclause > 0 +            let ind = indent(lastclause) + shiftwidth() +            "let ind = ind + shiftwidth() +        endif +    elseif line =~? clauses && cline !~? end +        let ind = ind + shiftwidth() +    endif +    return ind +endfunction + +function! GetCobolIndent(lnum) abort +    let minshft = 6 +    let ashft = minshft + 1 +    let bshft = ashft + 4 +    " (Obsolete) numbered lines +    if getline(a:lnum) =~? '^\s*\d\{6\}\%($\|[ */$CD-]\)' +        return 0 +    endif +    let cline = s:stripped(a:lnum) +    " Comments, etc. must start in the 7th column +    if cline =~? '^[*/$-]' +        return minshft +    elseif cline =~# '^[CD]' && indent(a:lnum) == minshft +        return minshft +    endif +    " Divisions, sections, and file descriptions start in area A +    if cline =~? '\<\(DIVISION\|SECTION\)\%($\|\.\)' || cline =~? '^[FS]D\>' +        return ashft +    endif +    " Fields +    if cline =~? '^0*\(1\|77\)\>' +        return ashft +    endif +    if cline =~? '^\d\+\>' +        let cnum = matchstr(cline,'^\d\+\>') +        let default = 0 +        let step = -1 +        while step < 2 +        let lnum = a:lnum +        while lnum > 0 && lnum < line('$') && lnum > a:lnum - 500 && lnum < a:lnum + 500 +            let lnum = step > 0 ? nextnonblank(lnum + step) : prevnonblank(lnum + step) +            let line = getline(lnum) +            let lindent = indent(lnum) +            if line =~? '^\s*\d\+\>' +                let num = matchstr(line,'^\s*\zs\d\+\>') +                if 0+cnum == num +                    return lindent +                elseif 0+cnum > num && default < lindent + shiftwidth() +                    let default = lindent + shiftwidth() +                endif +            elseif lindent < bshft && lindent >= ashft +                break +            endif +        endwhile +        let step = step + 2 +        endwhile +        return default ? default : bshft +    endif +    let lnum = s:prevgood(a:lnum) +    " Hit the start of the file, use "zero" indent. +    if lnum == 0 +        return ashft +    endif +    " Initial spaces are ignored +    let line = s:stripped(lnum) +    let ind = indent(lnum) +    " Paragraphs.  There may be some false positives. +    if cline =~? '^\(\a[A-Z0-9-]*[A-Z0-9]\|\d[A-Z0-9-]*\a\)\.' "\s*$' +        if cline !~? '^EXIT\s*\.' && line =~? '\.\s*$' +            return ashft +        endif +    endif +    " Paragraphs in the identification division. +    "if cline =~? '^\(PROGRAM-ID\|AUTHOR\|INSTALLATION\|' . +                "\ 'DATE-WRITTEN\|DATE-COMPILED\|SECURITY\)\>' +        "return ashft +    "endif +    if line =~? '\.$' +        " XXX +        return bshft +    endif +    if line =~? '^PERFORM\>' +        let perfline = substitute(line, '\c^PERFORM\s*', "", "") +        if perfline =~? '^\%(\k\+\s\+TIMES\)\=\s*$' +            let ind = ind + shiftwidth() +        elseif perfline =~? '^\%(WITH\s\+TEST\|VARYING\|UNTIL\)\>.*[^.]$' +            let ind = ind + shiftwidth() +        endif +    endif +    if line =~? '^\%(IF\|THEN\|ELSE\|READ\|EVALUATE\|SEARCH\|SELECT\)\>' +        let ind = ind + shiftwidth() +    endif +    let ind = s:optionalblock(a:lnum,ind,'ADD\|COMPUTE\|DIVIDE\|MULTIPLY\|SUBTRACT','ON\s\+SIZE\s\+ERROR') +    let ind = s:optionalblock(a:lnum,ind,'STRING\|UNSTRING\|ACCEPT\|DISPLAY\|CALL','ON\s\+OVERFLOW\|ON\s\+EXCEPTION') +    if cline !~? '^AT\s\+END\>' || line !~? '^SEARCH\>' +        let ind = s:optionalblock(a:lnum,ind,'DELETE\|REWRITE\|START\|WRITE\|READ','INVALID\s\+KEY\|AT\s\+END\|NO\s\+DATA\|AT\s\+END-OF-PAGE') +    endif +    if cline =~? '^WHEN\>' +        call cursor(a:lnum,1) +        " We also search for READ so that contained AT ENDs are skipped +        let lastclause = searchpair('\c-\@<!\<\%(SEARCH\|EVALUATE\|READ\)\>','\c\<\%(WHEN\|AT\s\+END\)\>','\c\<END-\%(SEARCH\|EVALUATE\|READ\)\>','bW',s:skip) +        let g:foo = s:stripped(lastclause) +        if s:stripped(lastclause) =~? '\c\<\%(WHEN\|AT\s\+END\)\>' +            "&& s:stripped(lastclause) !~? '^\%(SEARCH\|EVALUATE\|READ\)\>' +            let ind = indent(lastclause) +        elseif lastclause > 0 +            let ind = indent(lastclause) + shiftwidth() +        endif +    elseif line =~? '^WHEN\>' +        let ind = ind + shiftwidth() +    endif +    "I'm not sure why I had this +    "if line =~? '^ELSE\>-\@!' && line !~? '\.$' +        "let ind = indent(s:prevgood(lnum)) +    "endif +    if cline =~? '^\(END\)\>-\@!' +        " On lines with just END, 'guess' a simple shift left +        let ind = ind - shiftwidth() +    elseif cline =~? '^\(END-IF\|THEN\|ELSE\)\>-\@!' +        call cursor(a:lnum,indent(a:lnum)) +        let match = searchpair('\c-\@<!\<IF\>','\c-\@<!\%(THEN\|ELSE\)\>','\c-\@<!\<END-IF\>\zs','bnW',s:skip) +        if match > 0 +            let ind = indent(match) +        endif +    elseif cline =~? '^END-[A-Z]' +        let beginword = matchstr(cline,'\c\<END-\zs[A-Z0-9-]\+') +        let endword = 'END-'.beginword +        let first = 0 +        let suffix = '.*\%(\n\%(\%(\s*\|.\{6\}\)[*/].*\n\)*\)\=\s*' +        if beginword =~? '^\%(ADD\|COMPUTE\|DIVIDE\|MULTIPLY\|SUBTRACT\)$' +            let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+SIZE\s\+ERROR' +            let g:beginword = beginword +            let first = 1 +        elseif beginword =~? '^\%(STRING\|UNSTRING\)$' +            let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+OVERFLOW' +            let first = 1 +        elseif beginword =~? '^\%(ACCEPT\|DISPLAY\)$' +            let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+EXCEPTION' +            let first = 1 +        elseif beginword ==? 'CALL' +            let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+\%(EXCEPTION\|OVERFLOW\)' +            let first = 1 +        elseif beginword =~? '^\%(DELETE\|REWRITE\|START\|READ\|WRITE\)$' +            let first = 1 +            let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=\(INVALID\s\+KEY' +            if beginword =~? '^READ' +                let first = 0 +                let beginword = beginword . '\|AT\s\+END\|NO\s\+DATA' +            elseif beginword =~? '^WRITE' +                let beginword = beginword . '\|AT\s\+END-OF-PAGE' +            endif +            let beginword = beginword . '\)' +        endif +        call cursor(a:lnum,indent(a:lnum)) +        let match = searchpair('\c-\@<!\<'.beginword.'\>','','\c\<'.endword.'\>\zs','bnW'.(first? 'r' : ''),s:skip) +        if match > 0 +            let ind = indent(match) +        elseif cline =~? '^\(END-\(READ\|EVALUATE\|SEARCH\|PERFORM\)\)\>' +            let ind = ind - shiftwidth() +        endif +    endif +    return ind < bshft ? bshft : ind +endfunction + +endif diff --git a/indent/config.vim b/indent/config.vim new file mode 100644 index 00000000..a49741ca --- /dev/null +++ b/indent/config.vim @@ -0,0 +1,86 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Autoconf configure.{ac,in} file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 +" TODO:                 how about nested [()]'s in one line +"                   what's wrong with '\\\@!'? + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +runtime! indent/sh.vim          " will set b:did_indent + +setlocal indentexpr=GetConfigIndent() +setlocal indentkeys=!^F,o,O,=then,=do,=else,=elif,=esac,=fi,=fin,=fil,=done +setlocal nosmartindent + +" Only define the function once. +if exists("*GetConfigIndent") +  finish +endif + +" get the offset (indent) of the end of the match of 'regexp' in 'line' +function s:GetOffsetOf(line, regexp) +  let end = matchend(a:line, a:regexp) +  let width = 0 +  let i = 0 +  while i < end +    if a:line[i] != "\t" +      let width = width + 1 +    else +      let width = width + &ts - (width % &ts) +    endif +    let i = i + 1 +  endwhile +  return width +endfunction + +function GetConfigIndent() +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " Hit the start of the file, use zero indent. +  if lnum == 0 +    return 0 +  endif + +  " where to put this +  let ind = GetShIndent() +  let line = getline(lnum) + +  " if previous line has unmatched, unescaped opening parentheses, +  " indent to its position. TODO: not failsafe if multiple ('s +  if line =~ '\\\@<!([^)]*$' +    let ind = s:GetOffsetOf(line, '\\\@!(') +  endif + +  " if previous line has unmatched opening bracket, +  " indent to its position. TODO: same as above +  if line =~ '\[[^]]*$' +    let ind = s:GetOffsetOf(line, '\[') +  endif + +  " if previous line had an unmatched closing parantheses, +  " indent to the matching opening parantheses +  if line =~ '[^(]\+\\\@<!)$' +    call search(')', 'bW') +    let lnum = searchpair('\\\@<!(', '', ')', 'bWn') +    let ind = indent(lnum) +  endif + +  " if previous line had an unmatched closing bracket, +  " indent to the matching opening bracket +  if line =~ '[^[]\+]$' +    call search(']', 'bW') +    let lnum = searchpair('\[', '', ']', 'bWn') +    let ind = indent(lnum) +  endif + +  return ind +endfunction + +endif diff --git a/indent/context.vim b/indent/context.vim new file mode 100644 index 00000000..41c98af8 --- /dev/null +++ b/indent/context.vim @@ -0,0 +1,40 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" ConTeXt indent file +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change:  2016 Oct 15 + +if exists("b:did_indent") +  finish +endif + +if !get(b:, 'context_metapost', get(g:, 'context_metapost', 1)) +  finish +endif + +" Load MetaPost indentation script +runtime! indent/mp.vim + +let s:keepcpo= &cpo +set cpo&vim + +setlocal indentexpr=GetConTeXtIndent() + +let b:undo_indent = "setl indentexpr<" + +function! GetConTeXtIndent() +  " Use MetaPost rules inside MetaPost graphic environments +  if len(synstack(v:lnum, 1)) > 0 && +        \ synIDattr(synstack(v:lnum, 1)[0], "name") ==# 'contextMPGraphic' +    return GetMetaPostIndent() +  endif +  return -1 +endfunc + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 + +endif diff --git a/indent/cpp.vim b/indent/cpp.vim new file mode 100644 index 00000000..e6bbfc63 --- /dev/null +++ b/indent/cpp.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	C++ +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2008 Nov 29 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" C++ indenting is built-in, thus this is very simple +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/cs.vim b/indent/cs.vim new file mode 100644 index 00000000..bd04c1e9 --- /dev/null +++ b/indent/cs.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	C# +" Maintainer:	Johannes Zellner <johannes@zellner.org> +" Last Change:	Fri, 15 Mar 2002 07:53:54 CET + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" C# is like indenting C +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/css.vim b/indent/css.vim new file mode 100644 index 00000000..bf26f77b --- /dev/null +++ b/indent/css.vim @@ -0,0 +1,88 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	    CSS +" Maintainer:	    Nikolai Weibull <now@bitwi.se> +" Latest Revision:  2012-05-30 +"		    Use of shiftwidth() added by Oleg Zubchenko.	 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetCSSIndent() +setlocal indentkeys=0{,0},!^F,o,O +setlocal nosmartindent + +let b:undo_indent = "setl smartindent< indentkeys< indentexpr<" + +if exists("*GetCSSIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +function s:prevnonblanknoncomment(lnum) +  let lnum = a:lnum +  while lnum > 1 +    let lnum = prevnonblank(lnum) +    let line = getline(lnum) +    if line =~ '\*/' +      while lnum > 1 && line !~ '/\*' +        let lnum -= 1 +      endwhile +      if line =~ '^\s*/\*' +        let lnum -= 1 +      else +        break +      endif +    else +      break +    endif +  endwhile +  return lnum +endfunction + +function s:count_braces(lnum, count_open) +  let n_open = 0 +  let n_close = 0 +  let line = getline(a:lnum) +  let pattern = '[{}]' +  let i = match(line, pattern) +  while i != -1 +    if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'css\%(Comment\|StringQ\{1,2}\)' +      if line[i] == '{' +        let n_open += 1 +      elseif line[i] == '}' +        if n_open > 0 +          let n_open -= 1 +        else +          let n_close += 1 +        endif +      endif +    endif +    let i = match(line, pattern, i + 1) +  endwhile +  return a:count_open ? n_open : n_close +endfunction + +function GetCSSIndent() +  let line = getline(v:lnum) +  if line =~ '^\s*\*' +    return cindent(v:lnum) +  endif + +  let pnum = s:prevnonblanknoncomment(v:lnum - 1) +  if pnum == 0 +    return 0 +  endif + +  return indent(pnum) + s:count_braces(pnum, 1) * shiftwidth() +        \ - s:count_braces(v:lnum, 0) * shiftwidth() +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +endif diff --git a/indent/cucumber.vim b/indent/cucumber.vim index 03f11dc8..a6b745c0 100644 --- a/indent/cucumber.vim +++ b/indent/cucumber.vim @@ -1,3 +1,82 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Cucumber +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2017 Jun 13 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetCucumberIndent() +setlocal indentkeys=o,O,*<Return>,<:>,0<Bar>,0#,=,!^F + +let b:undo_indent = 'setl ai< inde< indk<' + +" Only define the function once. +if exists("*GetCucumberIndent") +  finish +endif + +function! s:syn(lnum) +  return synIDattr(synID(a:lnum,1+indent(a:lnum),1),'name') +endfunction + +function! GetCucumberIndent() +  let line  = getline(prevnonblank(v:lnum-1)) +  let cline = getline(v:lnum) +  let nline = getline(nextnonblank(v:lnum+1)) +  let sw = exists('*shiftwidth') ? shiftwidth() : shiftwidth() +  let syn = s:syn(prevnonblank(v:lnum-1)) +  let csyn = s:syn(v:lnum) +  let nsyn = s:syn(nextnonblank(v:lnum+1)) +  if csyn ==# 'cucumberFeature' || cline =~# '^\s*Feature:' +    " feature heading +    return 0 +  elseif csyn ==# 'cucumberExamples' || cline =~# '^\s*\%(Examples\|Scenarios\):' +    " examples heading +    return 2 * sw +  elseif csyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || cline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' +    " background, scenario or outline heading +    return sw +  elseif syn ==# 'cucumberFeature' || line =~# '^\s*Feature:' +    " line after feature heading +    return sw +  elseif syn ==# 'cucumberExamples' || line =~# '^\s*\%(Examples\|Scenarios\):' +    " line after examples heading +    return 3 * sw +  elseif syn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || line =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' +    " line after background, scenario or outline heading +    return 2 * sw +  elseif cline =~# '^\s*[@#]' && (nsyn == 'cucumberFeature' || nline =~# '^\s*Feature:' || indent(prevnonblank(v:lnum-1)) <= 0) +    " tag or comment before a feature heading +    return 0 +  elseif cline =~# '^\s*@' +    " other tags +    return sw +  elseif cline =~# '^\s*[#|]' && line =~# '^\s*|' +    " mid-table +    " preserve indent +    return indent(prevnonblank(v:lnum-1)) +  elseif cline =~# '^\s*|' && line =~# '^\s*[^|]' +    " first line of a table, relative indent +    return indent(prevnonblank(v:lnum-1)) + sw +  elseif cline =~# '^\s*[^|]' && line =~# '^\s*|' +    " line after a table, relative unindent +    return indent(prevnonblank(v:lnum-1)) - sw +  elseif cline =~# '^\s*#' && getline(v:lnum-1) =~ '^\s*$' && (nsyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || nline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):') +    " comments on scenarios +    return sw +  endif +  return indent(prevnonblank(v:lnum-1)) +endfunction + +" vim:set sts=2 sw=2: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'cucumber') == -1  " Vim indent file diff --git a/indent/cuda.vim b/indent/cuda.vim new file mode 100644 index 00000000..d120eda7 --- /dev/null +++ b/indent/cuda.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	CUDA +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2008 Nov 29 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" It's just like C indenting +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/d.vim b/indent/d.vim new file mode 100644 index 00000000..c44e7352 --- /dev/null +++ b/indent/d.vim @@ -0,0 +1,26 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file for the D programming language (version 0.137). +" +" Language:	D +" Maintainer:	Jason Mills<jmills@cs.mun.ca> +" Last Change:	2005 Nov 22 +" Version:	0.1 +" +" Please email me with bugs, comments, and suggestion. Put vim in the subject +" to ensure the email will not be marked has spam. +" + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +let b:did_indent = 1 + +" D indenting is a lot like the built-in C indenting. +setlocal cindent + +" vim: ts=8 noet + +endif diff --git a/indent/dictconf.vim b/indent/dictconf.vim new file mode 100644 index 00000000..193d8ba5 --- /dev/null +++ b/indent/dictconf.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             dict(1) configuration file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentkeys=0{,0},!^F,o,O cinwords= autoindent smartindent +setlocal nosmartindent +inoremap <buffer> # X# + +endif diff --git a/indent/dictdconf.vim b/indent/dictdconf.vim new file mode 100644 index 00000000..1aa5fd3e --- /dev/null +++ b/indent/dictdconf.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             dictd(8) configuration file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentkeys=0{,0},!^F,o,O cinwords= autoindent smartindent +setlocal nosmartindent +inoremap <buffer> # X# + +endif diff --git a/indent/docbk.vim b/indent/docbk.vim new file mode 100644 index 00000000..8a671f42 --- /dev/null +++ b/indent/docbk.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    	    DocBook Documentation Format +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-04-19 + +if exists("b:did_indent") +  finish +endif + +" Same as XML indenting for now. +runtime! indent/xml.vim + +if exists('*XmlIndentGet') +  setlocal indentexpr=XmlIndentGet(v:lnum,0) +endif + +endif diff --git a/indent/dtd.vim b/indent/dtd.vim new file mode 100644 index 00000000..eb2665b4 --- /dev/null +++ b/indent/dtd.vim @@ -0,0 +1,329 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    	    DTD (Document Type Definition for XML) +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2011-07-08 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal indentexpr=GetDTDIndent() +setlocal indentkeys=!^F,o,O,> +setlocal nosmartindent + +if exists("*GetDTDIndent") +  finish +endif + +" TODO: Needs to be adjusted to stop at [, <, and ]. +let s:token_pattern = '^[^[:space:]]\+' + +function s:lex1(input, start, ...) +  let pattern = a:0 > 0 ? a:1 : s:token_pattern +  let start = matchend(a:input, '^\_s*', a:start) +  if start == -1 +    return ["", a:start] +  endif +  let end = matchend(a:input, pattern, start) +  if end == -1 +    return ["", a:start] +  endif +  let token = strpart(a:input, start, end - start) +  return [token, end] +endfunction + +function s:lex(input, start, ...) +  let pattern = a:0 > 0 ? a:1 : s:token_pattern +  let info = s:lex1(a:input, a:start, pattern) +  while info[0] == '--' +    let info = s:lex1(a:input, info[1], pattern) +    while info[0] != "" && info[0] != '--' +      let info = s:lex1(a:input, info[1], pattern) +    endwhile +    if info[0] == "" +      return info +    endif +    let info = s:lex1(a:input, info[1], pattern) +  endwhile +  return info +endfunction + +function s:indent_to_innermost_parentheses(line, end) +  let token = '(' +  let end = a:end +  let parentheses = [end - 1] +  while token != "" +    let [token, end] = s:lex(a:line, end, '^\%([(),|]\|[A-Za-z0-9_-]\+\|#P\=CDATA\|%[A-Za-z0-9_-]\+;\)[?*+]\=') +    if token[0] == '(' +      call add(parentheses, end - 1) +    elseif token[0] == ')' +      if len(parentheses) == 1 +        return [-1, end] +      endif +      call remove(parentheses, -1) +    endif +  endwhile +  return [parentheses[-1] - strridx(a:line, "\n", parentheses[-1]), end] +endfunction + +" TODO: Line and end could be script global (think OO members). +function GetDTDIndent() +  if v:lnum == 1 +    return 0 +  endif +   +  " Begin by searching back for a <! that isn’t inside a comment. +  " From here, depending on what follows immediately after, parse to +  " where we’re at to determine what to do. +  if search('<!', 'bceW') == 0 +    return indent(v:lnum - 1) +  endif +  let lnum = line('.') +  let col = col('.') +  let indent = indent('.') +  let line = lnum == v:lnum ? getline(lnum) : join(getline(lnum, v:lnum - 1), "\n") + +  let [declaration, end] = s:lex1(line, col) +  if declaration == "" +    return indent + shiftwidth() +  elseif declaration == '--' +    " We’re looking at a comment.  Now, simply determine if the comment is +    " terminated or not.  If it isn’t, let Vim take care of that using +    " 'comments' and 'autoindent'. Otherwise, indent to the first lines level. +    while declaration != "" +      let [declaration, end] = s:lex(line, end) +      if declaration == "-->" +        return indent +      endif +    endwhile +    return -1 +  elseif declaration == 'ELEMENT' +    " Check for element name.  If none exists, indent one level. +    let [name, end] = s:lex(line, end) +    if name == "" +      return indent + shiftwidth() +    endif + +    " Check for token following element name.  This can be a specification of +    " whether the start or end tag may be omitted.  If nothing is found, indent +    " one level. +    let [token, end] = s:lex(line, end, '^\%([-O(]\|ANY\|EMPTY\)') +    let n = 0 +    while token =~ '[-O]' && n < 2 +      let [token, end] = s:lex(line, end, '^\%([-O(]\|ANY\|EMPTY\)') +      let n += 1 +    endwhile +    if token == "" +      return indent + shiftwidth() +    endif + +    " Next comes the content model.  If the token we’ve found isn’t a +    " parenthesis it must be either ANY, EMPTY or some random junk.  Either +    " way, we’re done indenting this element, so set it to that of the first +    " line so that the terminating “>†winds up having the same indention. +    if token != '(' +      return indent +    endif + +    " Now go through the content model.  We need to keep track of the nesting +    " of parentheses.  As soon as we hit 0 we’re done.  If that happens we must +    " have a complete content model.  Thus set indention to be the same as that +    " of the first line so that the terminating “>†winds up having the same +    " indention.  Otherwise, we’ll indent to the innermost parentheses not yet +    " matched. +    let [indent_of_innermost, end] = s:indent_to_innermost_parentheses(line, end) +    if indent_of_innermost != -1 +      return indent_of_innermost +    endif + +    " Finally, look for any additions and/or exceptions to the content model. +    " This is defined by a “+†or “-†followed by another content model +    " declaration. +    " TODO: Can the “-†be separated by whitespace from the “(â€? +    let seen = { '+(': 0, '-(': 0 } +    while 1 +      let [additions_exceptions, end] = s:lex(line, end, '^[+-](') +      if additions_exceptions != '+(' && additions_exceptions != '-(' +        let [token, end] = s:lex(line, end) +        if token == '>' +          return indent +        endif +        " TODO: Should use s:lex here on getline(v:lnum) and check for >. +        return getline(v:lnum) =~ '^\s*>' || count(values(seen), 0) == 0 ? indent : (indent + shiftwidth()) +      endif + +      " If we’ve seen an addition or exception already and this is of the same +      " kind, the user is writing a broken DTD.  Time to bail. +      if seen[additions_exceptions] +        return indent +      endif +      let seen[additions_exceptions] = 1 + +      let [indent_of_innermost, end] = s:indent_to_innermost_parentheses(line, end) +      if indent_of_innermost != -1 +        return indent_of_innermost +      endif +    endwhile +  elseif declaration == 'ATTLIST' +    " Check for element name.  If none exists, indent one level. +    let [name, end] = s:lex(line, end) +    if name == "" +      return indent + shiftwidth() +    endif + +    " Check for any number of attributes. +    while 1 +      " Check for attribute name.  If none exists, indent one level, unless the +      " current line is a lone “>â€, in which case we indent to the same level +      " as the first line.  Otherwise, if the attribute name is “>â€, we have +      " actually hit the end of the attribute list, in which case we indent to +      " the same level as the first line. +      let [name, end] = s:lex(line, end) +      if name == "" +        " TODO: Should use s:lex here on getline(v:lnum) and check for >. +        return getline(v:lnum) =~ '^\s*>' ? indent : (indent + shiftwidth()) +      elseif name == ">" +        return indent +      endif + +      " Check for attribute value declaration.  If none exists, indent two +      " levels.  Otherwise, if it’s an enumerated value, check for nested +      " parentheses and indent to the innermost one if we don’t reach the end +      " of the listc.  Otherwise, just continue with looking for the default +      " attribute value. +      " TODO: Do validation of keywords +      " (CDATA|NMTOKEN|NMTOKENS|ID|IDREF|IDREFS|ENTITY|ENTITIES)? +      let [value, end] = s:lex(line, end, '^\%((\|[^[:space:]]\+\)') +      if value == "" +        return indent + shiftwidth() * 2 +      elseif value == 'NOTATION' +        " If this is a enumerated value based on notations, read another token +        " for the actual value.  If it doesn’t exist, indent three levels. +        " TODO: If validating according to above, value must be equal to '('. +        let [value, end] = s:lex(line, end, '^\%((\|[^[:space:]]\+\)') +        if value == "" +          return indent + shiftwidth() * 3 +        endif +      endif + +      if value == '(' +        let [indent_of_innermost, end] = s:indent_to_innermost_parentheses(line, end) +        if indent_of_innermost != -1 +          return indent_of_innermost +        endif +      endif + +      " Finally look for the attribute’s default value.  If non exists, indent +      " two levels. +      let [default, end] = s:lex(line, end, '^\%("\_[^"]*"\|#\(REQUIRED\|IMPLIED\|FIXED\)\)') +      if default == "" +        return indent + shiftwidth() * 2 +      elseif default == '#FIXED' +        " We need to look for the fixed value.  If non exists, indent three +        " levels. +        let [default, end] = s:lex(line, end, '^"\_[^"]*"') +        if default == "" +          return indent + shiftwidth() * 3 +        endif +      endif +    endwhile +  elseif declaration == 'ENTITY' +    " Check for entity name.  If none exists, indent one level.  Otherwise, if +    " the name actually turns out to be a percent sign, “%â€, this is a +    " parameter entity.  Read another token to determine the entity name and, +    " again, if none exists, indent one level. +    let [name, end] = s:lex(line, end) +    if name == "" +      return indent + shiftwidth() +    elseif name == '%' +      let [name, end] = s:lex(line, end) +      if name == "" +        return indent + shiftwidth() +      endif +    endif + +    " Now check for the entity value.  If none exists, indent one level.  If it +    " does exist, indent to same level as first line, as we’re now done with +    " this entity. +    " +    " The entity value can be a string in single or double quotes (no escapes +    " to worry about, as entities are used instead).  However, it can also be +    " that this is an external unparsed entity.  In that case we have to look +    " further for (possibly) a public ID and an URI followed by the NDATA +    " keyword and the actual notation name.  For the public ID and URI, indent +    " two levels, if they don’t exist.  If the NDATA keyword doesn’t exist, +    " indent one level.  Otherwise, if the actual notation name doesn’t exist, +    " indent two level.  If it does, indent to same level as first line, as +    " we’re now done with this entity. +    let [value, end] = s:lex(line, end) +    if value == "" +      return indent + shiftwidth() +    elseif value == 'SYSTEM' || value == 'PUBLIC' +      let [quoted_string, end] = s:lex(line, end, '\%("[^"]\+"\|''[^'']\+''\)') +      if quoted_string == "" +        return indent + shiftwidth() * 2 +      endif + +      if value == 'PUBLIC' +        let [quoted_string, end] = s:lex(line, end, '\%("[^"]\+"\|''[^'']\+''\)') +        if quoted_string == "" +          return indent + shiftwidth() * 2 +        endif +      endif + +      let [ndata, end] = s:lex(line, end) +      if ndata == "" +        return indent + shiftwidth() +      endif + +      let [name, end] = s:lex(line, end) +      return name == "" ? (indent + shiftwidth() * 2) : indent +    else +      return indent +    endif +  elseif declaration == 'NOTATION' +    " Check for notation name.  If none exists, indent one level. +    let [name, end] = s:lex(line, end) +    if name == "" +      return indent + shiftwidth() +    endif + +    " Now check for the external ID.  If none exists, indent one level. +    let [id, end] = s:lex(line, end) +    if id == "" +      return indent + shiftwidth() +    elseif id == 'SYSTEM' || id == 'PUBLIC' +      let [quoted_string, end] = s:lex(line, end, '\%("[^"]\+"\|''[^'']\+''\)') +      if quoted_string == "" +        return indent + shiftwidth() * 2 +      endif + +      if id == 'PUBLIC' +        let [quoted_string, end] = s:lex(line, end, '\%("[^"]\+"\|''[^'']\+''\|>\)') +        if quoted_string == "" +          " TODO: Should use s:lex here on getline(v:lnum) and check for >. +          return getline(v:lnum) =~ '^\s*>' ? indent : (indent + shiftwidth() * 2) +        elseif quoted_string == '>' +          return indent +        endif +      endif +    endif + +    return indent +  endif + +  " TODO: Processing directives could be indented I suppose.  But perhaps it’s +  " just as well to let the user decide how to indent them (perhaps extending +  " this function to include proper support for whatever processing directive +  " language they want to use). + +  " Conditional sections are simply passed along to let Vim decide what to do +  " (and hence the user). +  return -1 +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/dtrace.vim b/indent/dtrace.vim new file mode 100644 index 00000000..3d9d4e07 --- /dev/null +++ b/indent/dtrace.vim @@ -0,0 +1,21 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language: D script as described in "Solaris Dynamic Tracing Guide", +"           http://docs.sun.com/app/docs/doc/817-6223 +" Last Change: 2008/03/20 +" Version: 1.2 +" Maintainer: Nicolas Weber <nicolasweber@gmx.de> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +" Built-in C indenting works nicely for dtrace. +setlocal cindent + +let b:undo_indent = "setl cin<" + +endif diff --git a/indent/dylan.vim b/indent/dylan.vim new file mode 100644 index 00000000..4858ea84 --- /dev/null +++ b/indent/dylan.vim @@ -0,0 +1,94 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Dylan +" Version:	0.01 +" Last Change:	2017 Jun 13 +" Maintainer:	Brent A. Fulgham <bfulgham@debian.org> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentkeys+==~begin,=~block,=~case,=~cleanup,=~define,=~end,=~else,=~elseif,=~exception,=~for,=~finally,=~if,=~otherwise,=~select,=~unless,=~while + +" Define the appropriate indent function but only once +setlocal indentexpr=DylanGetIndent() +if exists("*DylanGetIndent") +  finish +endif + +function DylanGetIndent() +  " Get the line to be indented +  let cline = getline(v:lnum) + +  " Don't reindent comments on first column +  if cline =~ '^/\[/\*]' +    return 0 +  endif + +  "Find the previous non-blank line +  let lnum = prevnonblank(v:lnum - 1) +  "Use zero indent at the top of the file +  if lnum == 0 +    return 0 +  endif + +  let prevline=getline(lnum) +  let ind = indent(lnum) +  let chg = 0 + +  " If previous line was a comment, use its indent +  if prevline =~ '^\s*//' +    return ind +  endif + +  " If previous line was a 'define', indent +  if prevline =~? '\(^\s*\(begin\|block\|case\|define\|else\|elseif\|for\|finally\|if\|select\|unless\|while\)\|\s*\S*\s*=>$\)' +    let chg = shiftwidth() +  " local methods indent the shift-width, plus 6 for the 'local' +  elseif prevline =~? '^\s*local' +    let chg = shiftwidth() + 6 +  " If previous line was a let with no closing semicolon, indent +  elseif prevline =~? '^\s*let.*[^;]\s*$' +    let chg = shiftwidth() +  " If previous line opened a parenthesis, and did not close it, indent +  elseif prevline =~ '^.*(\s*[^)]*\((.*)\)*[^)]*$' +    return = match( prevline, '(.*\((.*)\|[^)]\)*.*$') + 1 +  "elseif prevline =~ '^.*(\s*[^)]*\((.*)\)*[^)]*$' +  elseif prevline =~ '^[^(]*)\s*$' +    " This line closes a parenthesis.  Find opening +    let curr_line = prevnonblank(lnum - 1) +    while curr_line >= 0 +      let str = getline(curr_line) +      if str !~ '^.*(\s*[^)]*\((.*)\)*[^)]*$' +	let curr_line = prevnonblank(curr_line - 1) +      else +	break +      endif +    endwhile +    if curr_line < 0 +      return -1 +    endif +    let ind = indent(curr_line) +    " Although we found the closing parenthesis, make sure this +    " line doesn't start with an indentable command: +    let curr_str = getline(curr_line) +    if curr_str =~? '^\s*\(begin\|block\|case\|define\|else\|elseif\|for\|finally\|if\|select\|unless\|while\)' +      let chg = shiftwidth() +    endif +  endif + +  " If a line starts with end, un-indent (even if we just indented!) +  if cline =~? '^\s*\(cleanup\|end\|else\|elseif\|exception\|finally\|otherwise\)' +    let chg = chg - shiftwidth() +  endif + +  return ind + chg +endfunction + +" vim:sw=2 tw=130 + +endif diff --git a/indent/eiffel.vim b/indent/eiffel.vim new file mode 100644 index 00000000..d5967022 --- /dev/null +++ b/indent/eiffel.vim @@ -0,0 +1,119 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Eiffel +" Maintainer:	Jocelyn Fiat <jfiat@eiffel.com> +" Previous-Maintainer:	David Clarke <gadicath@dishevelled.net> +" Contributions from: Takuya Fujiwara +" Contributions from: Thilo Six +" $Date: 2017/03/08 06:00:00 $ +" $Revision: 1.4 $ +" URL: https://github.com/eiffelhub/vim-eiffel + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetEiffelIndent() +setlocal nolisp +setlocal nosmartindent +setlocal nocindent +setlocal autoindent +setlocal comments=:-- +setlocal indentkeys+==end,=else,=ensure,=require,=check,=loop,=until +setlocal indentkeys+==creation,=feature,=inherit,=class,=is,=redefine,=rename,=variant +setlocal indentkeys+==invariant,=do,=local,=export + +let b:undo_indent = "setl smartindent< indentkeys< indentexpr< autoindent< comments< " + +" Define some stuff +" keywords grouped by indenting +let s:trust_user_indent = '\(+\)\(\s*\(--\).*\)\=$' +let s:relative_indent = '^\s*\(deferred\|class\|feature\|creation\|inherit\|loop\|from\|across\|until\|if\|else\|elseif\|ensure\|require\|check\|do\|local\|invariant\|variant\|rename\|redefine\|do\|export\)\>' +let s:outdent = '^\s*\(else\|invariant\|variant\|do\|require\|until\|loop\|local\)\>' +let s:no_indent = '^\s*\(class\|feature\|creation\|inherit\)\>' +let s:single_dent = '^[^-]\+[[:alnum:]]\+ is\(\s*\(--\).*\)\=$' +let s:inheritance_dent = '\s*\(redefine\|rename\|export\)\>' + + +" Only define the function once. +if exists("*GetEiffelIndent") +  finish +endif + +let s:keepcpo= &cpo +set cpo&vim + +function GetEiffelIndent() + +  " Eiffel Class indenting +  " +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  " trust the user's indenting +  if getline(lnum) =~ s:trust_user_indent +    return -1 +  endif + +  " Add a 'shiftwidth' after lines that start with an indent word +  let ind = indent(lnum) +  if getline(lnum) =~ s:relative_indent +    let ind = ind + shiftwidth() +  endif + +  " Indent to single indent +  if getline(v:lnum) =~ s:single_dent && getline(v:lnum) !~ s:relative_indent +	   \ && getline(v:lnum) !~ '\s*\<\(and\|or\|implies\)\>' +     let ind = shiftwidth() +  endif + +  " Indent to double indent +  if getline(v:lnum) =~ s:inheritance_dent +     let ind = 2 * shiftwidth() +  endif + +  " Indent line after the first line of the function definition +  if getline(lnum) =~ s:single_dent +     let ind = ind + shiftwidth() +  endif + +  " The following should always be at the start of a line, no indenting +  if getline(v:lnum) =~ s:no_indent +     let ind = 0 +  endif + +  " Subtract a 'shiftwidth', if this isn't the first thing after the 'is' +  " or first thing after the 'do' +  if getline(v:lnum) =~ s:outdent && getline(v:lnum - 1) !~ s:single_dent +	\ && getline(v:lnum - 1) !~ '^\s*do\>' +    let ind = ind - shiftwidth() +  endif + +  " Subtract a shiftwidth for end statements +  if getline(v:lnum) =~ '^\s*end\>' +    let ind = ind - shiftwidth() +  endif + +  " set indent of zero end statements that are at an indent of 3, this should +  " only ever be the class's end. +  if getline(v:lnum) =~ '^\s*end\>' && ind == shiftwidth() +    let ind = 0 +  endif + +  return ind +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 + +endif diff --git a/indent/erlang.vim b/indent/erlang.vim index 64525bbd..efd4ba47 100644 --- a/indent/erlang.vim +++ b/indent/erlang.vim @@ -1,3 +1,1397 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     Erlang (http://www.erlang.org) +" Author:       Csaba Hoch <csaba.hoch@gmail.com> +" Contributors: Edwin Fine <efine145_nospam01 at usa dot net> +"               Pawel 'kTT' Salata <rockplayer.pl@gmail.com> +"               Ricardo Catalinas Jiménez <jimenezrick@gmail.com> +" Last Update:  2013-Jul-21 +" License:      Vim license +" URL:          https://github.com/hcs42/vim-erlang + +" Note About Usage: +"   This indentation script works best with the Erlang syntax file created by +"   KreÄ…imir Marľić (Kresimir Marzic) and maintained by Csaba Hoch. + +" Notes About Implementation: +" +" - LTI = Line to indent. +" - The index of the first line is 1, but the index of the first column is 0. + + +" Initialization {{{1 +" ============== + +" Only load this indent file when no other was loaded +" Vim 7 or later is needed +if exists("b:did_indent") || version < 700 +  finish +else +  let b:did_indent = 1 +endif + +setlocal indentexpr=ErlangIndent() +setlocal indentkeys+=0=end,0=of,0=catch,0=after,0=when,0=),0=],0=},0=>> + +" Only define the functions once +if exists("*ErlangIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Logging library {{{1 +" =============== + +" Purpose: +"   Logs the given string using the ErlangIndentLog function if it exists. +" Parameters: +"   s: string +function! s:Log(s) +  if exists("*ErlangIndentLog") +    call ErlangIndentLog(a:s) +  endif +endfunction + +" Line tokenizer library {{{1 +" ====================== + +" Indtokens are "indentation tokens". + +" Purpose: +"   Calculate the new virtual column after the given segment of a line. +" Parameters: +"   line: string +"   first_index: integer -- the index of the first character of the segment +"   last_index: integer -- the index of the last character of the segment +"   vcol: integer -- the virtual column of the first character of the token +"   tabstop: integer -- the value of the 'tabstop' option to be used +" Returns: +"   vcol: integer +" Example: +"   " index:    0 12 34567 +"   " vcol:     0 45 89 +"   s:CalcVCol("\t'\tx', b", 1, 4, 4)  -> 10 +function! s:CalcVCol(line, first_index, last_index, vcol, tabstop) + +  " We copy the relevent segment of the line, otherwise if the line were +  " e.g. `"\t", term` then the else branch below would consume the `", term` +  " part at once. +  let line = a:line[a:first_index : a:last_index] + +  let i = 0 +  let last_index = a:last_index - a:first_index +  let vcol = a:vcol + +  while 0 <= i && i <= last_index + +    if line[i] ==# "\t" +      " Example (when tabstop == 4): +      " +      " vcol + tab -> next_vcol +      " 0 + tab -> 4 +      " 1 + tab -> 4 +      " 2 + tab -> 4 +      " 3 + tab -> 4 +      " 4 + tab -> 8 +      " +      " next_i - i == the number of tabs +      let next_i = matchend(line, '\t*', i + 1) +      let vcol = (vcol / a:tabstop + (next_i - i)) * a:tabstop +      call s:Log('new vcol after tab: '. vcol) +    else +      let next_i = matchend(line, '[^\t]*', i + 1) +      let vcol += next_i - i +      call s:Log('new vcol after other: '. vcol) +    endif +    let i = next_i +  endwhile + +  return vcol +endfunction + +" Purpose: +"   Go through the whole line and return the tokens in the line. +" Parameters: +"   line: string -- the line to be examined +"   string_continuation: bool +"   atom_continuation: bool +" Returns: +"   indtokens = [indtoken] +"   indtoken = [token, vcol, col] +"   token = string (examples: 'begin', '<variable>', '}') +"   vcol = integer (the virtual column of the first character of the token) +"   col = integer +function! s:GetTokensFromLine(line, string_continuation, atom_continuation, +                             \tabstop) + +  let linelen = strlen(a:line) " The length of the line +  let i = 0 " The index of the current character in the line +  let vcol = 0 " The virtual column of the current character +  let indtokens = [] + +  if a:string_continuation +    let i = matchend(a:line, '^\%([^"\\]\|\\.\)*"', 0) +    if i ==# -1 +      call s:Log('    Whole line is string continuation -> ignore') +      return [] +    else +      let vcol = s:CalcVCol(a:line, 0, i - 1, 0, a:tabstop) +      call add(indtokens, ['<string_end>', vcol, i]) +    endif +  elseif a:atom_continuation +    let i = matchend(a:line, "^\\%([^'\\\\]\\|\\\\.\\)*'", 0) +    if i ==# -1 +      call s:Log('    Whole line is quoted atom continuation -> ignore') +      return [] +    else +      let vcol = s:CalcVCol(a:line, 0, i - 1, 0, a:tabstop) +      call add(indtokens, ['<quoted_atom_end>', vcol, i]) +    endif +  endif + +  while 0 <= i && i < linelen + +    let next_vcol = '' + +    " Spaces +    if a:line[i] ==# ' ' +      let next_i = matchend(a:line, ' *', i + 1) + +    " Tabs +    elseif a:line[i] ==# "\t" +      let next_i = matchend(a:line, '\t*', i + 1) + +      " See example in s:CalcVCol +      let next_vcol = (vcol / a:tabstop + (next_i - i)) * a:tabstop + +    " Comment +    elseif a:line[i] ==# '%' +      let next_i = linelen + +    " String token: "..." +    elseif a:line[i] ==# '"' +      let next_i = matchend(a:line, '\%([^"\\]\|\\.\)*"', i + 1) +      if next_i ==# -1 +        call add(indtokens, ['<string_start>', vcol, i]) +      else +        let next_vcol = s:CalcVCol(a:line, i, next_i - 1, vcol, a:tabstop) +        call add(indtokens, ['<string>', vcol, i]) +      endif + +    " Quoted atom token: '...' +    elseif a:line[i] ==# "'" +      let next_i = matchend(a:line, "\\%([^'\\\\]\\|\\\\.\\)*'", i + 1) +      if next_i ==# -1 +        call add(indtokens, ['<quoted_atom_start>', vcol, i]) +      else +        let next_vcol = s:CalcVCol(a:line, i, next_i - 1, vcol, a:tabstop) +        call add(indtokens, ['<quoted_atom>', vcol, i]) +      endif + +    " Keyword or atom or variable token or number +    elseif a:line[i] =~# '[a-zA-Z_@0-9]' +      let next_i = matchend(a:line, +                           \'[[:alnum:]_@:]*\%(\s*#\s*[[:alnum:]_@:]*\)\=', +                           \i + 1) +      call add(indtokens, [a:line[(i):(next_i - 1)], vcol, i]) + +    " Character token: $<char> (as in: $a) +    elseif a:line[i] ==# '$' +      call add(indtokens, ['$.', vcol, i]) +      let next_i = i + 2 + +    " Dot token: . +    elseif a:line[i] ==# '.' + +      let next_i = i + 1 + +      if i + 1 ==# linelen || a:line[i + 1] =~# '[[:blank:]%]' +        " End of clause token: . (as in: f() -> ok.) +        call add(indtokens, ['<end_of_clause>', vcol, i]) + +      else +        " Possibilities: +        " - Dot token in float: . (as in: 3.14) +        " - Dot token in record: . (as in: #myrec.myfield) +        call add(indtokens, ['.', vcol, i]) +      endif + +    " Equal sign +    elseif a:line[i] ==# '=' +      " This is handled separately so that "=<<" will be parsed as +      " ['=', '<<'] instead of ['=<', '<']. Although Erlang parses it +      " currently in the latter way, that may be fixed some day. +      call add(indtokens, [a:line[i], vcol, i]) +      let next_i = i + 1 + +    " Three-character tokens +    elseif i + 1 < linelen && +         \ index(['=:=', '=/='], a:line[i : i + 1]) != -1 +      call add(indtokens, [a:line[i : i + 1], vcol, i]) +      let next_i = i + 2 + +    " Two-character tokens +    elseif i + 1 < linelen && +         \ index(['->', '<<', '>>', '||', '==', '/=', '=<', '>=', '++', '--', +         \        '::'], +         \       a:line[i : i + 1]) != -1 +      call add(indtokens, [a:line[i : i + 1], vcol, i]) +      let next_i = i + 2 + +    " Other character: , ; < > ( ) [ ] { } # + - * / : ? = ! | +    else +      call add(indtokens, [a:line[i], vcol, i]) +      let next_i = i + 1 + +    endif + +    if next_vcol ==# '' +      let vcol += next_i - i +    else +      let vcol = next_vcol +    endif + +    let i = next_i + +  endwhile + +  return indtokens + +endfunction + +" TODO: doc, handle "not found" case +function! s:GetIndtokenAtCol(indtokens, col) +  let i = 0 +  while i < len(a:indtokens) +    if a:indtokens[i][2] ==# a:col +      return [1, i] +    elseif a:indtokens[i][2] > a:col +      return [0, s:IndentError('No token at col ' . a:col . ', ' . +                              \'indtokens = ' . string(a:indtokens), +                              \'', '')] +    endif +    let i += 1 +  endwhile +  return [0, s:IndentError('No token at col ' . a:col . ', ' . +                           \'indtokens = ' . string(a:indtokens), +                           \'', '')] +endfunction + +" Stack library {{{1 +" ============= + +" Purpose: +"   Push a token onto the parser's stack. +" Parameters: +"   stack: [token] +"   token: string +function! s:Push(stack, token) +  call s:Log('    Stack Push: "' . a:token . '" into ' . string(a:stack)) +  call insert(a:stack, a:token) +endfunction + +" Purpose: +"   Pop a token from the parser's stack. +" Parameters: +"   stack: [token] +"   token: string +" Returns: +"   token: string -- the removed element +function! s:Pop(stack) +  let head = remove(a:stack, 0) +  call s:Log('    Stack Pop: "' . head . '" from ' . string(a:stack)) +  return head +endfunction + +" Library for accessing and storing tokenized lines {{{1 +" ================================================= + +" The Erlang token cache: an `lnum -> indtokens` dictionary that stores the +" tokenized lines. +let s:all_tokens = {} +let s:file_name = '' +let s:last_changedtick = -1 + +" Purpose: +"   Clear the Erlang token cache if we have a different file or the file has +"   been changed since the last indentation. +function! s:ClearTokenCacheIfNeeded() +  let file_name = expand('%:p') +  if file_name != s:file_name || +   \ b:changedtick != s:last_changedtick +    let s:file_name = file_name +    let s:last_changedtick = b:changedtick +    let s:all_tokens = {} +  endif +endfunction + +" Purpose: +"   Return the tokens of line `lnum`, if that line is not empty. If it is +"   empty, find the first non-empty line in the given `direction` and return +"   the tokens of that line. +" Parameters: +"   lnum: integer +"   direction: 'up' | 'down' +" Returns: +"   result: [] -- the result is an empty list if we hit the beginning or end +"                  of the file +"           | [lnum, indtokens] +"   lnum: integer -- the index of the non-empty line that was found and +"                    tokenized +"   indtokens: [indtoken] -- the tokens of line `lnum` +function! s:TokenizeLine(lnum, direction) + +  call s:Log('Tokenizing starts from line ' . a:lnum) +  if a:direction ==# 'up' +    let lnum = prevnonblank(a:lnum) +  else " a:direction ==# 'down' +    let lnum = nextnonblank(a:lnum) +  endif + +  " We hit the beginning or end of the file +  if lnum ==# 0 +    let indtokens = [] +    call s:Log('  We hit the beginning or end of the file.') + +    " The line has already been parsed +  elseif has_key(s:all_tokens, lnum) +    let indtokens = s:all_tokens[lnum] +    call s:Log('Cached line ' . lnum . ': ' . getline(lnum)) +    call s:Log("  Tokens in the line:\n    - " . join(indtokens, "\n    - ")) + +    " The line should be parsed now +  else + +    " Parse the line +    let line = getline(lnum) +    let string_continuation = s:IsLineStringContinuation(lnum) +    let atom_continuation = s:IsLineAtomContinuation(lnum) +    let indtokens = s:GetTokensFromLine(line, string_continuation, +                                       \atom_continuation, &tabstop) +    let s:all_tokens[lnum] = indtokens +    call s:Log('Tokenizing line ' . lnum . ': ' . line) +    call s:Log("  Tokens in the line:\n    - " . join(indtokens, "\n    - ")) + +  endif + +  return [lnum, indtokens] +endfunction + +" Purpose: +"   As a helper function for PrevIndToken and NextIndToken, the FindIndToken +"   function finds the first line with at least one token in the given +"   direction. +" Parameters: +"   lnum: integer +"   direction: 'up' | 'down' +" Returns: +"   result: [] -- the result is an empty list if we hit the beginning or end +"                  of the file +"           | indtoken +function! s:FindIndToken(lnum, dir) +  let lnum = a:lnum +  while 1 +    let lnum += (a:dir ==# 'up' ? -1 : 1) +    let [lnum, indtokens] = s:TokenizeLine(lnum, a:dir) +    if lnum ==# 0 +      " We hit the beginning or end of the file +      return [] +    elseif !empty(indtokens) +      return indtokens[a:dir ==# 'up' ? -1 : 0] +    endif +  endwhile +endfunction + +" Purpose: +"   Find the token that directly precedes the given token. +" Parameters: +"   lnum: integer -- the line of the given token +"   i: the index of the given token within line `lnum` +" Returns: +"   result = [] -- the result is an empty list if the given token is the first +"                  token of the file +"          | indtoken +function! s:PrevIndToken(lnum, i) +  call s:Log('    PrevIndToken called: lnum=' . a:lnum . ', i =' . a:i) + +  " If the current line has a previous token, return that +  if a:i > 0 +    return s:all_tokens[a:lnum][a:i - 1] +  else +    return s:FindIndToken(a:lnum, 'up') +  endif +endfunction + +" Purpose: +"   Find the token that directly succeeds the given token. +" Parameters: +"   lnum: integer -- the line of the given token +"   i: the index of the given token within line `lnum` +" Returns: +"   result = [] -- the result is an empty list if the given token is the last +"                  token of the file +"          | indtoken +function! s:NextIndToken(lnum, i) +  call s:Log('    NextIndToken called: lnum=' . a:lnum . ', i =' . a:i) + +  " If the current line has a next token, return that +  if len(s:all_tokens[a:lnum]) > a:i + 1 +    return s:all_tokens[a:lnum][a:i + 1] +  else +    return s:FindIndToken(a:lnum, 'down') +  endif +endfunction + +" ErlangCalcIndent helper functions {{{1 +" ================================= + +" Purpose: +"   This function is called when the parser encounters a syntax error. +" +"   If we encounter a syntax error, we return +"   g:erlang_unexpected_token_indent, which is -1 by default. This means that +"   the indentation of the LTI will not be changed. +" Parameter: +"   msg: string +"   token: string +"   stack: [token] +" Returns: +"   indent: integer +function! s:IndentError(msg, token, stack) +  call s:Log('Indent error: ' . a:msg . ' -> return') +  call s:Log('  Token = ' . a:token . ', ' . +            \'  stack = ' . string(a:stack)) +  return g:erlang_unexpected_token_indent +endfunction + +" Purpose: +"   This function is called when the parser encounters an unexpected token, +"   and the parser will return the number given back by UnexpectedToken. +" +"   If we encounter an unexpected token, we return +"   g:erlang_unexpected_token_indent, which is -1 by default. This means that +"   the indentation of the LTI will not be changed. +" Parameter: +"   token: string +"   stack: [token] +" Returns: +"   indent: integer +function! s:UnexpectedToken(token, stack) +  call s:Log('    Unexpected token ' . a:token . ', stack = ' . +            \string(a:stack) . ' -> return') +  return g:erlang_unexpected_token_indent +endfunction + +if !exists('g:erlang_unexpected_token_indent') +  let g:erlang_unexpected_token_indent = -1 +endif + +" Purpose: +"   Return whether the given line starts with a string continuation. +" Parameter: +"   lnum: integer +" Returns: +"   result: bool +" Example: +"   f() ->           % IsLineStringContinuation = false +"       "This is a   % IsLineStringContinuation = false +"       multiline    % IsLineStringContinuation = true +"       string".     % IsLineStringContinuation = true +function! s:IsLineStringContinuation(lnum) +  if has('syntax_items') +    return synIDattr(synID(a:lnum, 1, 0), 'name') =~# '^erlangString' +  else +    return 0 +  endif +endfunction + +" Purpose: +"   Return whether the given line starts with an atom continuation. +" Parameter: +"   lnum: integer +" Returns: +"   result: bool +" Example: +"   'function with   % IsLineAtomContinuation = true, but should be false +"   weird name'() -> % IsLineAtomContinuation = true +"       ok.          % IsLineAtomContinuation = false +function! s:IsLineAtomContinuation(lnum) +  if has('syntax_items') +    return synIDattr(synID(a:lnum, 1, 0), 'name') =~# '^erlangQuotedAtom' +  else +    return 0 +  endif +endfunction + +" Purpose: +"   Return whether the 'catch' token (which should be the `i`th token in line +"   `lnum`) is standalone or part of a try-catch block, based on the preceding +"   token. +" Parameters: +"   lnum: integer +"   i: integer +" Return: +"   is_standalone: bool +function! s:IsCatchStandalone(lnum, i) +  call s:Log('    IsCatchStandalone called: lnum=' . a:lnum . ', i=' . a:i) +  let prev_indtoken = s:PrevIndToken(a:lnum, a:i) + +  " If we hit the beginning of the file, it is not a catch in a try block +  if prev_indtoken == [] +    return 1 +  endif + +  let prev_token = prev_indtoken[0] + +  if prev_token =~# '[A-Z_@0-9]' +    let is_standalone = 0 +  elseif prev_token =~# '[a-z]' +    if index(['after', 'and', 'andalso', 'band', 'begin', 'bnot', 'bor', 'bsl', +            \ 'bsr', 'bxor', 'case', 'catch', 'div', 'not', 'or', 'orelse', +            \ 'rem', 'try', 'xor'], prev_token) != -1 +      " If catch is after these keywords, it is standalone +      let is_standalone = 1 +    else +      " If catch is after another keyword (e.g. 'end') or an atom, it is +      " part of try-catch. +      " +      " Keywords: +      " - may precede 'catch': end +      " - may not precede 'catch': fun if of receive when +      " - unused: cond let query +      let is_standalone = 0 +    endif +  elseif index([')', ']', '}', '<string>', '<string_end>', '<quoted_atom>', +              \ '<quoted_atom_end>', '$.'], prev_token) != -1 +    let is_standalone = 0 +  else +    " This 'else' branch includes the following tokens: +    "   -> == /= =< < >= > =:= =/= + - * / ++ -- :: < > ; ( [ { ? = ! . | +    let is_standalone = 1 +  endif + +  call s:Log('   "catch" preceded by "' . prev_token  . '" -> catch ' . +            \(is_standalone ? 'is standalone' : 'belongs to try-catch')) +  return is_standalone + +endfunction + +" Purpose: +"   This function is called when a begin-type element ('begin', 'case', +"   '[', '<<', etc.) is found. It asks the caller to return if the stack +" Parameters: +"   stack: [token] +"   token: string +"   curr_vcol: integer +"   stored_vcol: integer +"   sw: integer -- number of spaces to be used after the begin element as +"                  indentation +" Returns: +"   result: [should_return, indent] +"   should_return: bool -- if true, the caller should return `indent` to Vim +"   indent -- integer +function! s:BeginElementFoundIfEmpty(stack, token, curr_vcol, stored_vcol, sw) +  if empty(a:stack) +    if a:stored_vcol ==# -1 +      call s:Log('    "' . a:token . '" directly preceeds LTI -> return') +      return [1, a:curr_vcol + a:sw] +    else +      call s:Log('    "' . a:token . +                \'" token (whose expression includes LTI) found -> return') +      return [1, a:stored_vcol] +    endif +  else +    return [0, 0] +  endif +endfunction + +" Purpose: +"   This function is called when a begin-type element ('begin', 'case', '[', +"   '<<', etc.) is found, and in some cases when 'after' and 'when' is found. +"   It asks the caller to return if the stack is already empty. +" Parameters: +"   stack: [token] +"   token: string +"   curr_vcol: integer +"   stored_vcol: integer +"   end_token: end token that belongs to the begin element found (e.g. if the +"              begin element is 'begin', the end token is 'end') +"   sw: integer -- number of spaces to be used after the begin element as +"                  indentation +" Returns: +"   result: [should_return, indent] +"   should_return: bool -- if true, the caller should return `indent` to Vim +"   indent -- integer +function! s:BeginElementFound(stack, token, curr_vcol, stored_vcol, end_token, sw) + +  " Return 'return' if the stack is empty +  let [ret, res] = s:BeginElementFoundIfEmpty(a:stack, a:token, a:curr_vcol, +                                             \a:stored_vcol, a:sw) +  if ret | return [ret, res] | endif + +  if a:stack[0] ==# a:end_token +    call s:Log('    "' . a:token . '" pops "' . a:end_token . '"') +    call s:Pop(a:stack) +    if !empty(a:stack) && a:stack[0] ==# 'align_to_begin_element' +      call s:Pop(a:stack) +      if empty(a:stack) +        return [1, a:curr_vcol] +      else +        return [1, s:UnexpectedToken(a:token, a:stack)] +      endif +    else +      return [0, 0] +    endif +  else +    return [1, s:UnexpectedToken(a:token, a:stack)] +  endif +endfunction + +" Purpose: +"   This function is called when we hit the beginning of a file or an +"   end-of-clause token -- i.e. when we found the beginning of the current +"   clause. +" +"   If the stack contains an '->' or 'when', this means that we can return +"   now, since we were looking for the beginning of the clause. +" Parameters: +"   stack: [token] +"   token: string +"   stored_vcol: integer +" Returns: +"   result: [should_return, indent] +"   should_return: bool -- if true, the caller should return `indent` to Vim +"   indent -- integer +function! s:BeginningOfClauseFound(stack, token, stored_vcol) +  if !empty(a:stack) && a:stack[0] ==# 'when' +    call s:Log('    BeginningOfClauseFound: "when" found in stack') +    call s:Pop(a:stack) +    if empty(a:stack) +      call s:Log('    Stack is ["when"], so LTI is in a guard -> return') +      return [1, a:stored_vcol + shiftwidth() + 2] +    else +      return [1, s:UnexpectedToken(a:token, a:stack)] +    endif +  elseif !empty(a:stack) && a:stack[0] ==# '->' +    call s:Log('    BeginningOfClauseFound: "->" found in stack') +    call s:Pop(a:stack) +    if empty(a:stack) +      call s:Log('    Stack is ["->"], so LTI is in function body -> return') +      return [1, a:stored_vcol + shiftwidth()] +    elseif a:stack[0] ==# ';' +      call s:Pop(a:stack) +      if empty(a:stack) +        call s:Log('    Stack is ["->", ";"], so LTI is in a function head ' . +                  \'-> return') +        return [0, a:stored_vcol] +      else +        return [1, s:UnexpectedToken(a:token, a:stack)] +      endif +    else +      return [1, s:UnexpectedToken(a:token, a:stack)] +    endif +  else +    return [0, 0] +  endif +endfunction + +let g:erlang_indent_searchpair_timeout = 2000 + +" TODO +function! s:SearchPair(lnum, curr_col, start, middle, end) +  call cursor(a:lnum, a:curr_col + 1) +  let [lnum_new, col1_new] =  +      \searchpairpos(a:start, a:middle, a:end, 'bW', +                    \'synIDattr(synID(line("."), col("."), 0), "name") ' . +                    \'=~? "string\\|quotedatom\\|todo\\|comment\\|' .  +                    \'erlangmodifier"', +                    \0, g:erlang_indent_searchpair_timeout) +  return [lnum_new, col1_new - 1] +endfunction + +function! s:SearchEndPair(lnum, curr_col) +  return s:SearchPair( +         \ a:lnum, a:curr_col, +         \ '\C\<\%(case\|try\|begin\|receive\|if\)\>\|' . +         \ '\<fun\>\%(\s\|\n\|%.*$\)*(', +         \ '', +         \ '\<end\>') +endfunction + +" ErlangCalcIndent {{{1 +" ================ + +" Purpose: +"   Calculate the indentation of the given line. +" Parameters: +"   lnum: integer -- index of the line for which the indentation should be +"                    calculated +"   stack: [token] -- initial stack +" Return: +"   indent: integer -- if -1, that means "don't change the indentation"; +"                      otherwise it means "indent the line with `indent` +"                      number of spaces or equivalent tabs" +function! s:ErlangCalcIndent(lnum, stack) +  let res = s:ErlangCalcIndent2(a:lnum, a:stack) +  call s:Log("ErlangCalcIndent returned: " . res) +  return res +endfunction + +function! s:ErlangCalcIndent2(lnum, stack) + +  let lnum = a:lnum +  let stored_vcol = -1 " Virtual column of the first character of the token that +                   " we currently think we might align to. +  let mode = 'normal' +  let stack = a:stack +  let semicolon_abscol = '' + +  " Walk through the lines of the buffer backwards (starting from the +  " previous line) until we can decide how to indent the current line. +  while 1 + +    let [lnum, indtokens] = s:TokenizeLine(lnum, 'up') + +    " Hit the start of the file +    if lnum ==# 0 +      let [ret, res] = s:BeginningOfClauseFound(stack, 'beginning_of_file', +                                               \stored_vcol) +      if ret | return res | endif + +      return 0 +    endif + +    let i = len(indtokens) - 1 +    let last_token_of_line = 1 + +    while i >= 0 + +      let [token, curr_vcol, curr_col] = indtokens[i] +      call s:Log('  Analyzing the following token: ' . string(indtokens[i])) + +      if len(stack) > 256 " TODO: magic number +        return s:IndentError('Stack too long', token, stack) +      endif + +      if token ==# '<end_of_clause>' +        let [ret, res] = s:BeginningOfClauseFound(stack, token, stored_vcol) +        if ret | return res | endif + +        if stored_vcol ==# -1 +          call s:Log('    End of clause directly preceeds LTI -> return') +          return 0 +        else +          call s:Log('    End of clause (but not end of line) -> return') +          return stored_vcol +        endif + +      elseif stack == ['prev_term_plus'] +        if token =~# '[a-zA-Z_@]' || +         \ token ==# '<string>' || token ==# '<string_start>' || +         \ token ==# '<quoted_atom>' || token ==# '<quoted_atom_start>' +          call s:Log('    previous token found: curr_vcol + plus = ' . +                    \curr_vcol . " + " . plus) +          return curr_vcol + plus +        endif + +      elseif token ==# 'begin' +        let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, +                                            \stored_vcol, 'end', shiftwidth()) +        if ret | return res | endif + +      " case EXPR of BRANCHES end +      " try EXPR catch BRANCHES end +      " try EXPR after BODY end +      " try EXPR catch BRANCHES after BODY end +      " try EXPR of BRANCHES catch BRANCHES end +      " try EXPR of BRANCHES after BODY end +      " try EXPR of BRANCHES catch BRANCHES after BODY end +      " receive BRANCHES end +      " receive BRANCHES after BRANCHES end + +      " This branch is not Emacs-compatible +      elseif (index(['of', 'receive', 'after', 'if'], token) != -1 || +           \  (token ==# 'catch' && !s:IsCatchStandalone(lnum, i))) && +           \ !last_token_of_line && +           \ (empty(stack) || stack ==# ['when'] || stack ==# ['->'] || +           \  stack ==# ['->', ';']) + +        " If we are after of/receive, but these are not the last +        " tokens of the line, we want to indent like this: +        " +        "   % stack == [] +        "   receive stored_vcol, +        "           LTI +        " +        "   % stack == ['->', ';'] +        "   receive stored_vcol -> +        "               B; +        "           LTI +        " +        "   % stack == ['->'] +        "   receive stored_vcol -> +        "               LTI +        " +        "   % stack == ['when'] +        "   receive stored_vcol when +        "               LTI + +        " stack = []  =>  LTI is a condition +        " stack = ['->']  =>  LTI is a branch +        " stack = ['->', ';']  =>  LTI is a condition +        " stack = ['when']  =>  LTI is a guard +        if empty(stack) || stack == ['->', ';'] +          call s:Log('    LTI is in a condition after ' . +                    \'"of/receive/after/if/catch" -> return') +          return stored_vcol +        elseif stack == ['->'] +          call s:Log('    LTI is in a branch after ' . +                    \'"of/receive/after/if/catch" -> return') +          return stored_vcol + shiftwidth() +        elseif stack == ['when'] +          call s:Log('    LTI is in a guard after ' . +                    \'"of/receive/after/if/catch" -> return') +          return stored_vcol + shiftwidth() +        else +          return s:UnexpectedToken(token, stack) +        endif + +      elseif index(['case', 'if', 'try', 'receive'], token) != -1 + +        " stack = []  =>  LTI is a condition +        " stack = ['->']  =>  LTI is a branch +        " stack = ['->', ';']  =>  LTI is a condition +        " stack = ['when']  =>  LTI is in a guard +        if empty(stack) +          " pass +        elseif (token ==# 'case' && stack[0] ==# 'of') || +             \ (token ==# 'if') || +             \ (token ==# 'try' && (stack[0] ==# 'of' || +             \                     stack[0] ==# 'catch' || +             \                     stack[0] ==# 'after')) || +             \ (token ==# 'receive') + +          " From the indentation point of view, the keyword +          " (of/catch/after/end) before the LTI is what counts, so +          " when we reached these tokens, and the stack already had +          " a catch/after/end, we didn't modify it. +          " +          " This way when we reach case/try/receive (i.e. now), +          " there is at most one of/catch/after/end token in the +          " stack. +          if token ==# 'case' || token ==# 'try' || +           \ (token ==# 'receive' && stack[0] ==# 'after') +            call s:Pop(stack) +          endif + +          if empty(stack) +            call s:Log('    LTI is in a condition; matching ' . +                      \'"case/if/try/receive" found') +            let stored_vcol = curr_vcol + shiftwidth() +          elseif stack[0] ==# 'align_to_begin_element' +            call s:Pop(stack) +            let stored_vcol = curr_vcol +          elseif len(stack) > 1 && stack[0] ==# '->' && stack[1] ==# ';' +            call s:Log('    LTI is in a condition; matching ' . +                      \'"case/if/try/receive" found') +            call s:Pop(stack) +            call s:Pop(stack) +            let stored_vcol = curr_vcol + shiftwidth() +          elseif stack[0] ==# '->' +            call s:Log('    LTI is in a branch; matching ' . +                      \'"case/if/try/receive" found') +            call s:Pop(stack) +            let stored_vcol = curr_vcol + 2 * shiftwidth() +          elseif stack[0] ==# 'when' +            call s:Log('    LTI is in a guard; matching ' . +                      \'"case/if/try/receive" found') +            call s:Pop(stack) +            let stored_vcol = curr_vcol + 2 * shiftwidth() + 2 +          endif + +        endif + +        let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, +                                            \stored_vcol, 'end', shiftwidth()) +        if ret | return res | endif + +      elseif token ==# 'fun' +        let next_indtoken = s:NextIndToken(lnum, i) +        call s:Log('    Next indtoken = ' . string(next_indtoken)) + +        if !empty(next_indtoken) && next_indtoken[0] ==# '(' +          " We have an anonymous function definition +          " (e.g. "fun () -> ok end") + +          " stack = []  =>  LTI is a condition +          " stack = ['->']  =>  LTI is a branch +          " stack = ['->', ';']  =>  LTI is a condition +          " stack = ['when']  =>  LTI is in a guard +          if empty(stack) +            call s:Log('    LTI is in a condition; matching "fun" found') +            let stored_vcol = curr_vcol + shiftwidth() +          elseif len(stack) > 1 && stack[0] ==# '->' && stack[1] ==# ';' +            call s:Log('    LTI is in a condition; matching "fun" found') +            call s:Pop(stack) +            call s:Pop(stack) +          elseif stack[0] ==# '->' +            call s:Log('    LTI is in a branch; matching "fun" found') +            call s:Pop(stack) +            let stored_vcol = curr_vcol + 2 * shiftwidth() +          elseif stack[0] ==# 'when' +            call s:Log('    LTI is in a guard; matching "fun" found') +            call s:Pop(stack) +            let stored_vcol = curr_vcol + 2 * shiftwidth() + 2 +          endif + +          let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, +                                              \stored_vcol, 'end', shiftwidth()) +          if ret | return res | endif +        else +          " Pass: we have a function reference (e.g. "fun f/0") +        endif + +      elseif token ==# '[' +        " Emacs compatibility +        let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, +                                            \stored_vcol, ']', 1) +        if ret | return res | endif + +      elseif token ==# '<<' +        " Emacs compatibility +        let [ret, res] = s:BeginElementFound(stack, token, curr_vcol, +                                            \stored_vcol, '>>', 2) +        if ret | return res | endif + +      elseif token ==# '(' || token ==# '{' + +        let end_token = (token ==# '(' ? ')' : +                        \token ==# '{' ? '}' : 'error') + +        if empty(stack) +          " We found the opening paren whose block contains the LTI. +          let mode = 'inside' +        elseif stack[0] ==# end_token +          call s:Log('    "' . token . '" pops "' . end_token . '"') +          call s:Pop(stack) + +          if !empty(stack) && stack[0] ==# 'align_to_begin_element' +            " We found the opening paren whose closing paren +            " starts LTI +            let mode = 'align_to_begin_element' +          else +            " We found the opening pair for a closing paren that +            " was already in the stack. +            let mode = 'outside' +          endif +        else +          return s:UnexpectedToken(token, stack) +        endif + +        if mode ==# 'inside' || mode ==# 'align_to_begin_element' + +          if last_token_of_line && i != 0 +            " Examples: {{{ +            " +            " mode == 'inside': +            " +            "     my_func( +            "       LTI +            " +            "     [Variable, { +            "        LTI +            " +            " mode == 'align_to_begin_element': +            " +            "     my_func( +            "       Params +            "      ) % LTI +            " +            "     [Variable, { +            "        Terms +            "       } % LTI +            " }}} +            let stack = ['prev_term_plus'] +            let plus = (mode ==# 'inside' ? 2 : 1) +            call s:Log('    "' . token . +                      \'" token found at end of line -> find previous token') +          elseif mode ==# 'align_to_begin_element' +            " Examples: {{{ +            " +            " mode == 'align_to_begin_element' && !last_token_of_line +            " +            "     my_func(stored_vcol +            "            ) % LTI +            " +            "     [Variable, {stored_vcol +            "                } % LTI +            " +            " mode == 'align_to_begin_element' && i == 0 +            " +            "     ( +            "       stored_vcol +            "     ) % LTI +            " +            "     { +            "       stored_vcol +            "     } % LTI +            " }}} +            call s:Log('    "' . token . '" token (whose closing token ' . +                      \'starts LTI) found -> return') +            return curr_vcol +          elseif stored_vcol ==# -1 +            " Examples: {{{ +            " +            " mode == 'inside' && stored_vcol == -1 && !last_token_of_line +            " +            "     my_func( +            "             LTI +            "     [Variable, { +            "                 LTI +            " +            " mode == 'inside' && stored_vcol == -1 && i == 0 +            " +            "     ( +            "      LTI +            " +            "     { +            "      LTI +            " }}} +            call s:Log('    "' . token . +                      \'" token (which directly precedes LTI) found -> return') +            return curr_vcol + 1 +          else +            " Examples: {{{ +            " +            " mode == 'inside' && stored_vcol != -1 && !last_token_of_line +            " +            "     my_func(stored_vcol, +            "             LTI +            " +            "     [Variable, {stored_vcol, +            "                 LTI +            " +            " mode == 'inside' && stored_vcol != -1 && i == 0 +            " +            "     (stored_vcol, +            "      LTI +            " +            "     {stored_vcol, +            "      LTI +            " }}} +            call s:Log('    "' . token . +                      \'" token (whose block contains LTI) found -> return') +            return stored_vcol +          endif +        endif + +      elseif index(['end', ')', ']', '}', '>>'], token) != -1 + +        " If we can be sure that there is synchronization in the Erlang +        " syntax, we use searchpair to make the script quicker. Otherwise we +        " just push the token onto the stack and keep parsing. +     +        " No synchronization -> no searchpair optimization +        if !exists('b:erlang_syntax_synced') +          call s:Push(stack, token) + +        " We don't have searchpair optimization for '>>' +        elseif token ==# '>>' +          call s:Push(stack, token) + +        elseif token ==# 'end' +          let [lnum_new, col_new] = s:SearchEndPair(lnum, curr_col) + +          if lnum_new ==# 0 +            return s:IndentError('Matching token for "end" not found', +                                \token, stack) +          else +            if lnum_new != lnum +              call s:Log('    Tokenize for "end" <<<<') +              let [lnum, indtokens] = s:TokenizeLine(lnum_new, 'up') +              call s:Log('    >>>> Tokenize for "end"') +            endif + +            let [success, i] = s:GetIndtokenAtCol(indtokens, col_new) +            if !success | return i | endif +            let [token, curr_vcol, curr_col] = indtokens[i] +            call s:Log('    Match for "end" in line ' . lnum_new . ': ' . +                      \string(indtokens[i])) +          endif + +        else " token is one of the following: ')', ']', '}' + +          call s:Push(stack, token) + +          " We have to escape '[', because this string will be interpreted as a +          " regexp +          let open_paren = (token ==# ')' ? '(' : +                           \token ==# ']' ? '\[' : +                           \               '{') + +          let [lnum_new, col_new] = s:SearchPair(lnum, curr_col, +                                                \open_paren, '', token) + +          if lnum_new ==# 0 +            return s:IndentError('Matching token not found', +                                \token, stack) +          else +            if lnum_new != lnum +              call s:Log('    Tokenize the opening paren <<<<') +              let [lnum, indtokens] = s:TokenizeLine(lnum_new, 'up') +              call s:Log('    >>>>') +            endif + +            let [success, i] = s:GetIndtokenAtCol(indtokens, col_new) +            if !success | return i | endif +            let [token, curr_vcol, curr_col] = indtokens[i] +            call s:Log('    Match in line ' . lnum_new . ': ' . +                      \string(indtokens[i])) + +            " Go back to the beginning of the loop and handle the opening paren +            continue +          endif +        endif + +      elseif token ==# ';' + +        if empty(stack) +          call s:Push(stack, ';') +        elseif index([';', '->', 'when', 'end', 'after', 'catch'], +                    \stack[0]) != -1 +          " Pass: +          " +          " - If the stack top is another ';', then one ';' is +          "   enough. +          " - If the stack top is an '->' or a 'when', then we +          "   should keep that, because they signify the type of the +          "   LTI (branch, condition or guard). +          " - From the indentation point of view, the keyword +          "   (of/catch/after/end) before the LTI is what counts, so +          "   if the stack already has a catch/after/end, we don't +          "   modify it. This way when we reach case/try/receive, +          "   there will be at most one of/catch/after/end token in +          "   the stack. +        else +          return s:UnexpectedToken(token, stack) +        endif + +      elseif token ==# '->' + +        if empty(stack) && !last_token_of_line +          call s:Log('    LTI is in expression after arrow -> return') +          return stored_vcol +        elseif empty(stack) || stack[0] ==# ';' || stack[0] ==# 'end' +          " stack = [';']  -> LTI is either a branch or in a guard +          " stack = ['->']  ->  LTI is a condition +          " stack = ['->', ';']  -> LTI is a branch +          call s:Push(stack, '->') +        elseif index(['->', 'when', 'end', 'after', 'catch'], stack[0]) != -1 +          " Pass: +          " +          " - If the stack top is another '->', then one '->' is +          "   enough. +          " - If the stack top is a 'when', then we should keep +          "   that, because this signifies that LTI is a in a guard. +          " - From the indentation point of view, the keyword +          "   (of/catch/after/end) before the LTI is what counts, so +          "   if the stack already has a catch/after/end, we don't +          "   modify it. This way when we reach case/try/receive, +          "   there will be at most one of/catch/after/end token in +          "   the stack. +        else +          return s:UnexpectedToken(token, stack) +        endif + +      elseif token ==# 'when' + +        " Pop all ';' from the top of the stack +        while !empty(stack) && stack[0] ==# ';' +          call s:Pop(stack) +        endwhile + +        if empty(stack) +          if semicolon_abscol != '' +            let stored_vcol = semicolon_abscol +          endif +          if !last_token_of_line +            " Example: +            "   when A, +            "        LTI +            let [ret, res] = s:BeginElementFoundIfEmpty(stack, token, curr_vcol, +                                                       \stored_vcol, shiftwidth()) +            if ret | return res | endif +          else +            " Example: +            "   when +            "       LTI +            call s:Push(stack, token) +          endif +        elseif index(['->', 'when', 'end', 'after', 'catch'], stack[0]) != -1 +          " Pass: +          " - If the stack top is another 'when', then one 'when' is +          "   enough. +          " - If the stack top is an '->' or a 'when', then we +          "   should keep that, because they signify the type of the +          "   LTI (branch, condition or guard). +          " - From the indentation point of view, the keyword +          "   (of/catch/after/end) before the LTI is what counts, so +          "   if the stack already has a catch/after/end, we don't +          "   modify it. This way when we reach case/try/receive, +          "   there will be at most one of/catch/after/end token in +          "   the stack. +        else +          return s:UnexpectedToken(token, stack) +        endif + +      elseif token ==# 'of' || token ==# 'after' || +           \ (token ==# 'catch' && !s:IsCatchStandalone(lnum, i)) + +        if token ==# 'after' +          " If LTI is between an 'after' and the corresponding +          " 'end', then let's return +          let [ret, res] = s:BeginElementFoundIfEmpty(stack, token, curr_vcol, +                                                     \stored_vcol, shiftwidth()) +          if ret | return res | endif +        endif + +        if empty(stack) || stack[0] ==# '->' || stack[0] ==# 'when' +          call s:Push(stack, token) +        elseif stack[0] ==# 'catch' || stack[0] ==# 'after' || stack[0] ==# 'end' +          " Pass: From the indentation point of view, the keyword +          " (of/catch/after/end) before the LTI is what counts, so +          " if the stack already has a catch/after/end, we don't +          " modify it. This way when we reach case/try/receive, +          " there will be at most one of/catch/after/end token in +          " the stack. +        else +          return s:UnexpectedToken(token, stack) +        endif + +      elseif token ==# '||' && empty(stack) && !last_token_of_line + +        call s:Log('    LTI is in expression after "||" -> return') +        return stored_vcol + +      else +        call s:Log('    Misc token, stack unchanged = ' . string(stack)) + +      endif + +      if empty(stack) || stack[0] ==# '->' || stack[0] ==# 'when' +        let stored_vcol = curr_vcol +        let semicolon_abscol = '' +        call s:Log('    Misc token when the stack is empty or has "->" ' . +                  \'-> setting stored_vcol to ' . stored_vcol) +      elseif stack[0] ==# ';' +        let semicolon_abscol = curr_vcol +        call s:Log('    Setting semicolon-stored_vcol to ' . stored_vcol) +      endif + +      let i -= 1 +      call s:Log('    Token processed. stored_vcol=' . stored_vcol) + +      let last_token_of_line = 0 + +    endwhile " iteration on tokens in a line + +    call s:Log('  Line analyzed. stored_vcol=' . stored_vcol) + +    if empty(stack) && stored_vcol != -1 && +     \ (!empty(indtokens) && indtokens[0][0] != '<string_end>' && +     \                       indtokens[0][0] != '<quoted_atom_end>') +      call s:Log('    Empty stack at the beginning of the line -> return') +      return stored_vcol +    endif + +    let lnum -= 1 + +  endwhile " iteration on lines + +endfunction + +" ErlangIndent function {{{1 +" ===================== + +function! ErlangIndent() + +  call s:ClearTokenCacheIfNeeded() + +  let currline = getline(v:lnum) +  call s:Log('Indenting line ' . v:lnum . ': ' . currline) + +  if s:IsLineStringContinuation(v:lnum) || s:IsLineAtomContinuation(v:lnum) +    call s:Log('String or atom continuation found -> ' . +              \'leaving indentation unchanged') +    return -1 +  endif + +  let ml = matchlist(currline, +                    \'^\(\s*\)\(\%(end\|of\|catch\|after\)\>\|[)\]}]\|>>\)') + +  " If the line has a special beginning, but not a standalone catch +  if !empty(ml) && !(ml[2] ==# 'catch' && s:IsCatchStandalone(v:lnum, 0)) + +    let curr_col = len(ml[1]) + +    " If we can be sure that there is synchronization in the Erlang +    " syntax, we use searchpair to make the script quicker. +    if ml[2] ==# 'end' && exists('b:erlang_syntax_synced') + +      let [lnum, col] = s:SearchEndPair(v:lnum, curr_col) + +      if lnum ==# 0 +        return s:IndentError('Matching token for "end" not found', +                            \'end', []) +      else +        call s:Log('    Tokenize for "end" <<<<') +        let [lnum, indtokens] = s:TokenizeLine(lnum, 'up') +        call s:Log('    >>>> Tokenize for "end"') + +        let [success, i] = s:GetIndtokenAtCol(indtokens, col) +        if !success | return i | endif +        let [token, curr_vcol, curr_col] = indtokens[i] +        call s:Log('    Match for "end" in line ' . lnum . ': ' . +                   \string(indtokens[i])) +        return curr_vcol +      endif + +    else + +      call s:Log("  Line type = 'end'") +      let new_col = s:ErlangCalcIndent(v:lnum - 1, +                                      \[ml[2], 'align_to_begin_element']) +    endif +  else +    call s:Log("  Line type = 'normal'") + +    let new_col = s:ErlangCalcIndent(v:lnum - 1, []) +    if currline =~# '^\s*when\>' +      let new_col += 2 +    endif +  endif + +  if new_col < -1 +    call s:Log('WARNING: returning new_col == ' . new_col) +    return g:erlang_unexpected_token_indent +  endif + +  return new_col + +endfunction + +" Cleanup {{{1 +" ======= + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: sw=2 et fdm=marker + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'erlang') == -1  " Vim indent file diff --git a/indent/eruby.vim b/indent/eruby.vim index 6fd76600..3bae537e 100644 --- a/indent/eruby.vim +++ b/indent/eruby.vim @@ -1,3 +1,112 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:		eRuby +" Maintainer:		Tim Pope <vimNOSPAM@tpope.org> +" URL:			https://github.com/vim-ruby/vim-ruby +" Release Coordinator:	Doug Kearns <dougkearns@gmail.com> + +if exists("b:did_indent") +  finish +endif + +runtime! indent/ruby.vim +unlet! b:did_indent +setlocal indentexpr= + +if exists("b:eruby_subtype") +  exe "runtime! indent/".b:eruby_subtype.".vim" +else +  runtime! indent/html.vim +endif +unlet! b:did_indent + +" Force HTML indent to not keep state. +let b:html_indent_usestate = 0 + +if &l:indentexpr == '' +  if &l:cindent +    let &l:indentexpr = 'cindent(v:lnum)' +  else +    let &l:indentexpr = 'indent(prevnonblank(v:lnum-1))' +  endif +endif +let b:eruby_subtype_indentexpr = &l:indentexpr + +let b:did_indent = 1 + +setlocal indentexpr=GetErubyIndent() +setlocal indentkeys=o,O,*<Return>,<>>,{,},0),0],o,O,!^F,=end,=else,=elsif,=rescue,=ensure,=when + +" Only define the function once. +if exists("*GetErubyIndent") +  finish +endif + +" this file uses line continuations +let s:cpo_sav = &cpo +set cpo&vim + +function! GetErubyIndent(...) +  " The value of a single shift-width +  let sw = shiftwidth() + +  if a:0 && a:1 == '.' +    let v:lnum = line('.') +  elseif a:0 && a:1 =~ '^\d' +    let v:lnum = a:1 +  endif +  let vcol = col('.') +  call cursor(v:lnum,1) +  let inruby = searchpair('<%','','%>','W') +  call cursor(v:lnum,vcol) +  if inruby && getline(v:lnum) !~ '^<%\|^\s*[-=]\=%>' +    let ind = GetRubyIndent(v:lnum) +  else +    exe "let ind = ".b:eruby_subtype_indentexpr + +    " Workaround for Andy Wokula's HTML indent. This should be removed after +    " some time, since the newest version is fixed in a different way. +    if b:eruby_subtype_indentexpr =~# '^HtmlIndent(' +	  \ && exists('b:indent') +	  \ && type(b:indent) == type({}) +	  \ && has_key(b:indent, 'lnum') +      " Force HTML indent to not keep state +      let b:indent.lnum = -1 +    endif +  endif +  let lnum = prevnonblank(v:lnum-1) +  let line = getline(lnum) +  let cline = getline(v:lnum) +  if cline =~# '^\s*<%[-=]\=\s*\%(}\|end\|else\|\%(ensure\|rescue\|elsif\|when\).\{-\}\)\s*\%([-=]\=%>\|$\)' +    let ind = ind - sw +  endif +  if line =~# '\S\s*<%[-=]\=\s*\%(}\|end\).\{-\}\s*\%([-=]\=%>\|$\)' +    let ind = ind - sw +  endif +  if line =~# '\%({\|\<do\)\%(\s*|[^|]*|\)\=\s*[-=]\=%>' +    let ind = ind + sw +  elseif line =~# '<%[-=]\=\s*\%(module\|class\|def\|if\|for\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue\)\>.*%>' +    let ind = ind + sw +  endif +  if line =~# '^\s*<%[=#-]\=\s*$' && cline !~# '^\s*end\>' +    let ind = ind + sw +  endif +  if line !~# '^\s*<%' && line =~# '%>\s*$' && line !~# '^\s*end\>' +    let ind = ind - sw +  endif +  if cline =~# '^\s*[-=]\=%>\s*$' +    let ind = ind - sw +  endif +  return ind +endfunction + +let &cpo = s:cpo_sav +unlet! s:cpo_sav + +" vim:set sw=2 sts=2 ts=8 noet: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ruby') == -1  " Vim indent file diff --git a/indent/eterm.vim b/indent/eterm.vim new file mode 100644 index 00000000..df80c058 --- /dev/null +++ b/indent/eterm.vim @@ -0,0 +1,40 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Eterm configuration file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetEtermIndent() +setlocal indentkeys=!^F,o,O,=end +setlocal nosmartindent + +if exists("*GetEtermIndent") +  finish +endif + +function GetEtermIndent() +  let lnum = prevnonblank(v:lnum - 1) +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) + +  if getline(lnum) =~ '^\s*begin\>' +    let ind = ind + shiftwidth() +  endif + +  if getline(v:lnum) =~ '^\s*end\>' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/falcon.vim b/indent/falcon.vim new file mode 100644 index 00000000..4d17d33d --- /dev/null +++ b/indent/falcon.vim @@ -0,0 +1,455 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language: Falcon +" Maintainer: Steven Oliver <oliver.steven@gmail.com> +" Website: https://steveno@github.com/steveno/falconpl-vim.git +" Credits: This is, to a great extent, a copy n' paste of ruby.vim. + +" 1. Setup {{{1 +" ============ + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +" Setup indent function and when to use it +setlocal indentexpr=FalconGetIndent(v:lnum) +setlocal indentkeys=0{,0},0),0],!^F,o,O,e +setlocal indentkeys+==~case,=~catch,=~default,=~elif,=~else,=~end,=~\" + +" Define the appropriate indent function but only once +if exists("*FalconGetIndent") +    finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 2. Variables {{{1 +" ============ + +" Regex of syntax group names that are strings AND comments +let s:syng_strcom = '\<falcon\%(String\|StringEscape\|Comment\)\>' + +" Regex of syntax group names that are strings +let s:syng_string = '\<falcon\%(String\|StringEscape\)\>' + +" Regex that defines blocks. +" +" Note that there's a slight problem with this regex and s:continuation_regex. +" Code like this will be matched by both: +" +"   method_call do |(a, b)| +" +" The reason is that the pipe matches a hanging "|" operator. +" +let s:block_regex = +      \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|\s*(*\s*\%([*@&]\=\h\w*,\=\s*\)\%(,\s*(*\s*[*@&]\=\h\w*\s*)*\s*\)*|\)\=\s*\%(#.*\)\=$' + +let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex + +" Regex that defines continuation lines. +" TODO: this needs to deal with if ...: and so on +let s:continuation_regex = +      \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Regex that defines bracket continuations +let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$' + +" Regex that defines continuation lines, not including (, {, or [. +let s:non_bracket_continuation_regex = '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Keywords to indent on +let s:falcon_indent_keywords = '^\s*\(case\|catch\|class\|enum\|default\|elif\|else' . +    \ '\|for\|function\|if.*"[^"]*:.*"\|if \(\(:\)\@!.\)*$\|loop\|object\|select' . +    \ '\|switch\|try\|while\|\w*\s*=\s*\w*([$\)' + +" Keywords to deindent on +let s:falcon_deindent_keywords = '^\s*\(case\|catch\|default\|elif\|else\|end\)' + +" 3. 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 + +" 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 string delimiter +function s:IsInStringDelimiter(lnum, col) +    return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'falconStringDelimiter' +endfunction + +" 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 =~ '^=begin' +	    if in_block +		let in_block = 0 +	    else +		break +	    endif +	elseif !in_block && line =~ '^=end' +	    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 + +" Find line above 'lnum' that started the continuation 'lnum' may be part of. +function s:GetMSL(lnum) +    " Start on the line we're at and use its indent. +    let msl = a:lnum +    let msl_body = getline(msl) +    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) +	 +	if s:Match(line, s:non_bracket_continuation_regex) && +          	\ s:Match(msl, s:non_bracket_continuation_regex) +	    " If the current line is a non-bracket continuation and so is the +	    " previous one, keep its indent and continue looking for an MSL. +	    "     +	    " Example: +	    "   method_call one, +	    "       two, +	    "           three +	    "            +	    let msl = lnum +	elseif s:Match(lnum, s:non_bracket_continuation_regex) && +		    \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) +	    " If the current line is a bracket continuation or a block-starter, but +	    " the previous is a non-bracket one, respect the previous' indentation, +	    " and stop here. +	    "  +	    " Example: +	    "   method_call one, +	    "       two { +	    "           three +	    " +	    return lnum +	elseif s:Match(lnum, s:bracket_continuation_regex) && +		    \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) +	    " If both lines are bracket continuations (the current may also be a +	    " block-starter), use the current one's and stop here +	    " +	    " Example: +	    "   method_call( +	    "       other_method_call( +	    "             foo +	    return msl +	elseif s:Match(lnum, s:block_regex) && +		    \ !s:Match(msl, s:continuation_regex) && +		    \ !s:Match(msl, s:block_continuation_regex) +	    " If the previous line is a block-starter and the current one is +	    " mostly ordinary, use the current one as the MSL. +	    "  +	    " Example: +	    "   method_call do +	    "       something +	    "           something_else +	    return msl +	else +	    let col = match(line, s:continuation_regex) + 1 +	    if (col > 0 && !s:IsInStringOrComment(lnum, col)) +			\ || s:IsInString(lnum, strlen(line)) +		let msl = lnum +	    else +		break +	    endif +	endif +	 +	let msl_body = getline(msl) +	let lnum = s:PrevNonBlankNonString(lnum - 1) +    endwhile +    return msl +endfunction + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:ExtraBrackets(lnum) +    let opening = {'parentheses': [], 'braces': [], 'brackets': []} +    let closing = {'parentheses': [], 'braces': [], 'brackets': []} + +    let line = getline(a:lnum) +    let pos  = match(line, '[][(){}]', 0) + +    " Save any encountered opening brackets, and remove them once a matching +    " closing one has been found. If a closing bracket shows up that doesn't +    " close anything, save it for later. +    while pos != -1 +	if !s:IsInStringOrComment(a:lnum, pos + 1) +	    if line[pos] == '(' +		call add(opening.parentheses, {'type': '(', 'pos': pos}) +	    elseif line[pos] == ')' +		if empty(opening.parentheses) +		    call add(closing.parentheses, {'type': ')', 'pos': pos}) +		else +		    let opening.parentheses = opening.parentheses[0:-2] +		endif +	    elseif line[pos] == '{' +		call add(opening.braces, {'type': '{', 'pos': pos}) +	    elseif line[pos] == '}' +		if empty(opening.braces) +		    call add(closing.braces, {'type': '}', 'pos': pos}) +		else +		    let opening.braces = opening.braces[0:-2] +		endif +	    elseif line[pos] == '[' +		call add(opening.brackets, {'type': '[', 'pos': pos}) +	    elseif line[pos] == ']' +		if empty(opening.brackets) +		    call add(closing.brackets, {'type': ']', 'pos': pos}) +		else +		    let opening.brackets = opening.brackets[0:-2] +		endif +	    endif +	endif +	 +	let pos = match(line, '[][(){}]', pos + 1) +    endwhile + +    " Find the rightmost brackets, since they're the ones that are important in +    " both opening and closing cases +    let rightmost_opening = {'type': '(', 'pos': -1} +    let rightmost_closing = {'type': ')', 'pos': -1} + +    for opening in opening.parentheses + opening.braces + opening.brackets +	if opening.pos > rightmost_opening.pos +	    let rightmost_opening = opening +	endif +    endfor + +    for closing in closing.parentheses + closing.braces + closing.brackets +	if closing.pos > rightmost_closing.pos +	    let rightmost_closing = closing +	endif +    endfor + +    return [rightmost_opening, rightmost_closing] +endfunction + +function s:Match(lnum, regex) +    let col = match(getline(a:lnum), '\C'.a:regex) + 1 +    return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 +endfunction + +function s:MatchLast(lnum, regex) +    let line = getline(a:lnum) +    let col = match(line, '.*\zs' . a:regex) +    while col != -1 && s:IsInStringOrComment(a:lnum, col) +	let line = strpart(line, 0, col) +	let col = match(line, '.*' . a:regex) +    endwhile +    return col + 1 +endfunction + +" 4. FalconGetIndent Routine {{{1 +" ============ + +function FalconGetIndent(...) +    " For the current line, use the first argument if given, else v:lnum +    let clnum = a:0 ? a:1 : v:lnum + +    " Use zero indent at the top of the file +    if clnum == 0 +        return 0 +    endif + +    let line = getline(clnum) +    let ind = -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(clnum, col) +	call cursor(clnum, col) +	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('.'))) +	    endif +	endif +	return ind +    endif + +    " If we have a deindenting keyword, find its match and indent to its level. +    " TODO: this is messy +    if s:Match(clnum, s:falcon_deindent_keywords) +	call cursor(clnum, 1) +	if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', +		    \ s:end_skip_expr) > 0 +	    let msl  = s:GetMSL(line('.')) +	    let line = getline(line('.')) + +	    if strpart(line, 0, col('.') - 1) =~ '=\s*$' && +			\ strpart(line, col('.') - 1, 2) !~ 'do' +		let ind = virtcol('.') - 1 +	    elseif getline(msl) =~ '=\s*\(#.*\)\=$' +		let ind = indent(line('.')) +	    else +		let ind = indent(msl) +	    endif +	endif +	return ind +    endif + +    " If we are in a multi-line string or line-comment, don't do anything to it. +    if s:IsInString(clnum, matchend(line, '^\s*') + 1) +	return indent('.') +    endif + +    " Find a non-blank, non-multi-line string line above the current line. +    let lnum = s:PrevNonBlankNonString(clnum - 1) + +    " If the line is empty and inside a string, use the previous line. +    if line =~ '^\s*$' && lnum != prevnonblank(clnum - 1) +	return indent(prevnonblank(clnum)) +    endif + +    " At the start of the file use zero indent. +    if lnum == 0 +	return 0 +    endif + +    " Set up variables for the previous 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)) + shiftwidth() +    endif + +    " If it contained hanging closing brackets, find the rightmost one, find its +    " match and indent according to that. +    if line =~ '[[({]' || line =~ '[])}]\s*\%(#.*\)\=$' +	let [opening, closing] = s:ExtraBrackets(lnum) + +	if opening.pos != -1 +	    if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 +		if col('.') + 1 == col('$') +		    return ind + shiftwidth() +		else +		    return virtcol('.') +		endif +	    else +		let nonspace = matchend(line, '\S', opening.pos + 1) - 1 +		return nonspace > 0 ? nonspace : ind + shiftwidth() +	    endif +	elseif closing.pos != -1 +	    call cursor(lnum, closing.pos + 1) +	    normal! % + +	    if s:Match(line('.'), s:falcon_indent_keywords) +		return indent('.') + shiftwidth() +	    else +		return indent('.') +	    endif +	else +	    call cursor(clnum, vcol) +	end +    endif + +    " If the previous line ended with an "end", match that "end"s beginning's +    " indent. +    let col = s:Match(lnum, '\%(^\|[^.:@$]\)\<end\>\s*\%(#.*\)\=$') +    if col > 0 +	call cursor(lnum, col) +	if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', +		    \ s:end_skip_expr) > 0 +	    let n = line('.') +	    let ind = indent('.') +	    let msl = s:GetMSL(n) +	    if msl != n +		let ind = indent(msl) +	    end +	    return ind +	endif +    end + +    let col = s:Match(lnum, s:falcon_indent_keywords) +    if col > 0 +	call cursor(lnum, col) +	let ind = virtcol('.') - 1 + shiftwidth() +	" TODO: make this better (we need to count them) (or, if a searchpair +	" fails, we know that something is lacking an end and thus we indent a +	" level +	if s:Match(lnum, s:end_end_regex) +	    let ind = indent('.') +	endif +	return ind +    endif + +    " Set up variables to use and search for MSL to the previous line. +    let p_lnum = lnum +    let lnum = s:GetMSL(lnum) + +    " 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:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) +	    return ind +	endif +    endif + +    " Set up more variables, now that we know we wasn't continuation bound. +    let line = getline(lnum) +    let msl_ind = indent(lnum) + +    " If the MSL line had an indenting keyword in it, add a level of indent. +    " TODO: this does not take into account contrived things such as +    " module Foo; class Bar; end +    if s:Match(lnum, s:falcon_indent_keywords) +	let ind = msl_ind + shiftwidth() +	if s:Match(lnum, s:end_end_regex) +	    let ind = ind - shiftwidth() +	endif +	return ind +    endif + +    " If the previous line ended with [*+/.,-=], but wasn't a block ending or a +    " closing bracket, indent one extra level. +    if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') +	if lnum == p_lnum +	    let ind = msl_ind + shiftwidth() +	else +	    let ind = msl_ind +	endif +	return ind +    endif + +  return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: set sw=4 sts=4 et tw=80 : + +endif diff --git a/indent/fortran.vim b/indent/fortran.vim new file mode 100644 index 00000000..a7732d11 --- /dev/null +++ b/indent/fortran.vim @@ -0,0 +1,222 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) +" Version:	47 +" Last Change:	2016 Oct. 29 +" Maintainer:	Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> +" Usage:	For instructions, do :help fortran-indent from Vim +" Credits: +"  Useful suggestions were made, in chronological order, by: +"  Albert Oliver Serra, Takuya Fujiwara and Philipp Edelmann. + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +let s:cposet=&cpoptions +set cpoptions&vim + +setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select +setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect,=~elseif +setlocal indentkeys+==~type,=~interface,=~forall,=~associate,=~block,=~enum +setlocal indentkeys+==~endforall,=~endassociate,=~endblock,=~endenum +if exists("b:fortran_indent_more") || exists("g:fortran_indent_more") +  setlocal indentkeys+==~function,=~subroutine,=~module,=~contains,=~program +  setlocal indentkeys+==~endfunction,=~endsubroutine,=~endmodule +  setlocal indentkeys+==~endprogram +endif + +" Determine whether this is a fixed or free format source file +" if this hasn't been done yet using the priority: +" buffer-local value +" > global value +" > file extension as in Intel ifort, gcc (gfortran), NAG, Pathscale, and Cray compilers +if !exists("b:fortran_fixed_source") +  if exists("fortran_free_source") +    " User guarantees free source form +    let b:fortran_fixed_source = 0 +  elseif exists("fortran_fixed_source") +    " User guarantees fixed source form +    let b:fortran_fixed_source = 1 +  elseif expand("%:e") ==? "f\<90\|95\|03\|08\>" +    " Free-form file extension defaults as in Intel ifort, gcc(gfortran), NAG, Pathscale, and Cray compilers +    let b:fortran_fixed_source = 0 +  elseif expand("%:e") ==? "f\|f77\|for" +    " Fixed-form file extension defaults +    let b:fortran_fixed_source = 1 +  else +    " Modern fortran still allows both fixed and free source form +    " Assume fixed source form unless signs of free source form +    " are detected in the first five columns of the first s:lmax lines. +    " Detection becomes more accurate and time-consuming if more lines +    " are checked. Increase the limit below if you keep lots of comments at +    " the very top of each file and you have a fast computer. +    let s:lmax = 500 +    if ( s:lmax > line("$") ) +      let s:lmax = line("$") +    endif +    let b:fortran_fixed_source = 1 +    let s:ln=1 +    while s:ln <= s:lmax +      let s:test = strpart(getline(s:ln),0,5) +      if s:test !~ '^[Cc*]' && s:test !~ '^ *[!#]' && s:test =~ '[^ 0-9\t]' && s:test !~ '^[ 0-9]*\t' +	let b:fortran_fixed_source = 0 +	break +      endif +      let s:ln = s:ln + 1 +    endwhile +  endif +endif + +" Define the appropriate indent function but only once +if (b:fortran_fixed_source == 1) +  setlocal indentexpr=FortranGetFixedIndent() +  if exists("*FortranGetFixedIndent") +    finish +  endif +else +  setlocal indentexpr=FortranGetFreeIndent() +  if exists("*FortranGetFreeIndent") +    finish +  endif +endif + +function FortranGetIndent(lnum) +  let ind = indent(a:lnum) +  let prevline=getline(a:lnum) +  " Strip tail comment +  let prevstat=substitute(prevline, '!.*$', '', '') +  let prev2line=getline(a:lnum-1) +  let prev2stat=substitute(prev2line, '!.*$', '', '') + +  "Indent do loops only if they are all guaranteed to be of do/end do type +  if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo") +    if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>' +      let ind = ind + shiftwidth() +    endif +    if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>' +      let ind = ind - shiftwidth() +    endif +  endif + +  "Add a shiftwidth to statements following if, else, else if, case, class, +  "where, else where, forall, type, interface and associate statements +  if prevstat =~? '^\s*\(case\|class\|else\|else\s*if\|else\s*where\)\>' +	\ ||prevstat=~? '^\s*\(type\|interface\|associate\|enum\)\>' +	\ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>' +	\ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>' +     let ind = ind + shiftwidth() +    " Remove unwanted indent after logical and arithmetic ifs +    if prevstat =~? '\<if\>' && prevstat !~? '\<then\>' +      let ind = ind - shiftwidth() +    endif +    " Remove unwanted indent after type( statements +    if prevstat =~? '^\s*type\s*(' +      let ind = ind - shiftwidth() +    endif +  endif + +  "Indent program units unless instructed otherwise +  if !exists("b:fortran_indent_less") && !exists("g:fortran_indent_less") +    let prefix='\(\(pure\|impure\|elemental\|recursive\)\s\+\)\{,2}' +    let type='\(\(integer\|real\|double\s\+precision\|complex\|logical' +          \.'\|character\|type\|class\)\s*\S*\s\+\)\=' +    if prevstat =~? '^\s*\(contains\|submodule\|program\)\>' +            \ ||prevstat =~? '^\s*'.'module\>\(\s*\procedure\)\@!' +            \ ||prevstat =~? '^\s*'.prefix.'subroutine\>' +            \ ||prevstat =~? '^\s*'.prefix.type.'function\>' +            \ ||prevstat =~? '^\s*'.type.prefix.'function\>' +      let ind = ind + shiftwidth() +    endif +    if getline(v:lnum) =~? '^\s*contains\>' +          \ ||getline(v:lnum)=~? '^\s*end\s*' +          \ .'\(function\|subroutine\|module\|submodule\|program\)\>' +      let ind = ind - shiftwidth() +    endif +  endif + +  "Subtract a shiftwidth from else, else if, elsewhere, case, class, end if, +  " end where, end select, end forall, end interface, end associate, +  " end enum, end type, end block and end type statements +  if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*' +        \. '\(else\|else\s*if\|else\s*where\|case\|class\|' +        \. 'end\s*\(if\|where\|select\|interface\|' +        \. 'type\|forall\|associate\|enum\|block\)\)\>' +    let ind = ind - shiftwidth() +    " Fix indent for case statement immediately after select +    if prevstat =~? '\<select\s\+\(case\|type\)\>' +      let ind = ind + shiftwidth() +    endif +  endif + +  "First continuation line +  if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$' +    let ind = ind + shiftwidth() +  endif +  "Line after last continuation line +  if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +function FortranGetFreeIndent() +  "Find the previous non-blank line +  let lnum = prevnonblank(v:lnum - 1) + +  "Use zero indent at the top of the file +  if lnum == 0 +    return 0 +  endif + +  let ind=FortranGetIndent(lnum) +  return ind +endfunction + +function FortranGetFixedIndent() +  let currline=getline(v:lnum) +  "Don't indent comments, continuation lines and labelled lines +  if strpart(currline,0,6) =~ '[^ \t]' +    let ind = indent(v:lnum) +    return ind +  endif + +  "Find the previous line which is not blank, not a comment, +  "not a continuation line, and does not have a label +  let lnum = v:lnum - 1 +  while lnum > 0 +    let prevline=getline(lnum) +    if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$") +	\ || (strpart(prevline,5,1) !~ "[ 0]") +      " Skip comments, blank lines and continuation lines +      let lnum = lnum - 1 +    else +      let test=strpart(prevline,0,5) +      if test =~ "[0-9]" +	" Skip lines with statement numbers +	let lnum = lnum - 1 +      else +	break +      endif +    endif +  endwhile + +  "First line must begin at column 7 +  if lnum == 0 +    return 6 +  endif + +  let ind=FortranGetIndent(lnum) +  return ind +endfunction + +let &cpoptions=s:cposet +unlet s:cposet + +" vim:sw=2 tw=130 + +endif diff --git a/indent/framescript.vim b/indent/framescript.vim new file mode 100644 index 00000000..872d390c --- /dev/null +++ b/indent/framescript.vim @@ -0,0 +1,45 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             FrameScript +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2008-07-19 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetFrameScriptIndent() +setlocal indentkeys=!^F,o,O,0=~Else,0=~EndIf,0=~EndLoop,0=~EndSub +setlocal nosmartindent + +if exists("*GetFrameScriptIndent") +  finish +endif + +function GetFrameScriptIndent() +  let lnum = prevnonblank(v:lnum - 1) + +  if lnum == 0 +    return 0 +  endif + +  if getline(v:lnum) =~ '^\s*\*' +    return cindent(v:lnum) +  endif + +  let ind = indent(lnum) + +  if getline(lnum) =~? '^\s*\%(If\|Loop\|Sub\)' +    let ind = ind + shiftwidth() +  endif + +  if getline(v:lnum) =~? '^\s*\%(Else\|End\%(If\|Loop\|Sub\)\)' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/gitconfig.vim b/indent/gitconfig.vim index e0e4a456..cc6330c1 100644 --- a/indent/gitconfig.vim +++ b/indent/gitconfig.vim @@ -1,3 +1,45 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	git config file +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2017 Jun 13 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetGitconfigIndent() +setlocal indentkeys=o,O,*<Return>,0[,],0;,0#,=,!^F + +let b:undo_indent = 'setl ai< inde< indk<' + +" Only define the function once. +if exists("*GetGitconfigIndent") +  finish +endif + +function! GetGitconfigIndent() +  let sw    = shiftwidth() +  let line  = getline(prevnonblank(v:lnum-1)) +  let cline = getline(v:lnum) +  if line =~  '\\\@<!\%(\\\\\)*\\$' +    " odd number of slashes, in a line continuation +    return 2 * sw +  elseif cline =~ '^\s*\[' +    return 0 +  elseif cline =~ '^\s*\a' +    return sw +  elseif cline == ''       && line =~ '^\[' +    return sw +  else +    return -1 +  endif +endfunction + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'git') == -1  " Vim indent file diff --git a/indent/gitolite.vim b/indent/gitolite.vim new file mode 100644 index 00000000..693b84bf --- /dev/null +++ b/indent/gitolite.vim @@ -0,0 +1,49 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	gitolite configuration +" URL:		https://github.com/tmatilai/gitolite.vim +" Maintainer:	Teemu Matilainen <teemu.matilainen@iki.fi> +" Last Change:	2017 Jun 13 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetGitoliteIndent() +setlocal indentkeys=o,O,*<Return>,!^F,=repo,\",= + +" Only define the function once. +if exists("*GetGitoliteIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +function! GetGitoliteIndent() +  let prevln = prevnonblank(v:lnum-1) +  let pline = getline(prevln) +  let cline = getline(v:lnum) + +  if cline =~ '^\s*\(C\|R\|RW\|RW+\|RWC\|RW+C\|RWD\|RW+D\|RWCD\|RW+CD\|-\)[ \t=]' +    return shiftwidth() +  elseif cline =~ '^\s*config\s' +    return shiftwidth() +  elseif pline =~ '^\s*repo\s' && cline =~ '^\s*\(#.*\)\?$' +    return shiftwidth() +  elseif cline =~ '^\s*#' +    return indent(prevln) +  elseif cline =~ '^\s*$' +    return -1 +  else +    return 0 +  endif +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/go.vim b/indent/go.vim index fd973e45..98e42a8b 100644 --- a/indent/go.vim +++ b/indent/go.vim @@ -1,3 +1,73 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Go +" Maintainer:	David Barnett (https://github.com/google/vim-ft-go) +" Last Change:	2017 Jun 13 +" +" TODO: +" - function invocations split across lines +" - general line splits (line ends in an operator) + +if exists('b:did_indent') +  finish +endif +let b:did_indent = 1 + +" C indentation is too far off useful, mainly due to Go's := operator. +" Let's just define our own. +setlocal nolisp +setlocal autoindent +setlocal indentexpr=GoIndent(v:lnum) +setlocal indentkeys+=<:>,0=},0=) + +if exists('*GoIndent') +  finish +endif + +function! GoIndent(lnum) +  let l:prevlnum = prevnonblank(a:lnum-1) +  if l:prevlnum == 0 +    " top of file +    return 0 +  endif + +  " grab the previous and current line, stripping comments. +  let l:prevl = substitute(getline(l:prevlnum), '//.*$', '', '') +  let l:thisl = substitute(getline(a:lnum), '//.*$', '', '') +  let l:previ = indent(l:prevlnum) + +  let l:ind = l:previ + +  if l:prevl =~ '[({]\s*$' +    " previous line opened a block +    let l:ind += shiftwidth() +  endif +  if l:prevl =~# '^\s*\(case .*\|default\):$' +    " previous line is part of a switch statement +    let l:ind += shiftwidth() +  endif +  " TODO: handle if the previous line is a label. + +  if l:thisl =~ '^\s*[)}]' +    " this line closed a block +    let l:ind -= shiftwidth() +  endif + +  " Colons are tricky. +  " We want to outdent if it's part of a switch ("case foo:" or "default:"). +  " We ignore trying to deal with jump labels because (a) they're rare, and +  " (b) they're hard to disambiguate from a composite literal key. +  if l:thisl =~# '^\s*\(case .*\|default\):$' +    let l:ind -= shiftwidth() +  endif + +  return l:ind +endfunction + +" vim: sw=2 sts=2 et + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'go') == -1  " Copyright 2011 The Go Authors. All rights reserved. diff --git a/indent/haml.vim b/indent/haml.vim index c251a4c4..dcfc1168 100644 --- a/indent/haml.vim +++ b/indent/haml.vim @@ -1,3 +1,81 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Haml +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2017 Jun 13 + +if exists("b:did_indent") +  finish +endif +runtime! indent/ruby.vim +unlet! b:did_indent +let b:did_indent = 1 + +setlocal autoindent sw=2 et +setlocal indentexpr=GetHamlIndent() +setlocal indentkeys=o,O,*<Return>,},],0),!^F,=end,=else,=elsif,=rescue,=ensure,=when + +" Only define the function once. +if exists("*GetHamlIndent") +  finish +endif + +let s:attributes = '\%({.\{-\}}\|\[.\{-\}\]\)' +let s:tag = '\%([%.#][[:alnum:]_-]\+\|'.s:attributes.'\)*[<>]*' + +if !exists('g:haml_self_closing_tags') +  let g:haml_self_closing_tags = 'base|link|meta|br|hr|img|input' +endif + +function! GetHamlIndent() +  let lnum = prevnonblank(v:lnum-1) +  if lnum == 0 +    return 0 +  endif +  let line = substitute(getline(lnum),'\s\+$','','') +  let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','') +  let lastcol = strlen(line) +  let line = substitute(line,'^\s\+','','') +  let indent = indent(lnum) +  let cindent = indent(v:lnum) +  let sw = shiftwidth() +  if cline =~# '\v^-\s*%(elsif|else|when)>' +    let indent = cindent < indent ? cindent : indent - sw +  endif +  let increase = indent + sw +  if indent == indent(lnum) +    let indent = cindent <= indent ? -1 : increase +  endif + +  let group = synIDattr(synID(lnum,lastcol,1),'name') + +  if line =~ '^!!!' +    return indent +  elseif line =~ '^/\%(\[[^]]*\]\)\=$' +    return increase +  elseif group == 'hamlFilter' +    return increase +  elseif line =~ '^'.s:tag.'[&!]\=[=~-]\s*\%(\%(if\|else\|elsif\|unless\|case\|when\|while\|until\|for\|begin\|module\|class\|def\)\>\%(.*\<end\>\)\@!\|.*do\%(\s*|[^|]*|\)\=\s*$\)' +    return increase +  elseif line =~ '^'.s:tag.'[&!]\=[=~-].*,\s*$' +    return increase +  elseif line == '-#' +    return increase +  elseif group =~? '\v^(hamlSelfCloser)$' || line =~? '^%\v%('.g:haml_self_closing_tags.')>' +    return indent +  elseif group =~? '\v^%(hamlTag|hamlAttributesDelimiter|hamlObjectDelimiter|hamlClass|hamlId|htmlTagName|htmlSpecialTagName)$' +    return increase +  elseif synIDattr(synID(v:lnum,1,1),'name') ==? 'hamlRubyFilter' +    return GetRubyIndent() +  else +    return indent +  endif +endfunction + +" vim:set sw=2: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'haml') == -1  " Vim indent file diff --git a/indent/hamster.vim b/indent/hamster.vim new file mode 100644 index 00000000..35f33fb1 --- /dev/null +++ b/indent/hamster.vim @@ -0,0 +1,59 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    Hamster Script  +" Version:     2.0.6.0 +" Last Change: Wed Nov 08 2006 12:02:42 PM +" Maintainer:  David Fishburn <fishburn@ianywhere.com> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentkeys+==~if,=~else,=~endif,=~endfor,=~endwhile +setlocal indentkeys+==~do,=~until,=~while,=~repeat,=~for,=~loop +setlocal indentkeys+==~sub,=~endsub + +" Define the appropriate indent function but only once +setlocal indentexpr=HamGetFreeIndent() +if exists("*HamGetFreeIndent") +  finish +endif + +function HamGetIndent(lnum) +  let ind = indent(a:lnum) +  let prevline=getline(a:lnum) + +  " Add a shiftwidth to statements following if,  else, elseif, +  " case, select, default, do, until, while, for, start +  if prevline =~? '^\s*\<\(if\|else\%(if\)\?\|for\|repeat\|do\|while\|sub\)\>'  +    let ind = ind + shiftwidth() +  endif + +  " Subtract a shiftwidth from else, elseif, end(if|while|for), until +  let line = getline(v:lnum) +  if line =~? '^\s*\(else\|elseif\|loop\|until\|end\%(if\|while\|for\|sub\)\)\>' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +function HamGetFreeIndent() +  " Find the previous non-blank line +  let lnum = prevnonblank(v:lnum - 1) + +  " Use zero indent at the top of the file +  if lnum == 0 +    return 0 +  endif + +  let ind=HamGetIndent(lnum) +  return ind +endfunction + +" vim:sw=2 tw=80 + +endif diff --git a/indent/hog.vim b/indent/hog.vim new file mode 100644 index 00000000..e86bc181 --- /dev/null +++ b/indent/hog.vim @@ -0,0 +1,81 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     hog (Snort.conf) +" Maintainer:   Victor Roemer, <vroemer@badsec.org> +" Last Change:  Mar 7, 2013 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 +let b:undo_indent = 'setlocal smartindent< indentexpr< indentkeys<' + +setlocal nosmartindent +setlocal indentexpr=GetHogIndent() +setlocal indentkeys+=!^F,o,O,0# + +" Only define the function once. +if exists("*GetHogIndent") +    finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +let s:syn_blocks = '\<SnortRuleTypeBody\>' + +function s:IsInBlock(lnum) +    return synIDattr(synID(a:lnum, 1, 1), 'name') =~ s:syn_blocks  +endfunction + +function GetHogIndent() +    let prevlnum = prevnonblank(v:lnum-1) + +    " Comment blocks have identical indent +    if getline(v:lnum) =~ '^\s*#' && getline(prevlnum) =~ '^\s*#' +            return indent(prevlnum) +    endif + +    " Ignore comment lines when calculating indent +    while getline(prevlnum) =~ '^\s*#' +        let prevlnum = prevnonblank(prevlnum-1) +        if !prevlnum +            return previndent +        endif +    endwhile + +    " Continuation of a line that wasn't indented +    let prevline = getline(prevlnum) +    if prevline =~ '^\k\+.*\\\s*$' +        return shiftwidth()  +    endif + +    " Continuation of a line that was indented +    if prevline =~ '\k\+.*\\\s*$' +        return indent(prevlnum) +    endif + +    " Indent the next line if previous line contained a start of a block +    " definition ('{' or '('). +    if prevline =~ '^\k\+[^#]*{}\@!\s*$' " TODO || prevline =~ '^\k\+[^#]*()\@!\s*$' +        return shiftwidth() +    endif + +    " Match inside of a block +    if s:IsInBlock(v:lnum) +        if prevline =~ "^\k\+.*$" +            return shiftwidth() +        else +            return indent(prevlnum) +        endif +    endif + +    return 0  +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/html.vim b/indent/html.vim index 1e5691f7..9fb6886a 100644 --- a/indent/html.vim +++ b/indent/html.vim @@ -1,3 +1,1059 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent script for HTML +" Header: "{{{ +" Maintainer:	Bram Moolenaar +" Original Author: Andy Wokula <anwoku@yahoo.de> +" Last Change:	2017 Jun 13 +" Version:	1.0 +" Description:	HTML indent script with cached state for faster indenting on a +"		range of lines. +"		Supports template systems through hooks. +"		Supports Closure stylesheets. +" +" Credits: +"	indent/html.vim (2006 Jun 05) from J. Zellner +"	indent/css.vim (2006 Dec 20) from N. Weibull +" +" History: +" 2014 June	(v1.0) overhaul (Bram) +" 2012 Oct 21	(v0.9) added support for shiftwidth() +" 2011 Sep 09	(v0.8) added HTML5 tags (thx to J. Zuckerman) +" 2008 Apr 28	(v0.6) revised customization +" 2008 Mar 09	(v0.5) fixed 'indk' issue (thx to C.J. Robinson) +"}}} + +" Init Folklore, check user settings (2nd time ++) +if exists("b:did_indent") "{{{ +  finish +endif + +" Load the Javascript indent script first, it defines GetJavascriptIndent(). +" Undo the rest. +" Load base python indent. +if !exists('*GetJavascriptIndent') +  runtime! indent/javascript.vim +endif +let b:did_indent = 1 + +setlocal indentexpr=HtmlIndent() +setlocal indentkeys=o,O,<Return>,<>>,{,},!^F + +" Needed for % to work when finding start/end of a tag. +setlocal matchpairs+=<:> + +let b:undo_indent = "setlocal inde< indk<" + +" b:hi_indent keeps state to speed up indenting consecutive lines. +let b:hi_indent = {"lnum": -1} + +"""""" Code below this is loaded only once. """"" +if exists("*HtmlIndent") && !exists('g:force_reload_html') +  call HtmlIndent_CheckUserSettings() +  finish +endif + +" Allow for line continuation below. +let s:cpo_save = &cpo +set cpo-=C +"}}} + +" Check and process settings from b:html_indent and g:html_indent... variables. +" Prefer using buffer-local settings over global settings, so that there can +" be defaults for all HTML files and exceptions for specific types of HTML +" files. +func! HtmlIndent_CheckUserSettings() +  "{{{ +  let inctags = '' +  if exists("b:html_indent_inctags") +    let inctags = b:html_indent_inctags +  elseif exists("g:html_indent_inctags") +    let inctags = g:html_indent_inctags +  endif +  let b:hi_tags = {} +  if len(inctags) > 0 +    call s:AddITags(b:hi_tags, split(inctags, ",")) +  endif + +  let autotags = '' +  if exists("b:html_indent_autotags") +    let autotags = b:html_indent_autotags +  elseif exists("g:html_indent_autotags") +    let autotags = g:html_indent_autotags +  endif +  let b:hi_removed_tags = {} +  if len(autotags) > 0 +    call s:RemoveITags(b:hi_removed_tags, split(autotags, ",")) +  endif + +  " Syntax names indicating being inside a string of an attribute value. +  let string_names = [] +  if exists("b:html_indent_string_names") +    let string_names = b:html_indent_string_names +  elseif exists("g:html_indent_string_names") +    let string_names = g:html_indent_string_names +  endif +  let b:hi_insideStringNames = ['htmlString'] +  if len(string_names) > 0 +    for s in string_names +      call add(b:hi_insideStringNames, s) +    endfor +  endif + +  " Syntax names indicating being inside a tag. +  let tag_names = [] +  if exists("b:html_indent_tag_names") +    let tag_names = b:html_indent_tag_names +  elseif exists("g:html_indent_tag_names") +    let tag_names = g:html_indent_tag_names +  endif +  let b:hi_insideTagNames = ['htmlTag', 'htmlScriptTag'] +  if len(tag_names) > 0 +    for s in tag_names +      call add(b:hi_insideTagNames, s) +    endfor +  endif + +  let indone = {"zero": 0 +              \,"auto": "indent(prevnonblank(v:lnum-1))" +              \,"inc": "b:hi_indent.blocktagind + shiftwidth()"} + +  let script1 = '' +  if exists("b:html_indent_script1") +    let script1 = b:html_indent_script1 +  elseif exists("g:html_indent_script1") +    let script1 = g:html_indent_script1 +  endif +  if len(script1) > 0 +    let b:hi_js1indent = get(indone, script1, indone.zero) +  else +    let b:hi_js1indent = 0 +  endif + +  let style1 = '' +  if exists("b:html_indent_style1") +    let style1 = b:html_indent_style1 +  elseif exists("g:html_indent_style1") +    let style1 = g:html_indent_style1 +  endif +  if len(style1) > 0 +    let b:hi_css1indent = get(indone, style1, indone.zero) +  else +    let b:hi_css1indent = 0 +  endif + +  if !exists('b:html_indent_line_limit') +    if exists('g:html_indent_line_limit') +      let b:html_indent_line_limit = g:html_indent_line_limit +    else +      let b:html_indent_line_limit = 200 +    endif +  endif +endfunc "}}} + +" Init Script Vars +"{{{ +let b:hi_lasttick = 0 +let b:hi_newstate = {} +let s:countonly = 0 + "}}} + +" Fill the s:indent_tags dict with known tags. +" The key is "tagname" or "/tagname".  {{{ +" The value is: +" 1   opening tag +" 2   "pre" +" 3   "script" +" 4   "style" +" 5   comment start +" 6   conditional comment start +" -1  closing tag +" -2  "/pre" +" -3  "/script" +" -4  "/style" +" -5  comment end +" -6  conditional comment end +let s:indent_tags = {} +let s:endtags = [0,0,0,0,0,0,0]   " long enough for the highest index +"}}} + +" Add a list of tag names for a pair of <tag> </tag> to "tags". +func! s:AddITags(tags, taglist) +  "{{{ +  for itag in a:taglist +    let a:tags[itag] = 1 +    let a:tags['/' . itag] = -1 +  endfor +endfunc "}}} + +" Take a list of tag name pairs that are not to be used as tag pairs. +func! s:RemoveITags(tags, taglist) +  "{{{ +  for itag in a:taglist +    let a:tags[itag] = 1 +    let a:tags['/' . itag] = 1 +  endfor +endfunc "}}} + +" Add a block tag, that is a tag with a different kind of indenting. +func! s:AddBlockTag(tag, id, ...) +  "{{{ +  if !(a:id >= 2 && a:id < len(s:endtags)) +    echoerr 'AddBlockTag ' . a:id +    return +  endif +  let s:indent_tags[a:tag] = a:id +  if a:0 == 0 +    let s:indent_tags['/' . a:tag] = -a:id +    let s:endtags[a:id] = "</" . a:tag . ">" +  else +    let s:indent_tags[a:1] = -a:id +    let s:endtags[a:id] = a:1 +  endif +endfunc "}}} + +" Add known tag pairs. +" Self-closing tags and tags that are sometimes {{{ +" self-closing (e.g., <p>) are not here (when encountering </p> we can find +" the matching <p>, but not the other way around). +" Old HTML tags: +call s:AddITags(s:indent_tags, [ +    \ 'a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', +    \ 'blockquote', 'body', 'button', 'caption', 'center', 'cite', 'code', +    \ 'colgroup', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font', +    \ 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', +    \ 'i', 'iframe', 'ins', 'kbd', 'label', 'legend', 'li', +    \ 'map', 'menu', 'noframes', 'noscript', 'object', 'ol', +    \ 'optgroup', 'q', 's', 'samp', 'select', 'small', 'span', 'strong', 'sub', +    \ 'sup', 'table', 'textarea', 'title', 'tt', 'u', 'ul', 'var', 'th', 'td', +    \ 'tr', 'tbody', 'tfoot', 'thead']) + +" New HTML5 elements: +call s:AddITags(s:indent_tags, [ +    \ 'area', 'article', 'aside', 'audio', 'bdi', 'canvas', +    \ 'command', 'data', 'datalist', 'details', 'embed', 'figcaption', +    \ 'figure', 'footer', 'header', 'keygen', 'mark', 'meter', 'nav', 'output', +    \ 'progress', 'rp', 'rt', 'ruby', 'section', 'source', 'summary', 'svg',  +    \ 'time', 'track', 'video', 'wbr']) + +" Tags added for web components: +call s:AddITags(s:indent_tags, [ +    \ 'content', 'shadow', 'template']) +"}}} + +" Add Block Tags: these contain alien content +"{{{ +call s:AddBlockTag('pre', 2) +call s:AddBlockTag('script', 3) +call s:AddBlockTag('style', 4) +call s:AddBlockTag('<!--', 5, '-->') +call s:AddBlockTag('<!--[', 6, '![endif]-->') +"}}} + +" Return non-zero when "tagname" is an opening tag, not being a block tag, for +" which there should be a closing tag.  Can be used by scripts that include +" HTML indenting. +func! HtmlIndent_IsOpenTag(tagname) +  "{{{ +  if get(s:indent_tags, a:tagname) == 1 +    return 1 +  endif +  return get(b:hi_tags, a:tagname) == 1 +endfunc "}}} + +" Get the value for "tagname", taking care of buffer-local tags. +func! s:get_tag(tagname) +  "{{{ +  let i = get(s:indent_tags, a:tagname) +  if (i == 1 || i == -1) && get(b:hi_removed_tags, a:tagname) != 0 +    return 0 +  endif +  if i == 0 +    let i = get(b:hi_tags, a:tagname) +  endif +  return i +endfunc "}}} + +" Count the number of start and end tags in "text". +func! s:CountITags(text) +  "{{{ +  " Store the result in s:curind and s:nextrel. +  let s:curind = 0  " relative indent steps for current line [unit &sw]: +  let s:nextrel = 0  " relative indent steps for next line [unit &sw]: +  let s:block = 0		" assume starting outside of a block +  let s:countonly = 1	" don't change state +  call substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') +  let s:countonly = 0 +endfunc "}}} + +" Count the number of start and end tags in text. +func! s:CountTagsAndState(text) +  "{{{ +  " Store the result in s:curind and s:nextrel.  Update b:hi_newstate.block. +  let s:curind = 0  " relative indent steps for current line [unit &sw]: +  let s:nextrel = 0  " relative indent steps for next line [unit &sw]: + +  let s:block = b:hi_newstate.block +  let tmp = substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') +  if s:block == 3 +    let b:hi_newstate.scripttype = s:GetScriptType(matchstr(tmp, '\C.*<SCRIPT\>\zs[^>]*')) +  endif +  let b:hi_newstate.block = s:block +endfunc "}}} + +" Used by s:CountITags() and s:CountTagsAndState(). +func! s:CheckTag(itag) +  "{{{ +  " Returns an empty string or "SCRIPT". +  " a:itag can be "tag" or "/tag" or "<!--" or "-->" +  if (s:CheckCustomTag(a:itag)) +    return "" +  endif +  let ind = s:get_tag(a:itag) +  if ind == -1 +    " closing tag +    if s:block != 0 +      " ignore itag within a block +      return "" +    endif +    if s:nextrel == 0 +      let s:curind -= 1 +    else +      let s:nextrel -= 1 +    endif +  elseif ind == 1 +    " opening tag +    if s:block != 0 +      return "" +    endif +    let s:nextrel += 1 +  elseif ind != 0 +    " block-tag (opening or closing) +    return s:CheckBlockTag(a:itag, ind) +  " else ind==0 (other tag found): keep indent +  endif +  return "" +endfunc "}}} + +" Used by s:CheckTag(). Returns an empty string or "SCRIPT". +func! s:CheckBlockTag(blocktag, ind) +  "{{{ +  if a:ind > 0 +    " a block starts here +    if s:block != 0 +      " already in a block (nesting) - ignore +      " especially ignore comments after other blocktags +      return "" +    endif +    let s:block = a:ind		" block type +    if s:countonly +      return "" +    endif +    let b:hi_newstate.blocklnr = v:lnum +    " save allover indent for the endtag +    let b:hi_newstate.blocktagind = b:hi_indent.baseindent + (s:nextrel + s:curind) * shiftwidth() +    if a:ind == 3 +      return "SCRIPT"    " all except this must be lowercase +      " line is to be checked again for the type attribute +    endif +  else +    let s:block = 0 +    " we get here if starting and closing a block-tag on the same line +  endif +  return "" +endfunc "}}} + +" Used by s:CheckTag(). +func! s:CheckCustomTag(ctag) +  "{{{ +  " Returns 1 if ctag is the tag for a custom element, 0 otherwise. +  " a:ctag can be "tag" or "/tag" or "<!--" or "-->" +  let pattern = '\%\(\w\+-\)\+\w\+' +  if match(a:ctag, pattern) == -1 +    return 0 +  endif +  if matchstr(a:ctag, '\/\ze.\+') == "/" +    " closing tag +    if s:block != 0 +      " ignore ctag within a block +      return 1 +    endif +    if s:nextrel == 0 +      let s:curind -= 1 +    else +      let s:nextrel -= 1 +    endif +  else +    " opening tag +    if s:block != 0 +      return 1 +    endif +    let s:nextrel += 1 +  endif +  return 1 +endfunc "}}} + +" Return the <script> type: either "javascript" or "" +func! s:GetScriptType(str) +  "{{{ +  if a:str == "" || a:str =~ "java" +    return "javascript" +  else +    return "" +  endif +endfunc "}}} + +" Look back in the file, starting at a:lnum - 1, to compute a state for the +" start of line a:lnum.  Return the new state. +func! s:FreshState(lnum) +  "{{{ +  " A state is to know ALL relevant details about the +  " lines 1..a:lnum-1, initial calculating (here!) can be slow, but updating is +  " fast (incremental). +  " TODO: this should be split up in detecting the block type and computing the +  " indent for the block type, so that when we do not know the indent we do +  " not need to clear the whole state and re-detect the block type again. +  " State: +  "	lnum		last indented line == prevnonblank(a:lnum - 1) +  "	block = 0	a:lnum located within special tag: 0:none, 2:<pre>, +  "			3:<script>, 4:<style>, 5:<!--, 6:<!--[ +  "	baseindent	use this indent for line a:lnum as a start - kind of +  "			autoindent (if block==0) +  "	scripttype = ''	type attribute of a script tag (if block==3) +  "	blocktagind	indent for current opening (get) and closing (set) +  "			blocktag (if block!=0) +  "	blocklnr	lnum of starting blocktag (if block!=0) +  "	inattr		line {lnum} starts with attributes of a tag +  let state = {} +  let state.lnum = prevnonblank(a:lnum - 1) +  let state.scripttype = "" +  let state.blocktagind = -1 +  let state.block = 0 +  let state.baseindent = 0 +  let state.blocklnr = 0 +  let state.inattr = 0 + +  if state.lnum == 0 +    return state +  endif + +  " Heuristic: +  " remember startline state.lnum +  " look back for <pre, </pre, <script, </script, <style, </style tags +  " remember stopline +  " if opening tag found, +  "	assume a:lnum within block +  " else +  "	look back in result range (stopline, startline) for comment +  "	    \ delimiters (<!--, -->) +  "	if comment opener found, +  "	    assume a:lnum within comment +  "	else +  "	    assume usual html for a:lnum +  "	    if a:lnum-1 has a closing comment +  "		look back to get indent of comment opener +  " FI + +  " look back for a blocktag +  let stopline2 = v:lnum + 1 +  if has_key(b:hi_indent, 'block') && b:hi_indent.block > 5 +    let [stopline2, stopcol2] = searchpos('<!--', 'bnW') +  endif +  let [stopline, stopcol] = searchpos('\c<\zs\/\=\%(pre\>\|script\>\|style\>\)', "bnW") +  if stopline > 0 && stopline < stopline2 +    " ugly ... why isn't there searchstr() +    let tagline = tolower(getline(stopline)) +    let blocktag = matchstr(tagline, '\/\=\%(pre\>\|script\>\|style\>\)', stopcol - 1) +    if blocktag[0] != "/" +      " opening tag found, assume a:lnum within block +      let state.block = s:indent_tags[blocktag] +      if state.block == 3 +        let state.scripttype = s:GetScriptType(matchstr(tagline, '\>[^>]*', stopcol)) +      endif +      let state.blocklnr = stopline +      " check preceding tags in the line: +      call s:CountITags(tagline[: stopcol-2]) +      let state.blocktagind = indent(stopline) + (s:curind + s:nextrel) * shiftwidth() +      return state +    elseif stopline == state.lnum +      " handle special case: previous line (= state.lnum) contains a +      " closing blocktag which is preceded by line-noise; +      " blocktag == "/..." +      let swendtag = match(tagline, '^\s*</') >= 0 +      if !swendtag +        let [bline, bcol] = searchpos('<'.blocktag[1:].'\>', "bnW") +        call s:CountITags(tolower(getline(bline)[: bcol-2])) +        let state.baseindent = indent(bline) + (s:curind + s:nextrel) * shiftwidth() +        return state +      endif +    endif +  endif +  if stopline > stopline2 +    let stopline = stopline2 +    let stopcol = stopcol2 +  endif + +  " else look back for comment +  let [comlnum, comcol, found] = searchpos('\(<!--\[\)\|\(<!--\)\|-->', 'bpnW', stopline) +  if found == 2 || found == 3 +    " comment opener found, assume a:lnum within comment +    let state.block = (found == 3 ? 5 : 6) +    let state.blocklnr = comlnum +    " check preceding tags in the line: +    call s:CountITags(tolower(getline(comlnum)[: comcol-2])) +    if found == 2 +      let state.baseindent = b:hi_indent.baseindent +    endif +    let state.blocktagind = indent(comlnum) + (s:curind + s:nextrel) * shiftwidth() +    return state +  endif + +  " else within usual HTML +  let text = tolower(getline(state.lnum)) + +  " Check a:lnum-1 for closing comment (we need indent from the opening line). +  " Not when other tags follow (might be --> inside a string). +  let comcol = stridx(text, '-->') +  if comcol >= 0 && match(text, '[<>]', comcol) <= 0 +    call cursor(state.lnum, comcol + 1) +    let [comlnum, comcol] = searchpos('<!--', 'bW') +    if comlnum == state.lnum +      let text = text[: comcol-2] +    else +      let text = tolower(getline(comlnum)[: comcol-2]) +    endif +    call s:CountITags(text) +    let state.baseindent = indent(comlnum) + (s:curind + s:nextrel) * shiftwidth() +    " TODO check tags that follow "-->" +    return state +  endif + +  " Check if the previous line starts with end tag. +  let swendtag = match(text, '^\s*</') >= 0 + +  " If previous line ended in a closing tag, line up with the opening tag. +  if !swendtag && text =~ '</\w\+\s*>\s*$' +    call cursor(state.lnum, 99999) +    normal! F< +    let start_lnum = HtmlIndent_FindStartTag() +    if start_lnum > 0 +      let state.baseindent = indent(start_lnum) +      if col('.') > 2 +        " check for tags before the matching opening tag. +        let text = getline(start_lnum) +        let swendtag = match(text, '^\s*</') >= 0 +        call s:CountITags(text[: col('.') - 2]) +        let state.baseindent += s:nextrel * shiftwidth() +        if !swendtag +          let state.baseindent += s:curind * shiftwidth() +        endif +      endif +      return state +    endif +  endif + +  " Else: no comments. Skip backwards to find the tag we're inside. +  let [state.lnum, found] = HtmlIndent_FindTagStart(state.lnum) +  " Check if that line starts with end tag. +  let text = getline(state.lnum) +  let swendtag = match(text, '^\s*</') >= 0 +  call s:CountITags(tolower(text)) +  let state.baseindent = indent(state.lnum) + s:nextrel * shiftwidth() +  if !swendtag +    let state.baseindent += s:curind * shiftwidth() +  endif +  return state +endfunc "}}} + +" Indent inside a <pre> block: Keep indent as-is. +func! s:Alien2() +  "{{{ +  return -1 +endfunc "}}} + +" Return the indent inside a <script> block for javascript. +func! s:Alien3() +  "{{{ +  let lnum = prevnonblank(v:lnum - 1) +  while lnum > 1 && getline(lnum) =~ '^\s*/[/*]' +    " Skip over comments to avoid that cindent() aligns with the <script> tag +    let lnum = prevnonblank(lnum - 1) +  endwhile +  if lnum == b:hi_indent.blocklnr +    " indent for the first line after <script> +    return eval(b:hi_js1indent) +  endif +  if b:hi_indent.scripttype == "javascript" +    return GetJavascriptIndent() +  else +    return -1 +  endif +endfunc "}}} + +" Return the indent inside a <style> block. +func! s:Alien4() +  "{{{ +  if prevnonblank(v:lnum-1) == b:hi_indent.blocklnr +    " indent for first content line +    return eval(b:hi_css1indent) +  endif +  return s:CSSIndent() +endfunc "}}} + +" Indending inside a <style> block.  Returns the indent. +func! s:CSSIndent() +  "{{{ +  " This handles standard CSS and also Closure stylesheets where special lines +  " start with @. +  " When the line starts with '*' or the previous line starts with "/*" +  " and does not end in "*/", use C indenting to format the comment. +  " Adopted $VIMRUNTIME/indent/css.vim +  let curtext = getline(v:lnum) +  if curtext =~ '^\s*[*]' +        \ || (v:lnum > 1 && getline(v:lnum - 1) =~ '\s*/\*' +        \     && getline(v:lnum - 1) !~ '\*/\s*$') +    return cindent(v:lnum) +  endif + +  let min_lnum = b:hi_indent.blocklnr +  let prev_lnum = s:CssPrevNonComment(v:lnum - 1, min_lnum) +  let [prev_lnum, found] = HtmlIndent_FindTagStart(prev_lnum) +  if prev_lnum <= min_lnum +    " Just below the <style> tag, indent for first content line after comments. +    return eval(b:hi_css1indent) +  endif + +  " If the current line starts with "}" align with it's match. +  if curtext =~ '^\s*}' +    call cursor(v:lnum, 1) +    try +      normal! % +      " Found the matching "{", align with it after skipping unfinished lines. +      let align_lnum = s:CssFirstUnfinished(line('.'), min_lnum) +      return indent(align_lnum) +    catch +      " can't find it, try something else, but it's most likely going to be +      " wrong +    endtry +  endif + +  " add indent after { +  let brace_counts = HtmlIndent_CountBraces(prev_lnum) +  let extra = brace_counts.c_open * shiftwidth() + +  let prev_text = getline(prev_lnum) +  let below_end_brace = prev_text =~ '}\s*$' + +  " Search back to align with the first line that's unfinished. +  let align_lnum = s:CssFirstUnfinished(prev_lnum, min_lnum) + +  " Handle continuation lines if aligning with previous line and not after a +  " "}". +  if extra == 0 && align_lnum == prev_lnum && !below_end_brace +    let prev_hasfield = prev_text =~ '^\s*[a-zA-Z0-9-]\+:' +    let prev_special = prev_text =~ '^\s*\(/\*\|@\)' +    if curtext =~ '^\s*\(/\*\|@\)' +      " if the current line is not a comment or starts with @ (used by template +      " systems) reduce indent if previous line is a continuation line +      if !prev_hasfield && !prev_special +        let extra = -shiftwidth() +      endif +    else +      let cur_hasfield = curtext =~ '^\s*[a-zA-Z0-9-]\+:' +      let prev_unfinished = s:CssUnfinished(prev_text) +      if !cur_hasfield && (prev_hasfield || prev_unfinished) +        " Continuation line has extra indent if the previous line was not a +        " continuation line. +        let extra = shiftwidth() +        " Align with @if +        if prev_text =~ '^\s*@if ' +          let extra = 4 +        endif +      elseif cur_hasfield && !prev_hasfield && !prev_special +        " less indent below a continuation line +        let extra = -shiftwidth() +      endif +    endif +  endif + +  if below_end_brace +    " find matching {, if that line starts with @ it's not the start of a rule +    " but something else from a template system +    call cursor(prev_lnum, 1) +    call search('}\s*$') +    try +      normal! % +      " Found the matching "{", align with it. +      let align_lnum = s:CssFirstUnfinished(line('.'), min_lnum) +      let special = getline(align_lnum) =~ '^\s*@' +    catch +      let special = 0 +    endtry +    if special +      " do not reduce indent below @{ ... } +      if extra < 0 +        let extra += shiftwidth() +      endif +    else +      let extra -= (brace_counts.c_close - (prev_text =~ '^\s*}')) * shiftwidth() +    endif +  endif + +  " if no extra indent yet... +  if extra == 0 +    if brace_counts.p_open > brace_counts.p_close +      " previous line has more ( than ): add a shiftwidth +      let extra = shiftwidth() +    elseif brace_counts.p_open < brace_counts.p_close +      " previous line has more ) than (: subtract a shiftwidth +      let extra = -shiftwidth() +    endif +  endif + +  return indent(align_lnum) + extra +endfunc "}}} + +" Inside <style>: Whether a line is unfinished. +func! s:CssUnfinished(text) +  "{{{ +  return a:text =~ '\s\(||\|&&\|:\)\s*$' +endfunc "}}} + +" Search back for the first unfinished line above "lnum". +func! s:CssFirstUnfinished(lnum, min_lnum) +  "{{{ +  let align_lnum = a:lnum +  while align_lnum > a:min_lnum && s:CssUnfinished(getline(align_lnum - 1)) +    let align_lnum -= 1 +  endwhile +  return align_lnum +endfunc "}}} + +" Find the non-empty line at or before "lnum" that is not a comment. +func! s:CssPrevNonComment(lnum, stopline) +  "{{{ +  " caller starts from a line a:lnum + 1 that is not a comment +  let lnum = prevnonblank(a:lnum) +  while 1 +    let ccol = match(getline(lnum), '\*/') +    if ccol < 0 +      " No comment end thus it's something else. +      return lnum +    endif +    call cursor(lnum, ccol + 1) +    " Search back for the /* that starts the comment +    let lnum = search('/\*', 'bW', a:stopline) +    if indent(".") == virtcol(".") - 1 +      " The  found /* is at the start of the line. Now go back to the line +      " above it and again check if it is a comment. +      let lnum = prevnonblank(lnum - 1) +    else +      " /* is after something else, thus it's not a comment line. +      return lnum +    endif +  endwhile +endfunc "}}} + +" Check the number of {} and () in line "lnum". Return a dict with the counts. +func! HtmlIndent_CountBraces(lnum) +  "{{{ +  let brs = substitute(getline(a:lnum), '[''"].\{-}[''"]\|/\*.\{-}\*/\|/\*.*$\|[^{}()]', '', 'g') +  let c_open = 0 +  let c_close = 0 +  let p_open = 0 +  let p_close = 0 +  for brace in split(brs, '\zs') +    if brace == "{" +      let c_open += 1 +    elseif brace == "}" +      if c_open > 0 +        let c_open -= 1 +      else +        let c_close += 1 +      endif +    elseif brace == '(' +      let p_open += 1 +    elseif brace == ')' +      if p_open > 0 +        let p_open -= 1 +      else +        let p_close += 1 +      endif +    endif +  endfor +  return {'c_open': c_open, +        \ 'c_close': c_close, +        \ 'p_open': p_open, +        \ 'p_close': p_close} +endfunc "}}} + +" Return the indent for a comment: <!-- --> +func! s:Alien5() +  "{{{ +  let curtext = getline(v:lnum) +  if curtext =~ '^\s*\zs-->' +    " current line starts with end of comment, line up with comment start. +    call cursor(v:lnum, 0) +    let lnum = search('<!--', 'b') +    if lnum > 0 +      " TODO: what if <!-- is not at the start of the line? +      return indent(lnum) +    endif + +    " Strange, can't find it. +    return -1 +  endif + +  let prevlnum = prevnonblank(v:lnum - 1) +  let prevtext = getline(prevlnum) +  let idx = match(prevtext, '^\s*\zs<!--') +  if idx >= 0 +    " just below comment start, add a shiftwidth +    return idx + shiftwidth() +  endif + +  " Some files add 4 spaces just below a TODO line.  It's difficult to detect +  " the end of the TODO, so let's not do that. + +  " Align with the previous non-blank line. +  return indent(prevlnum) +endfunc "}}} + +" Return the indent for conditional comment: <!--[ ![endif]--> +func! s:Alien6() +  "{{{ +  let curtext = getline(v:lnum) +  if curtext =~ '\s*\zs<!\[endif\]-->' +    " current line starts with end of comment, line up with comment start. +    let lnum = search('<!--', 'bn') +    if lnum > 0 +      return indent(lnum) +    endif +  endif +  return b:hi_indent.baseindent + shiftwidth() +endfunc "}}} + +" When the "lnum" line ends in ">" find the line containing the matching "<". +func! HtmlIndent_FindTagStart(lnum) +  "{{{ +  " Avoids using the indent of a continuation line. +  " Moves the cursor. +  " Return two values: +  " - the matching line number or "lnum". +  " - a flag indicating whether we found the end of a tag. +  " This method is global so that HTML-like indenters can use it. +  " To avoid matching " > " or " < " inside a string require that the opening +  " "<" is followed by a word character and the closing ">" comes after a +  " non-white character. +  let idx = match(getline(a:lnum), '\S>\s*$') +  if idx > 0 +    call cursor(a:lnum, idx) +    let lnum = searchpair('<\w', '' , '\S>', 'bW', '', max([a:lnum - b:html_indent_line_limit, 0])) +    if lnum > 0 +      return [lnum, 1] +    endif +  endif +  return [a:lnum, 0] +endfunc "}}} + +" Find the unclosed start tag from the current cursor position. +func! HtmlIndent_FindStartTag() +  "{{{ +  " The cursor must be on or before a closing tag. +  " If found, positions the cursor at the match and returns the line number. +  " Otherwise returns 0. +  let tagname = matchstr(getline('.')[col('.') - 1:], '</\zs\w\+\ze') +  let start_lnum = searchpair('<' . tagname . '\>', '', '</' . tagname . '\>', 'bW') +  if start_lnum > 0 +    return start_lnum +  endif +  return 0 +endfunc "}}} + +" Moves the cursor from a "<" to the matching ">". +func! HtmlIndent_FindTagEnd() +  "{{{ +  " Call this with the cursor on the "<" of a start tag. +  " This will move the cursor to the ">" of the matching end tag or, when it's +  " a self-closing tag, to the matching ">". +  " Limited to look up to b:html_indent_line_limit lines away. +  let text = getline('.') +  let tagname = matchstr(text, '\w\+\|!--', col('.')) +  if tagname == '!--' +    call search('--\zs>') +  elseif s:get_tag('/' . tagname) != 0 +    " tag with a closing tag, find matching "</tag>" +    call searchpair('<' . tagname, '', '</' . tagname . '\zs>', 'W', '', line('.') + b:html_indent_line_limit) +  else +    " self-closing tag, find the ">" +    call search('\S\zs>') +  endif +endfunc "}}} + +" Indenting inside a start tag. Return the correct indent or -1 if unknown. +func! s:InsideTag(foundHtmlString) +  "{{{ +  if a:foundHtmlString +    " Inside an attribute string. +    " Align with the previous line or use an external function. +    let lnum = v:lnum - 1 +    if lnum > 1 +      if exists('b:html_indent_tag_string_func') +        return b:html_indent_tag_string_func(lnum) +      endif +      return indent(lnum) +    endif +  endif + +  " Should be another attribute: " attr="val".  Align with the previous +  " attribute start. +  let lnum = v:lnum +  while lnum > 1 +    let lnum -= 1 +    let text = getline(lnum) +    " Find a match with one of these, align with "attr": +    "       attr= +    "  <tag attr= +    "  text<tag attr= +    "  <tag>text</tag>text<tag attr= +    " For long lines search for the first match, finding the last match +    " gets very slow. +    if len(text) < 300 +      let idx = match(text, '.*\s\zs[_a-zA-Z0-9-]\+="') +    else +      let idx = match(text, '\s\zs[_a-zA-Z0-9-]\+="') +    endif +    if idx > 0 +      " Found the attribute.  TODO: assumes spaces, no Tabs. +      return idx +    endif +  endwhile +  return -1 +endfunc "}}} + +" THE MAIN INDENT FUNCTION. Return the amount of indent for v:lnum. +func! HtmlIndent() +  "{{{ +  if prevnonblank(v:lnum - 1) < 1 +    " First non-blank line has no indent. +    return 0 +  endif + +  let curtext = tolower(getline(v:lnum)) +  let indentunit = shiftwidth() + +  let b:hi_newstate = {} +  let b:hi_newstate.lnum = v:lnum + +  " When syntax HL is enabled, detect we are inside a tag.  Indenting inside +  " a tag works very differently. Do not do this when the line starts with +  " "<", it gets the "htmlTag" ID but we are not inside a tag then. +  if curtext !~ '^\s*<' +    normal! ^ +    let stack = synstack(v:lnum, col('.'))  " assumes there are no tabs +    let foundHtmlString = 0 +    for synid in reverse(stack) +      let name = synIDattr(synid, "name") +      if index(b:hi_insideStringNames, name) >= 0 +        let foundHtmlString = 1 +      elseif index(b:hi_insideTagNames, name) >= 0 +        " Yes, we are inside a tag. +        let indent = s:InsideTag(foundHtmlString) +        if indent >= 0 +          " Do not keep the state. TODO: could keep the block type. +          let b:hi_indent.lnum = 0 +          return indent +        endif +      endif +    endfor +  endif + +  " does the line start with a closing tag? +  let swendtag = match(curtext, '^\s*</') >= 0 + +  if prevnonblank(v:lnum - 1) == b:hi_indent.lnum && b:hi_lasttick == b:changedtick - 1 +    " use state (continue from previous line) +  else +    " start over (know nothing) +    let b:hi_indent = s:FreshState(v:lnum) +  endif + +  if b:hi_indent.block >= 2 +    " within block +    let endtag = s:endtags[b:hi_indent.block] +    let blockend = stridx(curtext, endtag) +    if blockend >= 0 +      " block ends here +      let b:hi_newstate.block = 0 +      " calc indent for REST OF LINE (may start more blocks): +      call s:CountTagsAndState(strpart(curtext, blockend + strlen(endtag))) +      if swendtag && b:hi_indent.block != 5 +        let indent = b:hi_indent.blocktagind + s:curind * indentunit +        let b:hi_newstate.baseindent = indent + s:nextrel * indentunit +      else +        let indent = s:Alien{b:hi_indent.block}() +        let b:hi_newstate.baseindent = b:hi_indent.blocktagind + s:nextrel * indentunit +      endif +    else +      " block continues +      " indent this line with alien method +      let indent = s:Alien{b:hi_indent.block}() +    endif +  else +    " not within a block - within usual html +    let b:hi_newstate.block = b:hi_indent.block +    if swendtag +      " The current line starts with an end tag, align with its start tag. +      call cursor(v:lnum, 1) +      let start_lnum = HtmlIndent_FindStartTag() +      if start_lnum > 0 +        " check for the line starting with something inside a tag: +        " <sometag               <- align here +        "    attr=val><open>     not here +        let text = getline(start_lnum) +        let angle = matchstr(text, '[<>]') +        if angle == '>' +          call cursor(start_lnum, 1) +          normal! f>% +          let start_lnum = line('.') +          let text = getline(start_lnum) +        endif + +        let indent = indent(start_lnum) +        if col('.') > 2 +          let swendtag = match(text, '^\s*</') >= 0 +          call s:CountITags(text[: col('.') - 2]) +          let indent += s:nextrel * shiftwidth() +          if !swendtag +            let indent += s:curind * shiftwidth() +          endif +        endif +      else +        " not sure what to do +        let indent = b:hi_indent.baseindent +      endif +      let b:hi_newstate.baseindent = indent +    else +      call s:CountTagsAndState(curtext) +      let indent = b:hi_indent.baseindent +      let b:hi_newstate.baseindent = indent + (s:curind + s:nextrel) * indentunit +    endif +  endif + +  let b:hi_lasttick = b:changedtick +  call extend(b:hi_indent, b:hi_newstate, "force") +  return indent +endfunc "}}} + +" Check user settings when loading this script the first time. +call HtmlIndent_CheckUserSettings() + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: fdm=marker ts=8 sw=2 tw=78 + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'html5') == -1  " Description:      HTML5 and inline SVG indenter diff --git a/indent/htmldjango.vim b/indent/htmldjango.vim new file mode 100644 index 00000000..0182bdce --- /dev/null +++ b/indent/htmldjango.vim @@ -0,0 +1,16 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Django HTML template +" Maintainer:	Dave Hodder <dmh@dmh.org.uk> +" Last Change:	2007 Jan 25 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Use HTML formatting rules. +runtime! indent/html.vim + +endif diff --git a/indent/idlang.vim b/indent/idlang.vim new file mode 100644 index 00000000..845ad347 --- /dev/null +++ b/indent/idlang.vim @@ -0,0 +1,66 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" IDL (Interactive Data Language) indent file. +" Language: IDL (ft=idlang) +" Last change:	2017 Jun 13 +" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +setlocal indentkeys=o,O,0=endif,0=ENDIF,0=endelse,0=ENDELSE,0=endwhile,0=ENDWHILE,0=endfor,0=ENDFOR,0=endrep,0=ENDREP + +setlocal indentexpr=GetIdlangIndent(v:lnum) + +" Only define the function once. +if exists("*GetIdlangIndent") +   finish +endif + +function GetIdlangIndent(lnum) +   " First non-empty line above the current line. +   let pnum = prevnonblank(v:lnum-1) +   " v:lnum is the first non-empty line -- zero indent. +   if pnum == 0 +      return 0 +   endif +   " Second non-empty line above the current line. +   let pnum2 = prevnonblank(pnum-1) + +   " Current indent. +   let curind = indent(pnum) + +   " Indenting of continued lines. +   if getline(pnum) =~ '\$\s*\(;.*\)\=$' +      if getline(pnum2) !~ '\$\s*\(;.*\)\=$' +	 let curind = curind+shiftwidth() +      endif +   else +      if getline(pnum2) =~ '\$\s*\(;.*\)\=$' +	 let curind = curind-shiftwidth() +      endif +   endif + +   " Indenting blocks of statements. +   if getline(v:lnum) =~? '^\s*\(endif\|endelse\|endwhile\|endfor\|endrep\)\>' +      if getline(pnum) =~? 'begin\>' +      elseif indent(v:lnum) > curind-shiftwidth() +	 let curind = curind-shiftwidth() +      else +	 return -1 +      endif +   elseif getline(pnum) =~? 'begin\>' +      if indent(v:lnum) < curind+shiftwidth() +	 let curind = curind+shiftwidth() +      else +	 return -1 +      endif +   endif +   return curind +endfunction + + +endif diff --git a/indent/ishd.vim b/indent/ishd.vim new file mode 100644 index 00000000..203e1bde --- /dev/null +++ b/indent/ishd.vim @@ -0,0 +1,72 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Description:	InstallShield indenter +" Author:	Johannes Zellner <johannes@zellner.org> +" Last Change:	Tue, 27 Apr 2004 14:54:59 CEST + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetIshdIndent(v:lnum) +setlocal indentkeys& +setlocal indentkeys+==else,=elseif,=endif,=end,=begin,<:> +" setlocal indentkeys-=0# + +let b:undo_indent = "setl ai< indentexpr< indentkeys<" + +" Only define the function once. +if exists("*GetIshdIndent") +    finish +endif + +fun! GetIshdIndent(lnum) +    " labels and preprocessor get zero indent immediately +    let this_line = getline(a:lnum) +    let LABELS_OR_PREPROC = '^\s*\(\<\k\+\>:\s*$\|#.*\)' +    let LABELS_OR_PREPROC_EXCEPT = '^\s*\<default\+\>:' +    if this_line =~ LABELS_OR_PREPROC && this_line !~ LABELS_OR_PREPROC_EXCEPT +	return 0 +    endif + +    " Find a non-blank line above the current line. +    " Skip over labels and preprocessor directives. +    let lnum = a:lnum +    while lnum > 0 +	let lnum = prevnonblank(lnum - 1) +	let previous_line = getline(lnum) +	if previous_line !~ LABELS_OR_PREPROC || previous_line =~ LABELS_OR_PREPROC_EXCEPT +	    break +	endif +    endwhile + +    " Hit the start of the file, use zero indent. +    if lnum == 0 +	return 0 +    endif + +    let ind = indent(lnum) + +    " Add +    if previous_line =~ '^\s*\<\(function\|begin\|switch\|case\|default\|if.\{-}then\|else\|elseif\|while\|repeat\)\>' +	let ind = ind + shiftwidth() +    endif + +    " Subtract +    if this_line =~ '^\s*\<endswitch\>' +	let ind = ind - 2 * shiftwidth() +    elseif this_line =~ '^\s*\<\(begin\|end\|endif\|endwhile\|else\|elseif\|until\)\>' +	let ind = ind - shiftwidth() +    elseif this_line =~ '^\s*\<\(case\|default\)\>' +	if previous_line !~ '^\s*\<switch\>' +	    let ind = ind - shiftwidth() +	endif +    endif + +    return ind +endfun + +endif diff --git a/indent/j.vim b/indent/j.vim new file mode 100644 index 00000000..83e60580 --- /dev/null +++ b/indent/j.vim @@ -0,0 +1,54 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	J +" Maintainer:	David Bürgin <676c7473@gmail.com> +" URL:		https://github.com/glts/vim-j +" Last Change:	2015-01-11 + +if exists('b:did_indent') +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetJIndent() +setlocal indentkeys-=0{,0},:,0# +setlocal indentkeys+=0),0<:>,=case.,=catch.,=catchd.,=catcht.,=do.,=else.,=elseif.,=end.,=fcase. + +let b:undo_indent = 'setlocal indentkeys< indentexpr<' + +if exists('*GetJIndent') +  finish +endif + +" If g:j_indent_definitions is true, the bodies of explicit definitions of +" adverbs, conjunctions, and verbs will be indented. Default is false (0). +if !exists('g:j_indent_definitions') +  let g:j_indent_definitions = 0 +endif + +function GetJIndent() abort +  let l:prevlnum = prevnonblank(v:lnum - 1) +  if l:prevlnum == 0 +    return 0 +  endif +  let l:indent = indent(l:prevlnum) +  let l:prevline = getline(l:prevlnum) +  if l:prevline =~# '^\s*\%(case\|catch[dt]\=\|do\|else\%(if\)\=\|fcase\|for\%(_\a\k*\)\=\|if\|select\|try\|whil\%(e\|st\)\)\.\%(\%(\<end\.\)\@!.\)*$' +    " Increase indentation after an initial control word that starts or +    " continues a block and is not terminated by "end." +    let l:indent += shiftwidth() +  elseif g:j_indent_definitions && (l:prevline =~# '\<\%([1-4]\|13\|adverb\|conjunction\|verb\|monad\|dyad\)\s\+\%(:\s*0\|def\s\+0\|define\)\>' || l:prevline =~# '^\s*:\s*$') +    " Increase indentation in explicit definitions of adverbs, conjunctions, +    " and verbs +    let l:indent += shiftwidth() +  endif +  " Decrease indentation in lines that start with either control words that +  " continue or end a block, or the special items ")" and ":" +  if getline(v:lnum) =~# '^\s*\%()\|:\|\%(case\|catch[dt]\=\|do\|else\%(if\)\=\|end\|fcase\)\.\)' +    let l:indent -= shiftwidth() +  endif +  return l:indent +endfunction + +endif diff --git a/indent/java.vim b/indent/java.vim new file mode 100644 index 00000000..a530e65d --- /dev/null +++ b/indent/java.vim @@ -0,0 +1,154 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Java +" Previous Maintainer: Toby Allsopp <toby.allsopp@peace.com> +" Current Maintainer: Hong Xu <hong@topbug.net> +" Homepage: http://www.vim.org/scripts/script.php?script_id=3899 +"           https://github.com/xuhdev/indent-java.vim +" Last Change:	2016 Mar 7 +" Version: 1.1 +" License: Same as Vim. +" Copyright (c) 2012-2016 Hong Xu +" Before 2012, this file was maintained by Toby Allsopp. + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" Indent Java anonymous classes correctly. +setlocal cindent cinoptions& cinoptions+=j1 + +" The "extends" and "implements" lines start off with the wrong indent. +setlocal indentkeys& indentkeys+=0=extends indentkeys+=0=implements + +" Set the function to do the work. +setlocal indentexpr=GetJavaIndent() + +let b:undo_indent = "set cin< cino< indentkeys< indentexpr<" + +" Only define the function once. +if exists("*GetJavaIndent") +  finish +endif + +let s:keepcpo= &cpo +set cpo&vim + +function! SkipJavaBlanksAndComments(startline) +  let lnum = a:startline +  while lnum > 1 +    let lnum = prevnonblank(lnum) +    if getline(lnum) =~ '\*/\s*$' +      while getline(lnum) !~ '/\*' && lnum > 1 +        let lnum = lnum - 1 +      endwhile +      if getline(lnum) =~ '^\s*/\*' +        let lnum = lnum - 1 +      else +        break +      endif +    elseif getline(lnum) =~ '^\s*//' +      let lnum = lnum - 1 +    else +      break +    endif +  endwhile +  return lnum +endfunction + +function GetJavaIndent() + +  " Java is just like C; use the built-in C indenting and then correct a few +  " specific cases. +  let theIndent = cindent(v:lnum) + +  " If we're in the middle of a comment then just trust cindent +  if getline(v:lnum) =~ '^\s*\*' +    return theIndent +  endif + +  " find start of previous line, in case it was a continuation line +  let lnum = SkipJavaBlanksAndComments(v:lnum - 1) + +  " If the previous line starts with '@', we should have the same indent as +  " the previous one +  if getline(lnum) =~ '^\s*@.*$' +    return indent(lnum) +  endif + +  let prev = lnum +  while prev > 1 +    let next_prev = SkipJavaBlanksAndComments(prev - 1) +    if getline(next_prev) !~ ',\s*$' +      break +    endif +    let prev = next_prev +  endwhile + +  " Try to align "throws" lines for methods and "extends" and "implements" for +  " classes. +  if getline(v:lnum) =~ '^\s*\(throws\|extends\|implements\)\>' +        \ && getline(lnum) !~ '^\s*\(throws\|extends\|implements\)\>' +    let theIndent = theIndent + shiftwidth() +  endif + +  " correct for continuation lines of "throws", "implements" and "extends" +  let cont_kw = matchstr(getline(prev), +        \ '^\s*\zs\(throws\|implements\|extends\)\>\ze.*,\s*$') +  if strlen(cont_kw) > 0 +    let amount = strlen(cont_kw) + 1 +    if getline(lnum) !~ ',\s*$' +      let theIndent = theIndent - (amount + shiftwidth()) +      if theIndent < 0 +        let theIndent = 0 +      endif +    elseif prev == lnum +      let theIndent = theIndent + amount +      if cont_kw ==# 'throws' +        let theIndent = theIndent + shiftwidth() +      endif +    endif +  elseif getline(prev) =~ '^\s*\(throws\|implements\|extends\)\>' +        \ && (getline(prev) =~ '{\s*$' +        \  || getline(v:lnum) =~ '^\s*{\s*$') +    let theIndent = theIndent - shiftwidth() +  endif + +  " When the line starts with a }, try aligning it with the matching {, +  " skipping over "throws", "extends" and "implements" clauses. +  if getline(v:lnum) =~ '^\s*}\s*\(//.*\|/\*.*\)\=$' +    call cursor(v:lnum, 1) +    silent normal! % +    let lnum = line('.') +    if lnum < v:lnum +      while lnum > 1 +        let next_lnum = SkipJavaBlanksAndComments(lnum - 1) +        if getline(lnum) !~ '^\s*\(throws\|extends\|implements\)\>' +              \ && getline(next_lnum) !~ ',\s*$' +          break +        endif +        let lnum = prevnonblank(next_lnum) +      endwhile +      return indent(lnum) +    endif +  endif + +  " Below a line starting with "}" never indent more.  Needed for a method +  " below a method with an indented "throws" clause. +  let lnum = SkipJavaBlanksAndComments(v:lnum - 1) +  if getline(lnum) =~ '^\s*}\s*\(//.*\|/\*.*\)\=$' && indent(lnum) < theIndent +    let theIndent = indent(lnum) +  endif + +  return theIndent +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vi: sw=2 et + +endif diff --git a/indent/javascript.vim b/indent/javascript.vim index 100efbc5..37bd631a 100644 --- a/indent/javascript.vim +++ b/indent/javascript.vim @@ -1,3 +1,456 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language: Javascript +" Maintainer: Chris Paul ( https://github.com/bounceme ) +" URL: https://github.com/pangloss/vim-javascript +" Last Change: September 18, 2017 + +" Only load this indent file when no other was loaded. +if exists('b:did_indent') +  finish +endif +let b:did_indent = 1 + +" indent correctly if inside <script> +" vim/vim@690afe1 for the switch from cindent +let b:html_indent_script1 = 'inc' + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetJavascriptIndent() +setlocal autoindent nolisp nosmartindent +setlocal indentkeys+=0],0) +" Testable with something like: +" vim  -eNs "+filetype plugin indent on" "+syntax on" "+set ft=javascript" \ +"       "+norm! gg=G" '+%print' '+:q!' testfile.js \ +"       | diff -uBZ testfile.js - + +let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<' + +" Regex of syntax group names that are or delimit string or are comments. +let b:syng_strcom = get(b:,'syng_strcom','string\|comment\|regex\|special\|doc\|template\%(braces\)\@!') +let b:syng_str = get(b:,'syng_str','string\|template\|special') +" template strings may want to be excluded when editing graphql: +" au! Filetype javascript let b:syng_str = '^\%(.*template\)\@!.*string\|special' +" au! Filetype javascript let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc' + +" Only define the function once. +if exists('*GetJavascriptIndent') +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Get shiftwidth value +if exists('*shiftwidth') +  function s:sw() +    return shiftwidth() +  endfunction +else +  function s:sw() +    return &l:shiftwidth ? &l:shiftwidth : &l:tabstop +  endfunction +endif + +" Performance for forwards search(): start search at pos rather than masking +" matches before pos. +let s:z = has('patch-7.4.984') ? 'z' : '' + +" Expression used to check whether we should skip a match with searchpair(). +let s:skip_expr = "s:SynAt(line('.'),col('.')) =~? b:syng_strcom" +let s:in_comm = s:skip_expr[:-14] . "'comment\\|doc'" + +let s:rel = has('reltime') +" searchpair() wrapper +if s:rel +  function s:GetPair(start,end,flags,skip) +    return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,s:l1,a:skip ==# 's:SkipFunc()' ? 2000 : 200) +  endfunction +else +  function s:GetPair(start,end,flags,skip) +    return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,s:l1) +  endfunction +endif + +function s:SynAt(l,c) +  let byte = line2byte(a:l) + a:c - 1 +  let pos = index(s:synid_cache[0], byte) +  if pos == -1 +    let s:synid_cache[:] += [[byte], [synIDattr(synID(a:l, a:c, 0), 'name')]] +  endif +  return s:synid_cache[1][pos] +endfunction + +function s:ParseCino(f) +  let [divider, n, cstr] = [0] + matchlist(&cino, +        \ '\%(.*,\)\=\%(\%d'.char2nr(a:f).'\(-\)\=\([.s0-9]*\)\)\=')[1:2] +  for c in split(cstr,'\zs') +    if c == '.' && !divider +      let divider = 1 +    elseif c ==# 's' +      if n !~ '\d' +        return n . s:sw() + 0 +      endif +      let n = str2nr(n) * s:sw() +      break +    else +      let [n, divider] .= [c, 0] +    endif +  endfor +  return str2nr(n) / max([str2nr(divider),1]) +endfunction + +" Optimized {skip} expr, only callable from the search loop which +" GetJavascriptIndent does to find the containing [[{(] (side-effects) +function s:SkipFunc() +  if s:top_col == 1 +    throw 'out of bounds' +  endif +  let s:top_col = 0 +  if s:check_in +    if eval(s:skip_expr) +      return 1 +    endif +    let s:check_in = 0 +  elseif getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$' +    if eval(s:skip_expr) +      let s:looksyn = a:firstline +      return 1 +    endif +  elseif search('\m`\|\${\|\*\/','nW'.s:z,s:looksyn) && eval(s:skip_expr) +    let s:check_in = 1 +    return 1 +  endif +  let [s:looksyn, s:top_col] = getpos('.')[1:2] +endfunction + +function s:AlternatePair() +  let [pat, l:for] = ['[][(){};]', 2] +  while s:SearchLoop(pat,'bW','s:SkipFunc()') +    if s:LookingAt() == ';' +      if !l:for +        if s:GetPair('{','}','bW','s:SkipFunc()') +          return +        endif +        break +      else +        let [pat, l:for] = ['[{}();]', l:for - 1] +      endif +    else +      let idx = stridx('])}',s:LookingAt()) +      if idx == -1 +        return +      elseif !s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:SkipFunc()') +        break +      endif +    endif +  endwhile +  throw 'out of bounds' +endfunction + +function s:Nat(int) +  return a:int * (a:int > 0) +endfunction + +function s:LookingAt() +  return getline('.')[col('.')-1] +endfunction + +function s:Token() +  return s:LookingAt() =~ '\k' ? expand('<cword>') : s:LookingAt() +endfunction + +function s:PreviousToken() +  let l:col = col('.') +  if search('\m\k\{1,}\|\S','ebW') +    if search('\m\*\%#\/\|\/\/\%<'.a:firstline.'l','nbW',line('.')) && eval(s:in_comm) +      if s:SearchLoop('\S\ze\_s*\/[/*]','bW',s:in_comm) +        return s:Token() +      endif +      call cursor(a:firstline, l:col) +    else +      return s:Token() +    endif +  endif +  return '' +endfunction + +function s:Pure(f,...) +  return eval("[call(a:f,a:000),cursor(a:firstline,".col('.').")][0]") +endfunction + +function s:SearchLoop(pat,flags,expr) +  return s:GetPair(a:pat,'\_$.',a:flags,a:expr) +endfunction + +function s:ExprCol() +  let bal = 0 +  while s:SearchLoop('[{}?]\|\_[^:]\zs::\@!','bW',s:skip_expr) +    if s:LookingAt() == ':' +      let bal -= 1 +    elseif s:LookingAt() == '?' +      let bal += 1 +      if bal == 1 +        break +      endif +    elseif s:LookingAt() == '{' +      let bal = !s:IsBlock() +      break +    elseif !s:GetPair('{','}','bW',s:skip_expr) +      break +    endif +  endwhile +  return s:Nat(bal) +endfunction + +" configurable regexes that define continuation lines, not including (, {, or [. +let s:opfirst = '^' . get(g:,'javascript_opfirst', +      \ '\C\%([<>=,.?^%|/&]\|\([-:+]\)\1\@!\|\*\+\|!=\|in\%(stanceof\)\=\>\)') +let s:continuation = get(g:,'javascript_continuation', +      \ '\C\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$' + +function s:Continues(ln,con) +  let tok = matchstr(a:con[-15:],s:continuation) +  if tok =~ '[a-z:]' +    call cursor(a:ln, len(a:con)) +    return tok == ':' ? s:ExprCol() : s:PreviousToken() != '.' +  elseif tok !~ '[/>]' +    return tok isnot '' +  endif +  return s:SynAt(a:ln, len(a:con)) !~? (tok == '>' ? 'jsflow\|^html' : 'regex') +endfunction + +" Check if line 'lnum' has a balanced amount of parentheses. +function s:Balanced(lnum) +  let [l:open, l:line] = [0, getline(a:lnum)] +  let pos = match(l:line, '[][(){}]') +  while pos != -1 +    if s:SynAt(a:lnum,pos + 1) !~? b:syng_strcom +      let l:open += match(' ' . l:line[pos],'[[({]') +      if l:open < 0 +        return +      endif +    endif +    let pos = match(l:line, !l:open ? '[][(){}]' : '()' =~ l:line[pos] ? +          \ '[()]' : '{}' =~ l:line[pos] ? '[{}]' : '[][]', pos + 1) +  endwhile +  return !l:open +endfunction + +function s:OneScope() +  if s:LookingAt() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr) +    let tok = s:PreviousToken() +    return (count(split('for if let while with'),tok) || +          \ tok =~# '^await$\|^each$' && s:PreviousToken() ==# 'for') && +          \ s:Pure('s:PreviousToken') != '.' && !(tok == 'while' && s:DoWhile()) +  elseif s:Token() =~# '^else$\|^do$' +    return s:Pure('s:PreviousToken') != '.' +  endif +  return strpart(getline('.'),col('.')-2,2) == '=>' +endfunction + +function s:DoWhile() +  let cpos = searchpos('\m\<','cbW') +  if s:SearchLoop('\C[{}]\|\<\%(do\|while\)\>','bW',s:skip_expr) +    if s:{s:LookingAt() == '}' && s:GetPair('{','}','bW',s:skip_expr) ? +          \ 'Previous' : ''}Token() ==# 'do' && s:IsBlock() +      return 1 +    endif +    call call('cursor',cpos) +  endif +endfunction + +" returns total offset from braceless contexts. 'num' is the lineNr which +" encloses the entire context, 'cont' if whether a:firstline is a continued +" expression, which could have started in a braceless context +function s:IsContOne(num,cont) +  let [l:num, b_l] = [a:num + !a:num, 0] +  let pind = a:num ? indent(a:num) + s:sw() : 0 +  let ind = indent('.') + !a:cont +  while line('.') > l:num && ind > pind || line('.') == l:num +    if indent('.') < ind && s:OneScope() +      let b_l += 1 +    elseif !a:cont || b_l || ind < indent(a:firstline) +      break +    else +      call cursor(0,1) +    endif +    let ind = min([ind, indent('.')]) +    if s:PreviousToken() is '' +      break +    endif +  endwhile +  return b_l +endfunction + +function s:Class() +  return (s:Token() ==# 'class' || s:PreviousToken() =~# '^class$\|^extends$') && +        \ s:PreviousToken() != '.' +endfunction + +function s:IsSwitch() +  return s:PreviousToken() !~ '[.*]' && +        \ (!s:GetPair('{','}','cbW',s:skip_expr) || s:IsBlock() && !s:Class()) +endfunction + +" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader +function s:IsBlock() +  let tok = s:PreviousToken() +  if join(s:stack) =~? 'xml\|jsx' && s:SynAt(line('.'),col('.')-1) =~? 'xml\|jsx' +    return tok != '{' +  elseif tok =~ '\k' +    if tok ==# 'type' +      return s:Pure('eval',"s:PreviousToken() !~# '^\\%(im\\|ex\\)port$' || s:PreviousToken() == '.'") +    elseif tok ==# 'of' +      return s:Pure('eval',"!s:GetPair('[[({]','[])}]','bW',s:skip_expr) || s:LookingAt() != '(' ||" +            \ ."s:{s:PreviousToken() ==# 'await' ? 'Previous' : ''}Token() !=# 'for' || s:PreviousToken() == '.'") +    endif +    return index(split('return const let import export extends yield default delete var await void typeof throw case new in instanceof') +          \ ,tok) < (line('.') != a:firstline) || s:Pure('s:PreviousToken') == '.' +  elseif tok == '>' +    return getline('.')[col('.')-2] == '=' || s:SynAt(line('.'),col('.')) =~? 'jsflow\|^html' +  elseif tok == '*' +    return s:Pure('s:PreviousToken') == ':' +  elseif tok == ':' +    return s:Pure('eval',"s:PreviousToken() =~ '^\\K\\k*$' && !s:ExprCol()") +  elseif tok == '/' +    return s:SynAt(line('.'),col('.')) =~? 'regex' +  elseif tok !~ '[=~!<,.?^%|&([]' +    return tok !~ '[-+]' || line('.') != a:firstline && getline('.')[col('.')-2] == tok +  endif +endfunction + +function GetJavascriptIndent() +  let b:js_cache = get(b:,'js_cache',[0,0,0]) +  let s:synid_cache = [[],[]] +  let l:line = getline(v:lnum) +  " use synstack as it validates syn state and works in an empty line +  let s:stack = [''] + map(synstack(v:lnum,1),"synIDattr(v:val,'name')") + +  " start with strings,comments,etc. +  if s:stack[-1] =~? 'comment\|doc' +    if l:line =~ '^\s*\*' +      return cindent(v:lnum) +    elseif l:line !~ '^\s*\/[/*]' +      return -1 +    endif +  elseif s:stack[-1] =~? b:syng_str +    if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1) +      let b:js_cache[0] = v:lnum +    endif +    return -1 +  endif + +  let s:l1 = max([0,prevnonblank(v:lnum) - (s:rel ? 2000 : 1000), +        \ get(get(b:,'hi_indent',{}),'blocklnr')]) +  call cursor(v:lnum,1) +  if s:PreviousToken() is '' +    return +  endif +  let [l:lnum, pline] = [line('.'), getline('.')[:col('.')-1]] + +  let l:line = substitute(l:line,'^\s*','','') +  let l:line_raw = l:line +  if l:line[:1] == '/*' +    let l:line = substitute(l:line,'^\%(\/\*.\{-}\*\/\s*\)*','','') +  endif +  if l:line =~ '^\/[/*]' +    let l:line = '' +  endif + +  " the containing paren, bracket, or curly. Many hacks for performance +  call cursor(v:lnum,1) +  let idx = index([']',')','}'],l:line[0]) +  if b:js_cache[0] > l:lnum && b:js_cache[0] < v:lnum || +        \ b:js_cache[0] == l:lnum && s:Balanced(l:lnum) +    call call('cursor',b:js_cache[1:]) +  else +    let [s:looksyn, s:top_col, s:check_in, s:l1] = [v:lnum - 1,0,0, +          \ max([s:l1, &smc ? search('\m^.\{'.&smc.',}','nbW',s:l1 + 1) + 1 : 0])] +    try +      if idx != -1 +        call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:SkipFunc()') +      elseif getline(v:lnum) !~ '^\S' && s:stack[-1] =~? 'block\|^jsobject$' +        call s:GetPair('{','}','bW','s:SkipFunc()') +      else +        call s:AlternatePair() +      endif +    catch /^\Cout of bounds$/ +      call cursor(v:lnum,1) +    endtry +    let b:js_cache[1:] = line('.') == v:lnum ? [0,0] : getpos('.')[1:2] +  endif + +  let [b:js_cache[0], num] = [v:lnum, b:js_cache[1]] + +  let [num_ind, is_op, b_l, l:switch_offset] = [s:Nat(indent(num)),0,0,0] +  if !num || s:LookingAt() == '{' && s:IsBlock() +    let ilnum = line('.') +    if num && s:LookingAt() == ')' && s:GetPair('(',')','bW',s:skip_expr) +      if ilnum == num +        let [num, num_ind] = [line('.'), indent('.')] +      endif +      if idx == -1 && s:PreviousToken() ==# 'switch' && s:IsSwitch() +        let l:switch_offset = &cino !~ ':' ? s:sw() : s:ParseCino(':') +        if pline[-1:] != '.' && l:line =~# '^\%(default\|case\)\>' +          return s:Nat(num_ind + l:switch_offset) +        elseif &cino =~ '=' +          let l:case_offset = s:ParseCino('=') +        endif +      endif +    endif +    if idx == -1 && pline[-1:] !~ '[{;]' +      let sol = matchstr(l:line,s:opfirst) +      if sol is '' || sol == '/' && s:SynAt(v:lnum, +            \ 1 + len(getline(v:lnum)) - len(l:line)) =~? 'regex' +        if s:Continues(l:lnum,pline) +          let is_op = s:sw() +        endif +      elseif num && sol =~# '^\%(in\%(stanceof\)\=\|\*\)$' +        call call('cursor',b:js_cache[1:]) +        if s:PreviousToken() =~ '\k' && s:Class() +          return num_ind + s:sw() +        endif +        let is_op = s:sw() +      else +        let is_op = s:sw() +      endif +      call cursor(l:lnum, len(pline)) +      let b_l = s:Nat(s:IsContOne(b:js_cache[1],is_op) - (!is_op && l:line =~ '^{')) * s:sw() +    endif +  elseif idx.s:LookingAt().&cino =~ '^-1(.*(' && (search('\m\S','nbW',num) || s:ParseCino('U')) +    let pval = s:ParseCino('(') +    if !pval +      let [Wval, vcol] = [s:ParseCino('W'), virtcol('.')] +      if search('\m\S','W',num) +        return s:ParseCino('w') ? vcol : virtcol('.')-1 +      endif +      return Wval ? s:Nat(num_ind + Wval) : vcol +    endif +    return s:Nat(num_ind + pval + searchpair('\m(','','\m)','nbrmW',s:skip_expr,num) * s:sw()) +  endif + +  " main return +  if l:line =~ '^[])}]\|^|}' +    if l:line_raw[0] == ')' && getline(num)[b:js_cache[2]-1] == '(' +      if s:ParseCino('M') +        return indent(l:lnum) +      elseif &cino =~# 'm' && !s:ParseCino('m') +        return virtcol('.') - 1 +      endif +    endif +    return num_ind +  elseif num +    return s:Nat(num_ind + get(l:,'case_offset',s:sw()) + l:switch_offset + b_l + is_op) +  endif +  return b_l + is_op +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == -1  " Vim indent file diff --git a/indent/json.vim b/indent/json.vim index 7db3586e..67dd6212 100644 --- a/indent/json.vim +++ b/indent/json.vim @@ -1,3 +1,175 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:		JSON +" Mantainer:		Eli Parra <eli@elzr.com> https://github.com/elzr/vim-json +" Last Change:          2017 Jun 13 +"   https://github.com/jakar/vim-json/commit/20b650e22aa750c4ab6a66aa646bdd95d7cd548a#diff-e81fc111b2052e306d126bd9989f7b7c +" Original Author:	Rogerz Zhang <rogerz.zhang at gmail.com> http://github.com/rogerz/vim-json +" Acknowledgement:      Based off of vim-javascript maintained by Darrick Wiebe  +"                       http://www.vim.org/scripts/script.php?script_id=2765 + +" 0. Initialization {{{1 +" ================= + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetJSONIndent() +setlocal indentkeys=0{,0},0),0[,0],!^F,o,O,e + +" Only define the function once. +if exists("*GetJSONIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 1. Variables {{{1 +" ============ + +let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' +" Regex that defines blocks. +let s:block_regex = '\%({\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +" 2. Auxiliary Functions {{{1 +" ====================== + +" 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') == 'jsonString' +endfunction + +" Find line above 'lnum' that isn't empty, or in a string. +function s:PrevNonBlankNonString(lnum) +  let lnum = prevnonblank(a:lnum) +  while lnum > 0 +    " If the line isn't empty or in a string, end search. +    let line = getline(lnum) +    if !(s:IsInString(lnum, 1) && s:IsInString(lnum, strlen(line))) +      break +    endif +    let lnum = prevnonblank(lnum - 1) +  endwhile +  return lnum +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 +    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 +    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:IsInString(a:lnum, col) ? col : 0 +endfunction + +" 3. GetJSONIndent Function {{{1 +" ========================= + +function GetJSONIndent() +  " 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 +  " ----------------------------- + +  " Get the current line. +  let line = getline(v:lnum) +  let ind = -1 + +  " If we got a closing bracket on an empty line, find its match and indent +  " according to it. +  let col = matchend(line, '^\s*[]}]') + +  if col > 0 && !s:IsInString(v:lnum, col) +    call cursor(v:lnum, col) +    let bs = strpart('{}[]', stridx('}]', line[col - 1]) * 2, 2) + +    let pairstart = escape(bs[0], '[') +    let pairend = escape(bs[1], ']') +    let pairline = searchpair(pairstart, '', pairend, 'bW') + +    if pairline > 0  +      let ind = indent(pairline) +    else +      let ind = virtcol('.') - 1 +    endif + +    return ind +  endif + +  " If we are in a multi-line string, don't do anything to it. +  if s:IsInString(v:lnum, matchend(line, '^\s*') + 1) +    return indent('.') +  endif + +  " 3.3. Work on the previous line. {{{2 +  " ------------------------------- + +  let lnum = prevnonblank(v:lnum - 1) + +  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(lnum) + shiftwidth() +  " 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' || counts[1] == '1' || counts[2] == '1' +      return ind + shiftwidth() +    else +      call cursor(v:lnum, vcol) +    end +  endif + +  " }}}2 + +  return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 noet: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'json') == -1  " Vim indent file diff --git a/indent/jsp.vim b/indent/jsp.vim new file mode 100644 index 00000000..b3a149eb --- /dev/null +++ b/indent/jsp.vim @@ -0,0 +1,21 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim filetype indent file +" Language:    JSP files +" Maintainer:  David Fishburn <fishburn@ianywhere.com> +" Version:     1.0 +" Last Change: Wed Nov 08 2006 11:08:05 AM + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif + +" If there has been no specific JSP indent script created,  +" use the default html indent script which will handle +" html, javascript and most of the JSP constructs. +runtime! indent/html.vim + + + +endif diff --git a/indent/ld.vim b/indent/ld.vim new file mode 100644 index 00000000..5e2e9d86 --- /dev/null +++ b/indent/ld.vim @@ -0,0 +1,88 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             ld(1) script +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetLDIndent() +setlocal indentkeys=0{,0},!^F,o,O +setlocal nosmartindent + +if exists("*GetLDIndent") +  finish +endif + +function s:prevnonblanknoncomment(lnum) +  let lnum = a:lnum +  while lnum > 1 +    let lnum = prevnonblank(lnum) +    let line = getline(lnum) +    if line =~ '\*/' +      while lnum > 1 && line !~ '/\*' +        let lnum -= 1 +      endwhile +      if line =~ '^\s*/\*' +        let lnum -= 1 +      else +        break +      endif +    else +      break +    endif +  endwhile +  return lnum +endfunction + +function s:count_braces(lnum, count_open) +  let n_open = 0 +  let n_close = 0 +  let line = getline(a:lnum) +  let pattern = '[{}]' +  let i = match(line, pattern) +  while i != -1 +    if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'ld\%(Comment\|String\)' +      if line[i] == '{' +        let n_open += 1 +      elseif line[i] == '}' +        if n_open > 0 +          let n_open -= 1 +        else +          let n_close += 1 +        endif +      endif +    endif +    let i = match(line, pattern, i + 1) +  endwhile +  return a:count_open ? n_open : n_close +endfunction + +function GetLDIndent() +  let line = getline(v:lnum) +  if line =~ '^\s*\*' +    return cindent(v:lnum) +  elseif line =~ '^\s*}' +    return indent(v:lnum) - shiftwidth() +  endif + +  let pnum = s:prevnonblanknoncomment(v:lnum - 1) +  if pnum == 0 +    return 0 +  endif + +  let ind = indent(pnum) + s:count_braces(pnum, 1) * shiftwidth() + +  let pline = getline(pnum) +  if pline =~ '}\s*$' +    let ind -= (s:count_braces(pnum, 0) - (pline =~ '^\s*}' ? 1 : 0)) * shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/less.vim b/indent/less.vim index 700a19fb..d0209e58 100644 --- a/indent/less.vim +++ b/indent/less.vim @@ -1,3 +1,20 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	less +" Maintainer:	Alessandro Vioni <jenoma@gmail.com> +" URL: https://github.com/genoma/vim-less +" Last Change:	2014 November 24 + +if exists("b:did_indent") +  finish +endif + +runtime! indent/css.vim + +" vim:set sw=2: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'less') == -1  " Vim indent file diff --git a/indent/lifelines.vim b/indent/lifelines.vim new file mode 100644 index 00000000..6d8ec577 --- /dev/null +++ b/indent/lifelines.vim @@ -0,0 +1,28 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	LifeLines +" Maintainer:	Patrick Texier <p.texier@orsennes.com> +" Location:	<http://patrick.texier.free.fr/vim/indent/lifelines.vim> +" Last Change:	2010 May 7 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +" LifeLines uses cindent without ; line terminator, C functions +" declarations, C keywords, C++ formating +setlocal cindent +setlocal cinwords="" +setlocal cinoptions+=+0 +setlocal cinoptions+=p0 +setlocal cinoptions+=i0 +setlocal cinoptions+=t0 +setlocal cinoptions+=*500 + +let b:undo_indent = "setl cin< cino< cinw<" +" vim: ts=8 sw=4 + +endif diff --git a/indent/liquid.vim b/indent/liquid.vim index 1f12eec5..5c95a641 100644 --- a/indent/liquid.vim +++ b/indent/liquid.vim @@ -1,3 +1,70 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     Liquid +" Maintainer:   Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2017 Jun 13 + +if exists('b:did_indent') +  finish +endif + +set indentexpr= +if exists('b:liquid_subtype') +  exe 'runtime! indent/'.b:liquid_subtype.'.vim' +else +  runtime! indent/html.vim +endif +unlet! b:did_indent + +if &l:indentexpr == '' +  if &l:cindent +    let &l:indentexpr = 'cindent(v:lnum)' +  else +    let &l:indentexpr = 'indent(prevnonblank(v:lnum-1))' +  endif +endif +let b:liquid_subtype_indentexpr = &l:indentexpr + +let b:did_indent = 1 + +setlocal indentexpr=GetLiquidIndent() +setlocal indentkeys=o,O,*<Return>,<>>,{,},0),0],o,O,!^F,=end,=endif,=endunless,=endifchanged,=endcase,=endfor,=endtablerow,=endcapture,=else,=elsif,=when,=empty + +" Only define the function once. +if exists('*GetLiquidIndent') +  finish +endif + +function! s:count(string,pattern) +  let string = substitute(a:string,'\C'.a:pattern,"\n",'g') +  return strlen(substitute(string,"[^\n]",'','g')) +endfunction + +function! GetLiquidIndent(...) +  if a:0 && a:1 == '.' +    let v:lnum = line('.') +  elseif a:0 && a:1 =~ '^\d' +    let v:lnum = a:1 +  endif +  let vcol = col('.') +  call cursor(v:lnum,1) +  exe "let ind = ".b:liquid_subtype_indentexpr +  let lnum = prevnonblank(v:lnum-1) +  let line = getline(lnum) +  let cline = getline(v:lnum) +  let line  = substitute(line,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') +  let line .= matchstr(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+') +  let cline = substitute(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') +  let sw = shiftwidth() +  let ind += sw * s:count(line,'{%\s*\%(if\|elsif\|else\|unless\|ifchanged\|case\|when\|for\|empty\|tablerow\|capture\)\>') +  let ind -= sw * s:count(line,'{%\s*end\%(if\|unless\|ifchanged\|case\|for\|tablerow\|capture\)\>') +  let ind -= sw * s:count(cline,'{%\s*\%(elsif\|else\|when\|empty\)\>') +  let ind -= sw * s:count(cline,'{%\s*end\w*$') +  return ind +endfunction + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'liquid') == -1  " Vim indent file diff --git a/indent/lisp.vim b/indent/lisp.vim new file mode 100644 index 00000000..c4d62486 --- /dev/null +++ b/indent/lisp.vim @@ -0,0 +1,19 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Lisp +" Maintainer:    Sergey Khorev <sergey.khorev@gmail.com> +" URL:		 http://sites.google.com/site/khorser/opensource/vim +" Last Change:	2012 Jan 10 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +setlocal ai nosi + +let b:undo_indent = "setl ai< si<" + +endif diff --git a/indent/logtalk.vim b/indent/logtalk.vim new file mode 100644 index 00000000..a7c0a3a0 --- /dev/null +++ b/indent/logtalk.vim @@ -0,0 +1,65 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"  Maintainer:	Paulo Moura <pmoura@logtalk.org> +"  Revised on:	2008.06.02 +"  Language:	Logtalk + +" This Logtalk indent file is a modified version of the Prolog +" indent file written by Gergely Kontra + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +	finish +endif + +let b:did_indent = 1 + +setlocal indentexpr=GetLogtalkIndent() +setlocal indentkeys-=:,0# +setlocal indentkeys+=0%,-,0;,>,0) + +" Only define the function once. +if exists("*GetLogtalkIndent") +	finish +endif + +function! GetLogtalkIndent() +	" Find a non-blank line above the current line. +	let pnum = prevnonblank(v:lnum - 1) +	" Hit the start of the file, use zero indent. +	if pnum == 0 +		return 0 +	endif +	let line = getline(v:lnum) +	let pline = getline(pnum) + +	let ind = indent(pnum) +	" Previous line was comment -> use previous line's indent +	if pline =~ '^\s*%' +		retu ind +	endif +	" Check for entity opening directive on previous line +	if pline =~ '^\s*:-\s\(object\|protocol\|category\)\ze(.*,$' +		let ind = ind + shiftwidth() +	" Check for clause head on previous line +	elseif pline =~ ':-\s*\(%.*\)\?$' +		let ind = ind + shiftwidth() +	" Check for entity closing directive on previous line +	elseif pline =~ '^\s*:-\send_\(object\|protocol\|category\)\.\(%.*\)\?$' +		let ind = ind - shiftwidth() +	" Check for end of clause on previous line +	elseif pline =~ '\.\s*\(%.*\)\?$' +		let ind = ind - shiftwidth() +	endif +	" Check for opening conditional on previous line +	if pline =~ '^\s*\([(;]\|->\)' && pline !~ '\.\s*\(%.*\)\?$' && pline !~ '^.*\([)][,]\s*\(%.*\)\?$\)' +		let ind = ind + shiftwidth() +	endif +	" Check for closing an unclosed paren, or middle ; or -> +	if line =~ '^\s*\([);]\|->\)' +		let ind = ind - shiftwidth() +	endif +	return ind +endfunction + +endif diff --git a/indent/lua.vim b/indent/lua.vim index 3c33c032..9db1d7db 100644 --- a/indent/lua.vim +++ b/indent/lua.vim @@ -1,3 +1,70 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Lua script +" Maintainer:	Marcus Aurelius Farias <marcus.cf 'at' bol.com.br> +" First Author:	Max Ischenko <mfi 'at' ukr.net> +" Last Change:	2017 Jun 13 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetLuaIndent() + +" To make Vim call GetLuaIndent() when it finds '\s*end' or '\s*until' +" on the current line ('else' is default and includes 'elseif'). +setlocal indentkeys+=0=end,0=until + +setlocal autoindent + +" Only define the function once. +if exists("*GetLuaIndent") +  finish +endif + +function! GetLuaIndent() +  " Find a non-blank line above the current line. +  let prevlnum = prevnonblank(v:lnum - 1) + +  " Hit the start of the file, use zero indent. +  if prevlnum == 0 +    return 0 +  endif + +  " Add a 'shiftwidth' after lines that start a block: +  " 'function', 'if', 'for', 'while', 'repeat', 'else', 'elseif', '{' +  let ind = indent(prevlnum) +  let prevline = getline(prevlnum) +  let midx = match(prevline, '^\s*\%(if\>\|for\>\|while\>\|repeat\>\|else\>\|elseif\>\|do\>\|then\>\)') +  if midx == -1 +    let midx = match(prevline, '{\s*$') +    if midx == -1 +      let midx = match(prevline, '\<function\>\s*\%(\k\|[.:]\)\{-}\s*(') +    endif +  endif + +  if midx != -1 +    " Add 'shiftwidth' if what we found previously is not in a comment and +    " an "end" or "until" is not present on the same line. +    if synIDattr(synID(prevlnum, midx + 1, 1), "name") != "luaComment" && prevline !~ '\<end\>\|\<until\>' +      let ind = ind + shiftwidth() +    endif +  endif + +  " Subtract a 'shiftwidth' on end, else, elseif, until and '}' +  " This is the part that requires 'indentkeys'. +  let midx = match(getline(v:lnum), '^\s*\%(end\>\|else\>\|elseif\>\|until\>\|}\)') +  if midx != -1 && synIDattr(synID(v:lnum, midx + 1, 1), "name") != "luaComment" +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'lua') == -1  " Vim indent file diff --git a/indent/mail.vim b/indent/mail.vim new file mode 100644 index 00000000..8dd0366e --- /dev/null +++ b/indent/mail.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Mail +" Maintainer:	Bram Moolenaar +" Last Change:	2009 Jun 03 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" What works best is auto-indenting, disable other indenting. +" For formatting see the ftplugin. +setlocal autoindent nosmartindent nocindent indentexpr= + +endif diff --git a/indent/make.vim b/indent/make.vim new file mode 100644 index 00000000..35918121 --- /dev/null +++ b/indent/make.vim @@ -0,0 +1,120 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Makefile +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2007-05-07 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetMakeIndent() +setlocal indentkeys=!^F,o,O,<:>,=else,=endif +setlocal nosmartindent + +if exists("*GetMakeIndent") +  finish +endif + +let s:comment_rx = '^\s*#' +let s:rule_rx = '^[^ \t#:][^#:]*:\{1,2}\%([^=:]\|$\)' +let s:continued_rule_rx = '^[^#:]*:\{1,2}\%([^=:]\|$\)' +let s:continuation_rx = '\\$' +let s:assignment_rx = '^\s*\h\w*\s*[+?]\==\s*\zs.*\\$' +let s:folded_assignment_rx = '^\s*\h\w*\s*[+?]\==' +" TODO: This needs to be a lot more restrictive in what it matches. +let s:just_inserted_rule_rx = '^\s*[^#:]\+:\{1,2}$' +let s:conditional_directive_rx = '^ *\%(ifn\=\%(eq\|def\)\|else\)\>' +let s:end_conditional_directive_rx = '^\s*\%(else\|endif\)\>' + +function s:remove_continuation(line) +  return substitute(a:line, s:continuation_rx, "", "") +endfunction + +function GetMakeIndent() +  " TODO: Should this perhaps be v:lnum -1? +"  let prev_lnum = prevnonblank(v:lnum - 1) +  let prev_lnum = v:lnum - 1 +  if prev_lnum == 0 +    return 0 +  endif +  let prev_line = getline(prev_lnum) + +  let prev_prev_lnum = prev_lnum - 1 +  let prev_prev_line = prev_prev_lnum != 0 ? getline(prev_prev_lnum) : "" + +  " TODO: Deal with comments.  In comments, continuations aren't interesting. +  if prev_line =~ s:continuation_rx +    if prev_prev_line =~ s:continuation_rx +      return indent(prev_lnum) +    elseif prev_line =~ s:rule_rx +      return shiftwidth() +    elseif prev_line =~ s:assignment_rx +      call cursor(prev_lnum, 1) +      if search(s:assignment_rx, 'W') != 0 +        return virtcol('.') - 1 +      else +        " TODO: ? +        return shiftwidth() +      endif +    else +      " TODO: OK, this might be a continued shell command, so perhaps indent +      " properly here?  Leave this out for now, but in the next release this +      " should be using indent/sh.vim somehow. +      "if prev_line =~ '^\t' " s:rule_command_rx +      "  if prev_line =~ '^\s\+[@-]\%(if\)\>' +      "    return indent(prev_lnum) + 2 +      "  endif +      "endif +      return indent(prev_lnum) + shiftwidth() +    endif +  elseif prev_prev_line =~ s:continuation_rx +    let folded_line = s:remove_continuation(prev_prev_line) . ' ' . s:remove_continuation(prev_line) +    let lnum = prev_prev_lnum - 1 +    let line = getline(lnum) +    while line =~ s:continuation_rx +      let folded_line = s:remove_continuation(line) . ' ' . folded_line +      let lnum -= 1 +      let line = getline(lnum) +    endwhile +    let folded_lnum = lnum + 1 +    if folded_line =~ s:rule_rx +      if getline(v:lnum) =~ s:rule_rx +        return 0 +      else +        return &ts +      endif +    else +"    elseif folded_line =~ s:folded_assignment_rx +      if getline(v:lnum) =~ s:rule_rx +        return 0 +      else +        return indent(folded_lnum) +      endif +"    else +"      " TODO: ? +"      return indent(prev_lnum) +    endif +  elseif prev_line =~ s:rule_rx +    if getline(v:lnum) =~ s:rule_rx +      return 0 +    else +      return &ts +    endif +  elseif prev_line =~ s:conditional_directive_rx +    return shiftwidth() +  else +    let line = getline(v:lnum) +    if line =~ s:just_inserted_rule_rx +      return 0 +    elseif line =~ s:end_conditional_directive_rx +      return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1) - shiftwidth() +    else +      return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1) +    endif +  endif +endfunction + +endif diff --git a/indent/matlab.vim b/indent/matlab.vim new file mode 100644 index 00000000..32bb721e --- /dev/null +++ b/indent/matlab.vim @@ -0,0 +1,78 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Matlab indent file +" Language:	Matlab +" Maintainer:	Christophe Poucet <christophe.poucet@pandora.be> +" Last Change:	6 January, 2001 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" Some preliminary setting +setlocal indentkeys=!,o,O=end,=case,=else,=elseif,=otherwise,=catch + + +setlocal indentexpr=GetMatlabIndent(v:lnum) + +" Only define the function once. +if exists("*GetMatlabIndent") +  finish +endif + +function GetMatlabIndent(lnum) +  " Give up if this line is explicitly joined. +  if getline(a:lnum - 1) =~ '\\$' +    return -1 +  endif + +  " Search backwards for the first non-empty line. +  let plnum = a:lnum - 1 +  while plnum > 0 && getline(plnum) =~ '^\s*$' +    let plnum = plnum - 1 +  endwhile + +  if plnum == 0 +    " This is the first non-empty line, use zero indent. +    return 0 +  endif + +  let curind = indent(plnum) + +  " If the current line is a stop-block statement... +  if getline(v:lnum) =~ '^\s*\(end\|else\|elseif\|case\|otherwise\|catch\)\>' +    " See if this line does not follow the line right after an openblock +    if getline(plnum) =~ '^\s*\(for\|if\|else\|elseif\|case\|while\|switch\|try\|otherwise\|catch\)\>' +    " See if the user has already dedented +    elseif indent(v:lnum) > curind - shiftwidth() +      " If not, recommend one dedent +	let curind = curind - shiftwidth() +    else +      " Otherwise, trust the user +      return -1 +    endif +"  endif + +  " If the previous line opened a block +  elseif getline(plnum) =~ '^\s*\(for\|if\|else\|elseif\|case\|while\|switch\|try\|otherwise\|catch\)\>' +    " See if the user has already indented +    if indent(v:lnum) < curind + shiftwidth() +      "If not, recommend indent +      let curind = curind + shiftwidth() +    else +      " Otherwise, trust the user +      return -1 +    endif +  endif + + + +  " If we got to here, it means that the user takes the standardversion, so we return it +  return curind +endfunction + +" vim:sw=2 + +endif diff --git a/indent/mf.vim b/indent/mf.vim new file mode 100644 index 00000000..69b28cbc --- /dev/null +++ b/indent/mf.vim @@ -0,0 +1,10 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" METAFONT indent file +" Language:    METAFONT +" Maintainer:  Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change: 2016 Oct 1 + +runtime! indent/mp.vim + +endif diff --git a/indent/mma.vim b/indent/mma.vim new file mode 100644 index 00000000..e6ca9533 --- /dev/null +++ b/indent/mma.vim @@ -0,0 +1,79 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     Mathematica +" Author:       steve layland <layland@wolfram.com> +" Last Change:  Sat May  10 18:56:22 CDT 2005 +" Source:       http://vim.sourceforge.net/scripts/script.php?script_id=1274 +"               http://members.wolfram.com/layland/vim/indent/mma.vim +" +" NOTE: +" Empty .m files will automatically be presumed to be Matlab files +" unless you have the following in your .vimrc: +" +"       let filetype_m="mma" +" +" Credits: +" o steve hacked this out of a random indent file in the Vim 6.1 +"   distribution that he no longer remembers...sh.vim?  Thanks! + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetMmaIndent() +setlocal indentkeys+=0[,0],0(,0) +setlocal nosi "turn off smart indent so we don't over analyze } blocks + +if exists("*GetMmaIndent") +    finish +endif + +function GetMmaIndent() + +    " Hit the start of the file, use zero indent. +    if v:lnum == 0 +        return 0 +    endif + +     " Find a non-blank line above the current line. +    let lnum = prevnonblank(v:lnum - 1) + +    " use indenting as a base +    let ind = indent(v:lnum) +    let lnum = v:lnum + +    " if previous line has an unmatched bracket, or ( indent. +    " doesn't do multiple parens/blocks/etc... + +    " also, indent only if this line if this line isn't starting a new +    " block... TODO - fix this with indentkeys? +    if getline(v:lnum-1) =~ '\\\@<!\%(\[[^\]]*\|([^)]*\|{[^}]*\)$' && getline(v:lnum) !~ '\s\+[\[({]' +        let ind = ind+shiftwidth() +    endif + +    " if this line had unmatched closing block, +    " indent to the matching opening block +    if getline(v:lnum) =~ '[^[]*]\s*$' +        " move to the closing bracket +        call search(']','bW') +        " and find it's partner's indent +        let ind = indent(searchpair('\[','',']','bWn')) +    " same for ( blocks +    elseif getline(v:lnum) =~ '[^(]*)$' +        call search(')','bW') +        let ind = indent(searchpair('(','',')','bWn')) + +    " and finally, close { blocks if si ain't already set +    elseif getline(v:lnum) =~ '[^{]*}' +        call search('}','bW') +        let ind = indent(searchpair('{','','}','bWn')) +    endif + +    return ind +endfunction + + +endif diff --git a/indent/mp.vim b/indent/mp.vim new file mode 100644 index 00000000..36c3f716 --- /dev/null +++ b/indent/mp.vim @@ -0,0 +1,364 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" MetaPost indent file +" Language:           MetaPost +" Maintainer:         Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Eugene Minkovskii <emin@mccme.ru> +" Last Change:        2016 Oct 2, 4:13pm +" Version: 0.2 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetMetaPostIndent() +setlocal indentkeys+==end,=else,=fi,=fill,0),0] + +let b:undo_indent = "setl indentkeys< indentexpr<" + +" Only define the function once. +if exists("*GetMetaPostIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +function GetMetaPostIndent() +  let ignorecase_save = &ignorecase +  try +    let &ignorecase = 0 +    return GetMetaPostIndentIntern() +  finally +    let &ignorecase = ignorecase_save +  endtry +endfunc + +" Regexps {{{ +" Note: the next three variables are made global so that a user may add +" further keywords. +" +" Example: +" +"    Put these in ~/.vim/after/indent/mp.vim +" +"    let g:mp_open_tag .= '\|\<begintest\>' +"    let g:mp_close_tag .= '\|\<endtest\>' + +" Expressions starting indented blocks +let g:mp_open_tag = '' +      \ . '\<if\>' +      \ . '\|\<else\%[if]\>' +      \ . '\|\<for\%(\|ever\|suffixes\)\>' +      \ . '\|\<begingroup\>' +      \ . '\|\<\%(\|var\|primary\|secondary\|tertiary\)def\>' +      \ . '\|^\s*\<begin\%(fig\|graph\|glyph\|char\|logochar\)\>' +      \ . '\|[([{]' + +" Expressions ending indented blocks +let g:mp_close_tag = '' +      \ . '\<fi\>' +      \ . '\|\<else\%[if]\>' +      \ . '\|\<end\%(\|for\|group\|def\|fig\|char\|glyph\|graph\)\>' +      \ . '\|[)\]}]' + +" Statements that may span multiple lines and are ended by a semicolon. To +" keep this list short, statements that are unlikely to be very long or are +" not very common (e.g., keywords like `interim` or `showtoken`) are not +" included. +" +" The regex for assignments and equations (the last branch) is tricky, because +" it must not match things like `for i :=`, `if a=b`, `def...=`, etc... It is +" not perfect, but it works reasonably well. +let g:mp_statement = '' +      \ . '\<\%(\|un\|cut\)draw\>' +      \ . '\|\<\%(\|un\)fill\%[draw]\>' +      \ . '\|\<draw\%(dbl\)\=arrow\>' +      \ . '\|\<clip\>' +      \ . '\|\<addto\>' +      \ . '\|\<save\>' +      \ . '\|\<setbounds\>' +      \ . '\|\<message\>' +      \ . '\|\<errmessage\>' +      \ . '\|\<errhelp\>' +      \ . '\|\<fontmapline\>' +      \ . '\|\<pickup\>' +      \ . '\|\<show\>' +      \ . '\|\<special\>' +      \ . '\|\<write\>' +      \ . '\|\%(^\|;\)\%([^;=]*\%('.g:mp_open_tag.'\)\)\@!.\{-}:\==' + +" A line ends with zero or more spaces, possibly followed by a comment. +let s:eol = '\s*\%($\|%\)' +" }}} + +" Auxiliary functions {{{ +" Returns 1 if (0-based) position immediately preceding `pos` in `line` is +" inside a string or a comment; returns 0 otherwise. + +" This is the function that is called more often when indenting, so it is +" critical that it is efficient. The method we use is significantly faster +" than using syntax attributes, and more general (it does not require +" syntax_items). It is also faster than using a single regex matching an even +" number of quotes. It helps that MetaPost strings cannot span more than one +" line and cannot contain escaped quotes. +function! s:CommentOrString(line, pos) +  let in_string = 0 +  let q = stridx(a:line, '"') +  let c = stridx(a:line, '%') +  while q >= 0 && q < a:pos +    if c >= 0 && c < q +      if in_string " Find next percent symbol +        let c = stridx(a:line, '%', q + 1) +      else " Inside comment +        return 1 +      endif +    endif +    let in_string = 1 - in_string +    let q = stridx(a:line, '"', q + 1) " Find next quote +  endwhile +  return in_string || (c >= 0 && c <= a:pos) +endfunction + +" Find the first non-comment non-blank line before the current line. +function! s:PrevNonBlankNonComment(lnum) +  let l:lnum = prevnonblank(a:lnum - 1) +  while getline(l:lnum) =~# '^\s*%' +    let l:lnum = prevnonblank(l:lnum - 1) +  endwhile +  return l:lnum +endfunction + +" Returns true if the last tag appearing in the line is an open tag; returns +" false otherwise. +function! s:LastTagIsOpen(line) +  let o = s:LastValidMatchEnd(a:line, g:mp_open_tag, 0) +  if o == - 1 | return v:false | endif +  return s:LastValidMatchEnd(a:line, g:mp_close_tag, o) < 0 +endfunction + +" A simple, efficient and quite effective heuristics is used to test whether +" a line should cause the next line to be indented: count the "opening tags" +" (if, for, def, ...) in the line, count the "closing tags" (endif, endfor, +" ...) in the line, and compute the difference. We call the result the +" "weight" of the line. If the weight is positive, then the next line should +" most likely be indented. Note that `else` and `elseif` are both opening and +" closing tags, so they "cancel out" in almost all cases, the only exception +" being a leading `else[if]`, which is counted as an opening tag, but not as +" a closing tag (so that, for instance, a line containing a single `else:` +" will have weight equal to one, not zero). We do not treat a trailing +" `else[if]` in any special way, because lines ending with an open tag are +" dealt with separately before this function is called (see +" GetMetaPostIndentIntern()). +" +" Example: +" +"     forsuffixes $=a,b: if x.$ = y.$ : draw else: fill fi +"       % This line will be indented because |{forsuffixes,if,else}| > |{else,fi}| (3 > 2) +"     endfor + +function! s:Weight(line) +  let [o, i] = [0, s:ValidMatchEnd(a:line, g:mp_open_tag, 0)] +  while i > 0 +    let o += 1 +    let i = s:ValidMatchEnd(a:line, g:mp_open_tag, i) +  endwhile +  let [c, i] = [0, matchend(a:line, '^\s*\<else\%[if]\>')] " Skip a leading else[if] +  let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) +  while i > 0 +    let c += 1 +    let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) +  endwhile +  return o - c +endfunction + +" Similar to matchend(), but skips strings and comments. +" line: a String +function! s:ValidMatchEnd(line, pat, start) +  let i = matchend(a:line, a:pat, a:start) +  while i > 0 && s:CommentOrString(a:line, i) +    let i = matchend(a:line, a:pat, i) +  endwhile +  return i +endfunction + +" Like s:ValidMatchEnd(), but returns the end position of the last (i.e., +" rightmost) match. +function! s:LastValidMatchEnd(line, pat, start) +  let last_found = -1 +  let i = matchend(a:line, a:pat, a:start) +  while i > 0 +    if !s:CommentOrString(a:line, i) +      let last_found = i +    endif +    let i = matchend(a:line, a:pat, i) +  endwhile +  return last_found +endfunction + +function! s:DecreaseIndentOnClosingTag(curr_indent) +  let cur_text = getline(v:lnum) +  if cur_text =~# '^\s*\%('.g:mp_close_tag.'\)' +    return max([a:curr_indent - shiftwidth(), 0]) +  endif +  return a:curr_indent +endfunction +" }}} + +" Main function {{{ +" +" Note: Every rule of indentation in MetaPost is very subjective. We might get +" creative, but things get murky very soon (there are too many corner cases). +" So, we provide a means for the user to decide what to do when this script +" doesn't get it. We use a simple idea: use '%>', '%<' and '%=' to explicitly +" control indentation. The '<' and '>' symbols may be repeated many times +" (e.g., '%>>' will cause the next line to be indented twice). +" +" By using '%>...', '%<...' and '%=', the indentation the user wants is +" preserved by commands like gg=G, even if it does not follow the rules of +" this script. +" +" Example: +" +"    def foo = +"        makepen( +"            subpath(T-n,t) of r  %> +"                shifted .5down   %> +"                    --subpath(t,T) of r shifted .5up -- cycle   %<<< +"        ) +"        withcolor black +"    enddef +" +" The default indentation of the previous example would be: +" +"    def foo = +"        makepen( +"            subpath(T-n,t) of r +"            shifted .5down +"            --subpath(t,T) of r shifted .5up -- cycle +"        ) +"        withcolor black +"    enddef +" +" Personally, I prefer the latter, but anyway... +function! GetMetaPostIndentIntern() +  " Do not touch indentation inside verbatimtex/btex.. etex blocks. +  if synIDattr(synID(v:lnum, 1, 1), "name") =~# '^mpTeXinsert$\|^tex\|^Delimiter' +    return -1 +  endif + +  " This is the reference line relative to which the current line is indented +  " (but see below). +  let lnum = s:PrevNonBlankNonComment(v:lnum) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let prev_text = getline(lnum) + +  " User-defined overrides take precedence over anything else. +  " See above for an example. +  let j = match(prev_text, '%[<>=]') +  if j > 0 +    let i = strlen(matchstr(prev_text, '%>\+', j)) - 1 +    if i > 0 +      return indent(lnum) + i * shiftwidth() +    endif + +    let i = strlen(matchstr(prev_text, '%<\+', j)) - 1 +    if i > 0 +      return max([indent(lnum) - i * shiftwidth(), 0]) +    endif + +    if match(prev_text, '%=', j) +      return indent(lnum) +    endif +  endif + +  " If the reference line ends with an open tag, indent. +  " +  " Example: +  " +  " if c: +  "     0 +  " else: +  "     1 +  " fi if c2: % Note that this line has weight equal to zero. +  "     ...   % This line will be indented +  if s:LastTagIsOpen(prev_text) +    return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) +  endif + +  " Lines with a positive weight are unbalanced and should likely be indented. +  " +  " Example: +  " +  " def f = enddef for i = 1 upto 5: if x[i] > 0: 1 else: 2 fi +  "     ... % This line will be indented (because of the unterminated `for`) +  if s:Weight(prev_text) > 0 +    return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) +  endif + +  " Unterminated statements cause indentation to kick in. +  " +  " Example: +  " +  " draw unitsquare +  "     withcolor black; % This line is indented because of `draw`. +  " x := a + b + c +  "     + d + e;         % This line is indented because of `:=`. +  " +  let i = s:LastValidMatchEnd(prev_text, g:mp_statement, 0) +  if i >= 0 " Does the line contain a statement? +    if s:ValidMatchEnd(prev_text, ';', i) < 0 " Is the statement unterminated? +      return indent(lnum) + shiftwidth() +    else +      return s:DecreaseIndentOnClosingTag(indent(lnum)) +    endif +  endif + +  " Deal with the special case of a statement spanning multiple lines. If the +  " current reference line L ends with a semicolon, search backwards for +  " another semicolon or a statement keyword. If the latter is found first, +  " its line is used as the reference line for indenting the current line +  " instead of L. +  " +  "  Example: +  " +  "  if cond: +  "    draw if a: z0 else: z1 fi +  "        shifted S +  "        scaled T;      % L +  " +  "    for i = 1 upto 3:  % <-- Current line: this gets the same indent as `draw ...` +  " +  " NOTE: we get here only if L does not contain a statement (among those +  " listed in g:mp_statement). +  if s:ValidMatchEnd(prev_text, ';'.s:eol, 0) >= 0 " L ends with a semicolon +    let stm_lnum = s:PrevNonBlankNonComment(lnum) +    while stm_lnum > 0 +      let prev_text = getline(stm_lnum) +      let sc_pos = s:LastValidMatchEnd(prev_text, ';', 0) +      let stm_pos = s:ValidMatchEnd(prev_text, g:mp_statement, sc_pos) +      if stm_pos > sc_pos +        let lnum = stm_lnum +        break +      elseif sc_pos > stm_pos +        break +      endif +      let stm_lnum = s:PrevNonBlankNonComment(stm_lnum) +    endwhile +  endif + +  return s:DecreaseIndentOnClosingTag(indent(lnum)) +endfunction +" }}} + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2:fdm=marker + +endif diff --git a/indent/objc.vim b/indent/objc.vim new file mode 100644 index 00000000..f9405b2b --- /dev/null +++ b/indent/objc.vim @@ -0,0 +1,83 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"   Vim indent file +"   Language:	    Objective-C +"   Maintainer:	    Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com> +"   Last Change:    2004 May 16 +" + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 +setlocal cindent + +" Set the function to do the work. +setlocal indentexpr=GetObjCIndent() + +" To make a colon (:) suggest an indentation other than a goto/swich label, +setlocal indentkeys-=: +setlocal indentkeys+=<:> + +" Only define the function once. +if exists("*GetObjCIndent") +    finish +endif + +function s:GetWidth(line, regexp) +    let end = matchend(a:line, a:regexp) +    let width = 0 +    let i = 0 +    while i < end +	if a:line[i] != "\t" +	    let width = width + 1 +	else +	    let width = width + &ts - (width % &ts) +	endif +	let i = i + 1 +    endwhile +    return width +endfunction + +function s:LeadingWhiteSpace(line) +    let end = strlen(a:line) +    let width = 0 +    let i = 0 +    while i < end +	let char = a:line[i] +	if char != " " && char != "\t" +	    break +	endif +	if char != "\t" +	    let width = width + 1 +	else +	    let width = width + &ts - (width % &ts) +	endif +	let i = i + 1 +    endwhile +    return width +endfunction + + +function GetObjCIndent() +    let theIndent = cindent(v:lnum) + +    let prev_line = getline(v:lnum - 1) +    let cur_line = getline(v:lnum) + +    if prev_line !~# ":" || cur_line !~# ":" +	return theIndent +    endif + +    if prev_line !~# ";" +	let prev_colon_pos = s:GetWidth(prev_line, ":") +	let delta = s:GetWidth(cur_line, ":") - s:LeadingWhiteSpace(cur_line) +	let theIndent = prev_colon_pos - delta +    endif + +    return theIndent +endfunction + +endif diff --git a/indent/ocaml.vim b/indent/ocaml.vim index dac76ab8..71298d9b 100644 --- a/indent/ocaml.vim +++ b/indent/ocaml.vim @@ -1,3 +1,280 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     OCaml +" Maintainers:  Jean-Francois Yuen   <jfyuen@happycoders.org> +"               Mike Leary           <leary@nwlink.com> +"               Markus Mottl         <markus.mottl@gmail.com> +" URL:          http://www.ocaml.info/vim/indent/ocaml.vim +" Last Change:  2017 Jun 13 +"               2005 Jun 25 - Fixed multiple bugs due to 'else\nreturn ind' working +"               2005 May 09 - Added an option to not indent OCaml-indents specially (MM) +"               2013 June   - commented textwidth (Marc Weber) +" +" Marc Weber's comment: This file may contain a lot of (very custom) stuff +" which eventually should be moved somewhere else .. + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal expandtab +setlocal indentexpr=GetOCamlIndent() +setlocal indentkeys+=0=and,0=class,0=constraint,0=done,0=else,0=end,0=exception,0=external,0=if,0=in,0=include,0=inherit,0=initializer,0=let,0=method,0=open,0=then,0=type,0=val,0=with,0;;,0>\],0\|\],0>},0\|,0},0\],0) +setlocal nolisp +setlocal nosmartindent + +" At least Marc Weber and Markus Mottl do not like this: +" setlocal textwidth=80 + +" Comment formatting +if !exists("no_ocaml_comments") + if (has("comments")) +   setlocal comments=sr:(*,mb:*,ex:*) +   setlocal fo=cqort + endif +endif + +" Only define the function once. +if exists("*GetOCamlIndent") + finish +endif + +" Define some patterns: +let s:beflet = '^\s*\(initializer\|method\|try\)\|\(\<\(begin\|do\|else\|in\|then\|try\)\|->\|<-\|=\|;\|(\)\s*$' +let s:letpat = '^\s*\(let\|type\|module\|class\|open\|exception\|val\|include\|external\)\>' +let s:letlim = '\(\<\(sig\|struct\)\|;;\)\s*$' +let s:lim = '^\s*\(exception\|external\|include\|let\|module\|open\|type\|val\)\>' +let s:module = '\<\%(begin\|sig\|struct\|object\)\>' +let s:obj = '^\s*\(constraint\|inherit\|initializer\|method\|val\)\>\|\<\(object\|object\s*(.*)\)\s*$' +let s:type = '^\s*\%(class\|let\|type\)\>.*=' + +" Skipping pattern, for comments +function! s:GetLineWithoutFullComment(lnum) + let lnum = prevnonblank(a:lnum - 1) + let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') + while lline =~ '^\s*$' && lnum > 0 +   let lnum = prevnonblank(lnum - 1) +   let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') + endwhile + return lnum +endfunction + +" Indent for ';;' to match multiple 'let' +function! s:GetInd(lnum, pat, lim) + let llet = search(a:pat, 'bW') + let old = indent(a:lnum) + while llet > 0 +   let old = indent(llet) +   let nb = s:GetLineWithoutFullComment(llet) +   if getline(nb) =~ a:lim +     return old +   endif +   let llet = search(a:pat, 'bW') + endwhile + return old +endfunction + +" Indent pairs +function! s:FindPair(pstart, pmid, pend) + call search(a:pend, 'bW') + return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) +endfunction + +" Indent 'let' +function! s:FindLet(pstart, pmid, pend) + call search(a:pend, 'bW') + return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") =~ "^\\s*let\\>.*=.*\\<in\\s*$" || getline(prevnonblank(".") - 1) =~ s:beflet')) +endfunction + +function! GetOCamlIndent() + " Find a non-commented line above the current line. + let lnum = s:GetLineWithoutFullComment(v:lnum) + + " At the start of the file use zero indent. + if lnum == 0 +   return 0 + endif + + let ind = indent(lnum) + let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '') + + " Return double 'shiftwidth' after lines matching: + if lline =~ '^\s*|.*->\s*$' +   return ind + 2 * shiftwidth() + endif + + let line = getline(v:lnum) + + " Indent if current line begins with 'end': + if line =~ '^\s*end\>' +   return s:FindPair(s:module, '','\<end\>') + + " Indent if current line begins with 'done' for 'do': + elseif line =~ '^\s*done\>' +   return s:FindPair('\<do\>', '','\<done\>') + + " Indent if current line begins with '}' or '>}': + elseif line =~ '^\s*\(\|>\)}' +   return s:FindPair('{', '','}') + + " Indent if current line begins with ']', '|]' or '>]': + elseif line =~ '^\s*\(\||\|>\)\]' +   return s:FindPair('\[', '','\]') + + " Indent if current line begins with ')': + elseif line =~ '^\s*)' +   return s:FindPair('(', '',')') + + " Indent if current line begins with 'let': + elseif line =~ '^\s*let\>' +   if lline !~ s:lim . '\|' . s:letlim . '\|' . s:beflet +     return s:FindLet(s:type, '','\<let\s*$') +   endif + + " Indent if current line begins with 'class' or 'type': + elseif line =~ '^\s*\(class\|type\)\>' +   if lline !~ s:lim . '\|\<and\s*$\|' . s:letlim +     return s:FindLet(s:type, '','\<\(class\|type\)\s*$') +   endif + + " Indent for pattern matching: + elseif line =~ '^\s*|' +   if lline !~ '^\s*\(|[^\]]\|\(match\|type\|with\)\>\)\|\<\(function\|parser\|private\|with\)\s*$' +     call search('|', 'bW') +     return indent(searchpair('^\s*\(match\|type\)\>\|\<\(function\|parser\|private\|with\)\s*$', '', '^\s*|', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") !~ "^\\s*|.*->"')) +   endif + + " Indent if current line begins with ';;': + elseif line =~ '^\s*;;' +   if lline !~ ';;\s*$' +     return s:GetInd(v:lnum, s:letpat, s:letlim) +   endif + + " Indent if current line begins with 'in': + elseif line =~ '^\s*in\>' +   if lline !~ '^\s*\(let\|and\)\>' +     return s:FindPair('\<let\>', '', '\<in\>') +   endif + + " Indent if current line begins with 'else': + elseif line =~ '^\s*else\>' +   if lline !~ '^\s*\(if\|then\)\>' +     return s:FindPair('\<if\>', '', '\<else\>') +   endif + + " Indent if current line begins with 'then': + elseif line =~ '^\s*then\>' +   if lline !~ '^\s*\(if\|else\)\>' +     return s:FindPair('\<if\>', '', '\<then\>') +   endif + + " Indent if current line begins with 'and': + elseif line =~ '^\s*and\>' +   if lline !~ '^\s*\(and\|let\|type\)\>\|\<end\s*$' +     return ind - shiftwidth() +   endif + + " Indent if current line begins with 'with': + elseif line =~ '^\s*with\>' +   if lline !~ '^\s*\(match\|try\)\>' +     return s:FindPair('\<\%(match\|try\)\>', '','\<with\>') +   endif + + " Indent if current line begins with 'exception', 'external', 'include' or + " 'open': + elseif line =~ '^\s*\(exception\|external\|include\|open\)\>' +   if lline !~ s:lim . '\|' . s:letlim +     call search(line) +     return indent(search('^\s*\(\(exception\|external\|include\|open\|type\)\>\|val\>.*:\)', 'bW')) +   endif + + " Indent if current line begins with 'val': + elseif line =~ '^\s*val\>' +   if lline !~ '^\s*\(exception\|external\|include\|open\)\>\|' . s:obj . '\|' . s:letlim +     return indent(search('^\s*\(\(exception\|include\|initializer\|method\|open\|type\|val\)\>\|external\>.*:\)', 'bW')) +   endif + + " Indent if current line begins with 'constraint', 'inherit', 'initializer' + " or 'method': + elseif line =~ '^\s*\(constraint\|inherit\|initializer\|method\)\>' +   if lline !~ s:obj +     return indent(search('\<\(object\|object\s*(.*)\)\s*$', 'bW')) + shiftwidth() +   endif + + endif + + " Add a 'shiftwidth' after lines ending with: + if lline =~ '\(:\|=\|->\|<-\|(\|\[\|{\|{<\|\[|\|\[<\|\<\(begin\|do\|else\|fun\|function\|functor\|if\|initializer\|object\|parser\|private\|sig\|struct\|then\|try\)\|\<object\s*(.*)\)\s*$' +   let ind = ind + shiftwidth() + + " Back to normal indent after lines ending with ';;': + elseif lline =~ ';;\s*$' && lline !~ '^\s*;;' +   let ind = s:GetInd(v:lnum, s:letpat, s:letlim) + + " Back to normal indent after lines ending with 'end': + elseif lline =~ '\<end\s*$' +   let ind = s:FindPair(s:module, '','\<end\>') + + " Back to normal indent after lines ending with 'in': + elseif lline =~ '\<in\s*$' && lline !~ '^\s*in\>' +   let ind = s:FindPair('\<let\>', '', '\<in\>') + + " Back to normal indent after lines ending with 'done': + elseif lline =~ '\<done\s*$' +   let ind = s:FindPair('\<do\>', '','\<done\>') + + " Back to normal indent after lines ending with '}' or '>}': + elseif lline =~ '\(\|>\)}\s*$' +   let ind = s:FindPair('{', '','}') + + " Back to normal indent after lines ending with ']', '|]' or '>]': + elseif lline =~ '\(\||\|>\)\]\s*$' +   let ind = s:FindPair('\[', '','\]') + + " Back to normal indent after comments: + elseif lline =~ '\*)\s*$' +   call search('\*)', 'bW') +   let ind = indent(searchpair('(\*', '', '\*)', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')) + + " Back to normal indent after lines ending with ')': + elseif lline =~ ')\s*$' +   let ind = s:FindPair('(', '',')') + + " If this is a multiline comment then align '*': + elseif lline =~ '^\s*(\*' && line =~ '^\s*\*' +   let ind = ind + 1 + + else + " Don't change indentation of this line + " for new lines (indent==0) use indentation of previous line + + " This is for preventing removing indentation of these args: + "   let f x = + "     let y = x + 1 in + "     Printf.printf + "       "o"           << here + "       "oeuth"       << don't touch indentation + +   let i = indent(v:lnum) +   return i == 0 ? ind : i + + endif + + " Subtract a 'shiftwidth' after lines matching 'match ... with parser': + if lline =~ '\<match\>.*\<with\>\s*\<parser\s*$' +   let ind = ind - shiftwidth() + endif + + return ind + +endfunction + +" vim:sw=2 + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ocaml') == -1  " Vim indent file diff --git a/indent/occam.vim b/indent/occam.vim new file mode 100644 index 00000000..f074395c --- /dev/null +++ b/indent/occam.vim @@ -0,0 +1,191 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	occam +" Maintainer:	Mario Schweigler <ms44@kent.ac.uk> +" Last Change:	23 April 2003 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +"{{{  Settings +" Set the occam indent function +setlocal indentexpr=GetOccamIndent() +" Indent after new line and after initial colon +setlocal indentkeys=o,O,0=: +"}}} + +" Only define the function once +if exists("*GetOccamIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +"{{{  Indent definitions +" Define carriage return indent +let s:FirstLevelIndent = '^\C\s*\(IF\|ALT\|PRI\s\+ALT\|PAR\|SEQ\|PRI\s\+PAR\|WHILE\|VALOF\|CLAIM\|FORKING\)\>\|\(--.*\)\@<!\(\<PROC\>\|??\|\<CASE\>\s*\(--.*\)\=\_$\)' +let s:FirstLevelNonColonEndIndent = '^\C\s*PROTOCOL\>\|\(--.*\)\@<!\<\(\(CHAN\|DATA\)\s\+TYPE\|FUNCTION\)\>' +let s:SecondLevelIndent = '^\C\s*\(IF\|ALT\|PRI\s\+ALT\)\>\|\(--.*\)\@<!?\s*\<CASE\>\s*\(--.*\)\=\_$' +let s:SecondLevelNonColonEndIndent = '\(--.*\)\@<!\<\(CHAN\|DATA\)\s\+TYPE\>' + +" Define colon indent +let s:ColonIndent = '\(--.*\)\@<!\<PROC\>' +let s:ColonNonColonEndIndent = '^\C\s*PROTOCOL\>\|\(--.*\)\@<!\<\(\(CHAN\|DATA\)\s\+TYPE\|FUNCTION\)\>' + +let s:ColonEnd = '\(--.*\)\@<!:\s*\(--.*\)\=$' +let s:ColonStart = '^\s*:\s*\(--.*\)\=$' + +" Define comment +let s:CommentLine = '^\s*--' +"}}} + +"{{{  function GetOccamIndent() +" Auxiliary function to get the correct indent for a line of occam code +function GetOccamIndent() + +  " Ensure magic is on +  let save_magic = &magic +  setlocal magic + +  " Get reference line number +  let linenum = prevnonblank(v:lnum - 1) +  while linenum > 0 && getline(linenum) =~ s:CommentLine +    let linenum = prevnonblank(linenum - 1) +  endwhile + +  " Get current indent +  let curindent = indent(linenum) + +  " Get current line +  let line = getline(linenum) + +  " Get previous line number +  let prevlinenum = prevnonblank(linenum - 1) +  while prevlinenum > 0 && getline(prevlinenum) =~ s:CommentLine +    let prevlinenum = prevnonblank(prevlinenum - 1) +  endwhile + +  " Get previous line +  let prevline = getline(prevlinenum) + +  " Colon indent +  if getline(v:lnum) =~ s:ColonStart + +    let found = 0 + +    while found < 1 + +      if line =~ s:ColonStart +	let found = found - 1 +      elseif line =~ s:ColonIndent || (line =~ s:ColonNonColonEndIndent && line !~ s:ColonEnd) +	let found = found + 1 +      endif + +      if found < 1 +	let linenum = prevnonblank(linenum - 1) +	if linenum > 0 +	  let line = getline(linenum) +	else +	  let found = 1 +	endif +      endif + +    endwhile + +    if linenum > 0 +      let curindent = indent(linenum) +    else +      let colonline = getline(v:lnum) +      let tabstr = '' +      while strlen(tabstr) < &tabstop +	let tabstr = ' ' . tabstr +      endwhile +      let colonline = substitute(colonline, '\t', tabstr, 'g') +      let curindent = match(colonline, ':') +    endif + +    " Restore magic +    if !save_magic|setlocal nomagic|endif + +    return curindent +  endif + +  if getline(v:lnum) =~ '^\s*:' +    let colonline = getline(v:lnum) +    let tabstr = '' +    while strlen(tabstr) < &tabstop +      let tabstr = ' ' . tabstr +    endwhile +    let colonline = substitute(colonline, '\t', tabstr, 'g') +    let curindent = match(colonline, ':') + +    " Restore magic +    if !save_magic|setlocal nomagic|endif + +    return curindent +  endif + +  " Carriage return indenat +  if line =~ s:FirstLevelIndent || (line =~ s:FirstLevelNonColonEndIndent && line !~ s:ColonEnd) +	\ || (line !~ s:ColonStart && (prevline =~ s:SecondLevelIndent +	\ || (prevline =~ s:SecondLevelNonColonEndIndent && prevline !~ s:ColonEnd))) +    let curindent = curindent + shiftwidth() + +    " Restore magic +    if !save_magic|setlocal nomagic|endif + +    return curindent +  endif + +  " Commented line +  if getline(prevnonblank(v:lnum - 1)) =~ s:CommentLine + +    " Restore magic +    if !save_magic|setlocal nomagic|endif + +    return indent(prevnonblank(v:lnum - 1)) +  endif + +  " Look for previous second level IF / ALT / PRI ALT +  let found = 0 + +  while !found + +    if indent(prevlinenum) == curindent - shiftwidth() +      let found = 1 +    endif + +    if !found +      let prevlinenum = prevnonblank(prevlinenum - 1) +      while prevlinenum > 0 && getline(prevlinenum) =~ s:CommentLine +	let prevlinenum = prevnonblank(prevlinenum - 1) +      endwhile +      if prevlinenum == 0 +	let found = 1 +      endif +    endif + +  endwhile + +  if prevlinenum > 0 +    if getline(prevlinenum) =~ s:SecondLevelIndent +      let curindent = curindent + shiftwidth() +    endif +  endif + +  " Restore magic +  if !save_magic|setlocal nomagic|endif + +  return curindent + +endfunction +"}}} + +let &cpo = s:keepcpo +unlet s:keepcpo + +endif diff --git a/indent/pascal.vim b/indent/pascal.vim new file mode 100644 index 00000000..b20fb56d --- /dev/null +++ b/indent/pascal.vim @@ -0,0 +1,232 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    Pascal +" Maintainer:  Neil Carter <n.carter@swansea.ac.uk> +" Created:     2004 Jul 13 +" Last Change: 2017 Jun 13 +" +" This is version 2.0, a complete rewrite. +" +" For further documentation, see http://psy.swansea.ac.uk/staff/carter/vim/ + + +if exists("b:did_indent") +	finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetPascalIndent(v:lnum) +setlocal indentkeys& +setlocal indentkeys+==end;,==const,==type,==var,==begin,==repeat,==until,==for +setlocal indentkeys+==program,==function,==procedure,==object,==private +setlocal indentkeys+==record,==if,==else,==case + +if exists("*GetPascalIndent") +	finish +endif + + +function! s:GetPrevNonCommentLineNum( line_num ) + +	" Skip lines starting with a comment +	let SKIP_LINES = '^\s*\(\((\*\)\|\(\*\ \)\|\(\*)\)\|{\|}\)' + +	let nline = a:line_num +	while nline > 0 +		let nline = prevnonblank(nline-1) +		if getline(nline) !~? SKIP_LINES +			break +		endif +	endwhile + +	return nline +endfunction + + +function! s:PurifyCode( line_num ) +	" Strip any trailing comments and whitespace +	let pureline = 'TODO' +	return pureline +endfunction + + +function! GetPascalIndent( line_num ) + +	" Line 0 always goes at column 0 +	if a:line_num == 0 +		return 0 +	endif + +	let this_codeline = getline( a:line_num ) + + +	" SAME INDENT + +	" Middle of a three-part comment +	if this_codeline =~ '^\s*\*' +		return indent( a:line_num - 1) +	endif + + +	" COLUMN 1 ALWAYS + +	" Last line of the program +	if this_codeline =~ '^\s*end\.' +		return 0 +	endif + +	" Compiler directives, allowing "(*" and "{" +	"if this_codeline =~ '^\s*\({\|(\*\)$\(IFDEF\|IFNDEF\|ELSE\|ENDIF\)' +	if this_codeline =~ '^\s*\({\|(\*\)\$' +		return 0 +	endif + +	" section headers +	if this_codeline =~ '^\s*\(program\|procedure\|function\|type\)\>' +		return 0 +	endif + +	" Subroutine separators, lines ending with "const" or "var" +	if this_codeline =~ '^\s*\((\*\ _\+\ \*)\|\(const\|var\)\)$' +		return 0 +	endif + + +	" OTHERWISE, WE NEED TO LOOK FURTHER BACK... + +	let prev_codeline_num = s:GetPrevNonCommentLineNum( a:line_num ) +	let prev_codeline = getline( prev_codeline_num ) +	let indnt = indent( prev_codeline_num ) + + +	" INCREASE INDENT + +	" If the PREVIOUS LINE ended in these items, always indent +	if prev_codeline =~ '\<\(type\|const\|var\)$' +		return indnt + shiftwidth() +	endif + +	if prev_codeline =~ '\<repeat$' +		if this_codeline !~ '^\s*until\>' +			return indnt + shiftwidth() +		else +			return indnt +		endif +	endif + +	if prev_codeline =~ '\<\(begin\|record\)$' +		if this_codeline !~ '^\s*end\>' +			return indnt + shiftwidth() +		else +			return indnt +		endif +	endif + +	" If the PREVIOUS LINE ended with these items, indent if not +	" followed by "begin" +	if prev_codeline =~ '\<\(\|else\|then\|do\)$' || prev_codeline =~ ':$' +		if this_codeline !~ '^\s*begin\>' +			return indnt + shiftwidth() +		else +			" If it does start with "begin" then keep the same indent +			"return indnt + shiftwidth() +			return indnt +		endif +	endif + +	" Inside a parameter list (i.e. a "(" without a ")"). ???? Considers +	" only the line before the current one. TODO: Get it working for +	" parameter lists longer than two lines. +	if prev_codeline =~ '([^)]\+$' +		return indnt + shiftwidth() +	endif + + +	" DECREASE INDENT + +	" Lines starting with "else", but not following line ending with +	" "end". +	if this_codeline =~ '^\s*else\>' && prev_codeline !~ '\<end$' +		return indnt - shiftwidth() +	endif + +	" Lines after a single-statement branch/loop. +	" Two lines before ended in "then", "else", or "do" +	" Previous line didn't end in "begin" +	let prev2_codeline_num = s:GetPrevNonCommentLineNum( prev_codeline_num ) +	let prev2_codeline = getline( prev2_codeline_num ) +	if prev2_codeline =~ '\<\(then\|else\|do\)$' && prev_codeline !~ '\<begin$' +		" If the next code line after a single statement branch/loop +		" starts with "end", "except" or "finally", we need an +		" additional unindentation. +		if this_codeline =~ '^\s*\(end;\|except\|finally\|\)$' +			" Note that we don't return from here. +			return indnt - 2 * shiftwidth() +		endif +		return indnt - shiftwidth() +	endif + +	" Lines starting with "until" or "end". This rule must be overridden +	" by the one for "end" after a single-statement branch/loop. In +	" other words that rule should come before this one. +	if this_codeline =~ '^\s*\(end\|until\)\>' +		return indnt - shiftwidth() +	endif + + +	" MISCELLANEOUS THINGS TO CATCH + +	" Most "begin"s will have been handled by now. Any remaining +	" "begin"s on their own line should go in column 1. +	if this_codeline =~ '^\s*begin$' +		return 0 +	endif + + +" ____________________________________________________________________ +" Object/Borland Pascal/Delphi Extensions +" +" Note that extended-pascal is handled here, unless it is simpler to +" handle them in the standard-pascal section above. + + +	" COLUMN 1 ALWAYS + +	" section headers at start of line. +	if this_codeline =~ '^\s*\(interface\|implementation\|uses\|unit\)\>' +		return 0 +	endif + + +	" INDENT ONCE + +	" If the PREVIOUS LINE ended in these items, always indent. +	if prev_codeline =~ '^\s*\(unit\|uses\|try\|except\|finally\|private\|protected\|public\|published\)$' +		return indnt + shiftwidth() +	endif + +	" ???? Indent "procedure" and "functions" if they appear within an +	" class/object definition. But that means overriding standard-pascal +	" rule where these words always go in column 1. + + +	" UNINDENT ONCE + +	if this_codeline =~ '^\s*\(except\|finally\)$' +		return indnt - shiftwidth() +	endif + +	if this_codeline =~ '^\s*\(private\|protected\|public\|published\)$' +		return indnt - shiftwidth() +	endif + + +" ____________________________________________________________________ + +	" If nothing changed, return same indent. +	return indnt +endfunction + + +endif diff --git a/indent/perl.vim b/indent/perl.vim index 42cc1d01..d515844e 100644 --- a/indent/perl.vim +++ b/indent/perl.vim @@ -1,3 +1,187 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:      Perl 5 +" Maintainer:    vim-perl <vim-perl@googlegroups.com> +" Homepage:      http://github.com/vim-perl/vim-perl +" Bugs/requests: http://github.com/vim-perl/vim-perl/issues +" Last Change:   2017-01-04 + +" Suggestions and improvements by : +"   Aaron J. Sherman (use syntax for hints) +"   Artem Chuprina (play nice with folding) + +" TODO things that are not or not properly indented (yet) : +" - Continued statements +"     print "foo", +"       "bar"; +"     print "foo" +"       if bar(); +" - Multiline regular expressions (m//x) +" (The following probably needs modifying the perl syntax file) +" - qw() lists +" - Heredocs with terminators that don't match \I\i* + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +" Is syntax highlighting active ? +let b:indent_use_syntax = has("syntax") + +setlocal indentexpr=GetPerlIndent() +setlocal indentkeys+=0=,0),0],0=or,0=and +if !b:indent_use_syntax +    setlocal indentkeys+=0=EO +endif + +let s:cpo_save = &cpo +set cpo-=C + +function! GetPerlIndent() + +    " Get the line to be indented +    let cline = getline(v:lnum) + +    " Indent POD markers to column 0 +    if cline =~ '^\s*=\L\@!' +        return 0 +    endif + +    " Get current syntax item at the line's first char +    let csynid = '' +    if b:indent_use_syntax +        let csynid = synIDattr(synID(v:lnum,1,0),"name") +    endif + +    " Don't reindent POD and heredocs +    if csynid == "perlPOD" || csynid == "perlHereDoc" || csynid =~ "^pod" +        return indent(v:lnum) +    endif + +    " Indent end-of-heredocs markers to column 0 +    if b:indent_use_syntax +        " Assumes that an end-of-heredoc marker matches \I\i* to avoid +        " confusion with other types of strings +        if csynid == "perlStringStartEnd" && cline =~ '^\I\i*$' +            return 0 +        endif +    else +        " Without syntax hints, assume that end-of-heredocs markers begin with EO +        if cline =~ '^\s*EO' +            return 0 +        endif +    endif + +    " Now get the indent of the previous perl line. + +    " Find a non-blank line above the current line. +    let lnum = prevnonblank(v:lnum - 1) +    " Hit the start of the file, use zero indent. +    if lnum == 0 +        return 0 +    endif +    let line = getline(lnum) +    let ind = indent(lnum) +    " Skip heredocs, POD, and comments on 1st column +    if b:indent_use_syntax +        let skippin = 2 +        while skippin +            let synid = synIDattr(synID(lnum,1,0),"name") +            if (synid == "perlStringStartEnd" && line =~ '^\I\i*$') +                        \ || (skippin != 2 && synid == "perlPOD") +                        \ || (skippin != 2 && synid == "perlHereDoc") +                        \ || synid == "perlComment" +                        \ || synid =~ "^pod" +                let lnum = prevnonblank(lnum - 1) +                if lnum == 0 +                    return 0 +                endif +                let line = getline(lnum) +                let ind = indent(lnum) +                let skippin = 1 +            else +                let skippin = 0 +            endif +        endwhile +    else +        if line =~ "^EO" +            let lnum = search("<<[\"']\\=EO", "bW") +            let line = getline(lnum) +            let ind = indent(lnum) +        endif +    endif + +    " Indent blocks enclosed by {}, (), or [] +    if b:indent_use_syntax +        " Find a real opening brace +        " NOTE: Unlike Perl character classes, we do NOT need to escape the +        " closing brackets with a backslash.  Doing so just puts a backslash +        " in the character class and causes sorrow.  Instead, put the closing +        " bracket as the first character in the class. +        let braceclass = '[][(){}]' +        let bracepos = match(line, braceclass, matchend(line, '^\s*[])}]')) +        while bracepos != -1 +            let synid = synIDattr(synID(lnum, bracepos + 1, 0), "name") +            " If the brace is highlighted in one of those groups, indent it. +            " 'perlHereDoc' is here only to handle the case '&foo(<<EOF)'. +            if synid == "" +                        \ || synid == "perlMatchStartEnd" +                        \ || synid == "perlHereDoc" +                        \ || synid == "perlBraces" +                        \ || synid == "perlStatementIndirObj" +                        \ || synid =~ "^perlFiledescStatement" +                        \ || synid =~ '^perl\(Sub\|Block\|Package\)Fold' +                let brace = strpart(line, bracepos, 1) +                if brace == '(' || brace == '{' || brace == '[' +                    let ind = ind + shiftwidth() +                else +                    let ind = ind - shiftwidth() +                endif +            endif +            let bracepos = match(line, braceclass, bracepos + 1) +        endwhile +        let bracepos = matchend(cline, '^\s*[])}]') +        if bracepos != -1 +            let synid = synIDattr(synID(v:lnum, bracepos, 0), "name") +            if synid == "" +                        \ || synid == "perlMatchStartEnd" +                        \ || synid == "perlBraces" +                        \ || synid == "perlStatementIndirObj" +                        \ || synid =~ '^perl\(Sub\|Block\|Package\)Fold' +                let ind = ind - shiftwidth() +            endif +        endif +    else +        if line =~ '[{[(]\s*\(#[^])}]*\)\=$' +            let ind = ind + shiftwidth() +        endif +        if cline =~ '^\s*[])}]' +            let ind = ind - shiftwidth() +        endif +    endif + +    " Indent lines that begin with 'or' or 'and' +    if cline =~ '^\s*\(or\|and\)\>' +        if line !~ '^\s*\(or\|and\)\>' +            let ind = ind + shiftwidth() +        endif +    elseif line =~ '^\s*\(or\|and\)\>' +        let ind = ind - shiftwidth() +    endif + +    return ind + +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:ts=8:sts=4:sw=4:expandtab:ft=vim + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'perl') == -1  " Vim indent file diff --git a/indent/perl6.vim b/indent/perl6.vim new file mode 100644 index 00000000..81091651 --- /dev/null +++ b/indent/perl6.vim @@ -0,0 +1,136 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:      Perl 6 +" Maintainer:    vim-perl <vim-perl@googlegroups.com> +" Homepage:      http://github.com/vim-perl/vim-perl +" Bugs/requests: http://github.com/vim-perl/vim-perl/issues +" Last Change:   2017 Jun 13 +" Contributors:  Andy Lester <andy@petdance.com> +"                Hinrik Örn Sigurðsson <hinrik.sig@gmail.com> +" +" Adapted from indent/perl.vim by Rafael Garcia-Suarez <rgarciasuarez@free.fr> + +" Suggestions and improvements by : +"   Aaron J. Sherman (use syntax for hints) +"   Artem Chuprina (play nice with folding) +" TODO: +" This file still relies on stuff from the Perl 5 syntax file, which Perl 6 +" does not use. +" +" Things that are not or not properly indented (yet) : +" - Continued statements +"     print "foo", +"       "bar"; +"     print "foo" +"       if bar(); +" - Multiline regular expressions (m//x) +" (The following probably needs modifying the perl syntax file) +" - qw() lists +" - Heredocs with terminators that don't match \I\i* + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +" Is syntax highlighting active ? +let b:indent_use_syntax = has("syntax") + +setlocal indentexpr=GetPerl6Indent() + +" we reset it first because the Perl 5 indent file might have been loaded due +" to a .pl/pm file extension, and indent files don't clean up afterwards +setlocal indentkeys& + +setlocal indentkeys+=0=,0),0],0>,0»,0=or,0=and +if !b:indent_use_syntax +    setlocal indentkeys+=0=EO +endif + +let s:cpo_save = &cpo +set cpo-=C + +function! GetPerl6Indent() + +    " Get the line to be indented +    let cline = getline(v:lnum) + +    " Indent POD markers to column 0 +    if cline =~ '^\s*=\L\@!' +        return 0 +    endif + +    " Don't reindent coments on first column +    if cline =~ '^#' +        return 0 +    endif + +    " Get current syntax item at the line's first char +    let csynid = '' +    if b:indent_use_syntax +        let csynid = synIDattr(synID(v:lnum,1,0),"name") +    endif + +    " Don't reindent POD and heredocs +    if csynid =~ "^p6Pod" +        return indent(v:lnum) +    endif + + +    " Now get the indent of the previous perl line. + +    " Find a non-blank line above the current line. +    let lnum = prevnonblank(v:lnum - 1) +    " Hit the start of the file, use zero indent. +    if lnum == 0 +        return 0 +    endif +    let line = getline(lnum) +    let ind = indent(lnum) +    " Skip heredocs, POD, and comments on 1st column +    if b:indent_use_syntax +        let skippin = 2 +        while skippin +            let synid = synIDattr(synID(lnum,1,0),"name") +            if (synid =~ "^p6Pod" || synid =~ "p6Comment") +                let lnum = prevnonblank(lnum - 1) +                if lnum == 0 +                    return 0 +                endif +                let line = getline(lnum) +                let ind = indent(lnum) +                let skippin = 1 +            else +                let skippin = 0 +            endif +        endwhile +    endif + +        if line =~ '[<«\[{(]\s*\(#[^)}\]»>]*\)\=$' +            let ind = ind + shiftwidth() +        endif +        if cline =~ '^\s*[)}\]»>]' +            let ind = ind - shiftwidth() +        endif + +    " Indent lines that begin with 'or' or 'and' +    if cline =~ '^\s*\(or\|and\)\>' +        if line !~ '^\s*\(or\|and\)\>' +            let ind = ind + shiftwidth() +        endif +    elseif line =~ '^\s*\(or\|and\)\>' +        let ind = ind - shiftwidth() +    endif + +    return ind + +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:ts=8:sts=4:sw=4:expandtab:ft=vim + +endif diff --git a/indent/php.vim b/indent/php.vim new file mode 100644 index 00000000..3676b66f --- /dev/null +++ b/indent/php.vim @@ -0,0 +1,853 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	PHP +" Author:	John Wellesz <John.wellesz (AT) teaser (DOT) fr> +" URL:		http://www.2072productions.com/vim/indent/php.vim +" Home:		https://github.com/2072/PHP-Indenting-for-VIm +" Last Change:	2017 Jun 13 +" Version:	1.62 +" +" +"	Type :help php-indent for available options +" +"	A fully commented version of this file is available on github +" +" +"  If you find a bug, please open a ticket on github.org +"  ( https://github.com/2072/PHP-Indenting-for-VIm/issues ) with an example of +"  code that breaks the algorithm. +" + +" NOTE: This script must be used with PHP syntax ON and with the php syntax +"	script by Lutz Eymers (http://www.isp.de/data/php.vim ) or with the +"	script by Peter Hodge (http://www.vim.org/scripts/script.php?script_id=1571 ) +"	the later is bunbdled by default with Vim 7. +" +" +"	In the case you have syntax errors in your script such as HereDoc end +"	identifiers not at col 1 you'll have to indent your file 2 times (This +"	script will automatically put HereDoc end identifiers at col 1 if +"	they are followed by a ';'). +" + +" NOTE: If you are editing files in Unix file format and that (by accident) +"	there are '\r' before new lines, this script won't be able to proceed +"	correctly and will make many mistakes because it won't be able to match +"	'\s*$' correctly. +"	So you have to remove those useless characters first with a command like: +" +"	:%s /\r$//g +" +"	or simply 'let' the option PHP_removeCRwhenUnix to 1 and the script will +"	silently remove them when VIM load this script (at each bufread). + + + +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + + +let g:php_sync_method = 0 + + +if exists("PHP_default_indenting") +    let b:PHP_default_indenting = PHP_default_indenting * shiftwidth() +else +    let b:PHP_default_indenting = 0 +endif + +if exists("PHP_outdentSLComments") +    let b:PHP_outdentSLComments = PHP_outdentSLComments * shiftwidth() +else +    let b:PHP_outdentSLComments = 0 +endif + +if exists("PHP_BracesAtCodeLevel") +    let b:PHP_BracesAtCodeLevel = PHP_BracesAtCodeLevel +else +    let b:PHP_BracesAtCodeLevel = 0 +endif + + +if exists("PHP_autoformatcomment") +    let b:PHP_autoformatcomment = PHP_autoformatcomment +else +    let b:PHP_autoformatcomment = 1 +endif + +if exists("PHP_outdentphpescape") +    let b:PHP_outdentphpescape = PHP_outdentphpescape +else +    let b:PHP_outdentphpescape = 1 +endif + + +if exists("PHP_vintage_case_default_indent") && PHP_vintage_case_default_indent +    let b:PHP_vintage_case_default_indent = 1 +else +    let b:PHP_vintage_case_default_indent = 0 +endif + + + +let b:PHP_lastindented = 0 +let b:PHP_indentbeforelast = 0 +let b:PHP_indentinghuge = 0 +let b:PHP_CurrentIndentLevel = b:PHP_default_indenting +let b:PHP_LastIndentedWasComment = 0 +let b:PHP_InsideMultilineComment = 0 +let b:InPHPcode = 0 +let b:InPHPcode_checked = 0 +let b:InPHPcode_and_script = 0 +let b:InPHPcode_tofind = "" +let b:PHP_oldchangetick = b:changedtick +let b:UserIsTypingComment = 0 +let b:optionsset = 0 + +setlocal nosmartindent +setlocal noautoindent +setlocal nocindent +setlocal nolisp + +setlocal indentexpr=GetPhpIndent() +setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e,*<Return>,=?>,=<?,=*/ + + + +let s:searchpairflags = 'bWr' + +if &fileformat == "unix" && exists("PHP_removeCRwhenUnix") && PHP_removeCRwhenUnix +    silent! %s/\r$//g +endif + +if exists("*GetPhpIndent") +    call ResetPhpOptions() +    finish +endif + + +let s:PHP_validVariable = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' +let s:notPhpHereDoc = '\%(break\|return\|continue\|exit\|die\|else\)' +let s:blockstart = '\%(\%(\%(}\s*\)\=else\%(\s\+\)\=\)\=if\>\|\%(}\s*\)\?else\>\|do\>\|while\>\|switch\>\|case\>\|default\>\|for\%(each\)\=\>\|declare\>\|class\>\|trait\>\|use\>\|interface\>\|abstract\>\|final\>\|try\>\|\%(}\s*\)\=catch\>\|\%(}\s*\)\=finally\>\)' +let s:functionDecl = '\<function\>\%(\s\+'.s:PHP_validVariable.'\)\=\s*(.*' +let s:endline = '\s*\%(//.*\|#.*\|/\*.*\*/\s*\)\=$' +let s:unstated = '\%(^\s*'.s:blockstart.'.*)\|\%(//.*\)\@<!\<e'.'lse\>\)'.s:endline + + +let s:terminated = '\%(\%(;\%(\s*\%(?>\|}\)\)\=\|<<<\s*[''"]\=\a\w*[''"]\=$\|^\s*}\|^\s*'.s:PHP_validVariable.':\)'.s:endline.'\)' +let s:PHP_startindenttag = '<?\%(.*?>\)\@!\|<script[^>]*>\%(.*<\/script>\)\@!' +let s:structureHead = '^\s*\%(' . s:blockstart . '\)\|'. s:functionDecl . s:endline . '\|\<new\s\+class\>' + + + +let s:escapeDebugStops = 0 +function! DebugPrintReturn(scriptLine) + +    if ! s:escapeDebugStops +	echo "debug:" . a:scriptLine +	let c = getchar() +	if c == "\<Del>" +	    let s:escapeDebugStops = 1 +	end +    endif + +endfunction + +function! GetLastRealCodeLNum(startline) " {{{ + +    let lnum = a:startline + +    if b:GetLastRealCodeLNum_ADD && b:GetLastRealCodeLNum_ADD == lnum + 1 +	let lnum = b:GetLastRealCodeLNum_ADD +    endif + +    while lnum > 1 +	let lnum = prevnonblank(lnum) +	let lastline = getline(lnum) + +	if b:InPHPcode_and_script && lastline =~ '?>\s*$' +	    let lnum = lnum - 1 +	elseif lastline =~ '^\s*?>.*<?\%(php\)\=\s*$' +	    let lnum = lnum - 1 +	elseif lastline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)' +	    let lnum = lnum - 1 +	elseif lastline =~ '\*/\s*$' +	    call cursor(lnum, 1) +	    if lastline !~ '^\*/' +		call search('\*/', 'W') +	    endif +	    let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()') + +	    let lastline = getline(lnum) +	    if lastline =~ '^\s*/\*' +		let lnum = lnum - 1 +	    else +		break +	    endif + + +	elseif lastline =~? '\%(//\s*\|?>.*\)\@<!<?\%(php\)\=\s*$\|^\s*<script\>' + +	    while lastline !~ '\(<?.*\)\@<!?>' && lnum > 1 +		let lnum = lnum - 1 +		let lastline = getline(lnum) +	    endwhile +	    if lastline =~ '^\s*?>' +		let lnum = lnum - 1 +	    else +		break +	    endif + + +	elseif lastline =~? '^\a\w*;\=$' && lastline !~? s:notPhpHereDoc +	    let tofind=substitute( lastline, '\(\a\w*\);\=', '<<<\\s*[''"]\\=\1[''"]\\=$', '') +	    while getline(lnum) !~? tofind && lnum > 1 +		let lnum = lnum - 1 +	    endwhile +	elseif lastline =~ '^[^''"`]*[''"`][;,]'.s:endline + +	    let tofind=substitute( lastline, '^.*\([''"`]\)[;,].*$', '^[^\1]\\+[\1]$\\|^[^\1]\\+[=([]\\s*[\1]', '') +	    let trylnum = lnum +	    while getline(trylnum) !~? tofind && trylnum > 1 +		let trylnum = trylnum - 1 +	    endwhile + +	    if trylnum == 1 +		break +	    else +		if lastline =~ ';'.s:endline +		    while getline(trylnum) !~? s:terminated && getline(trylnum) !~? '{'.s:endline && trylnum > 1 +			let trylnum = prevnonblank(trylnum - 1) +		    endwhile + + +		    if trylnum == 1 +			break +		    end +		end +		let lnum = trylnum +	    end +	else +	    break +	endif +    endwhile + +    if lnum==1 && getline(lnum) !~ '<?' +	let lnum=0 +    endif + +    if b:InPHPcode_and_script && 1 > b:InPHPcode +	let b:InPHPcode_and_script = 0 +    endif + +    return lnum +endfunction " }}} + +function! Skippmatch2() + +    let line = getline(".") + +    if line =~ "\\([\"']\\).*/\\*.*\\1" || line =~ '\%(//\|#\).*/\*' +	return 1 +    else +	return 0 +    endif +endfun + +function! Skippmatch()	" {{{ +    let synname = synIDattr(synID(line("."), col("."), 0), "name") +    if synname == "Delimiter" || synname == "phpRegionDelimiter" || synname =~# "^phpParent" || synname == "phpArrayParens" || synname =~# '^php\%(Block\|Brace\)' || synname == "javaScriptBraces" || synname =~# '^php\%(Doc\)\?Comment' && b:UserIsTypingComment +	return 0 +    else +	return 1 +    endif +endfun " }}} + +function! FindOpenBracket(lnum, blockStarter) " {{{ +    call cursor(a:lnum, 1) +    let line = searchpair('{', '', '}', 'bW', 'Skippmatch()') + +    if a:blockStarter == 1 +	while line > 1 +	    let linec = getline(line) + +	    if linec =~ s:terminated || linec =~ s:structureHead +		break +	    endif + +	    let line = GetLastRealCodeLNum(line - 1) +	endwhile +    endif + +    return line +endfun " }}} + +let s:blockChars = {'{':1, '[': 1, '(': 1, ')':-1, ']':-1, '}':-1} +function! BalanceDirection (str) + +    let balance = 0 + +    for c in split(a:str, '\zs') +	if has_key(s:blockChars, c) +	    let balance += s:blockChars[c] +	endif +    endfor + +    return balance +endfun + +function! FindTheIfOfAnElse (lnum, StopAfterFirstPrevElse) " {{{ + +    if getline(a:lnum) =~# '^\s*}\s*else\%(if\)\=\>' +	let beforeelse = a:lnum +    else +	let beforeelse = GetLastRealCodeLNum(a:lnum - 1) +    endif + +    if !s:level +	let s:iftoskip = 0 +    endif + +    if getline(beforeelse) =~# '^\s*\%(}\s*\)\=else\%(\s*if\)\@!\>' +	let s:iftoskip = s:iftoskip + 1 +    endif + +    if getline(beforeelse) =~ '^\s*}' +	let beforeelse = FindOpenBracket(beforeelse, 0) + +	if getline(beforeelse) =~ '^\s*{' +	    let beforeelse = GetLastRealCodeLNum(beforeelse - 1) +	endif +    endif + + +    if !s:iftoskip && a:StopAfterFirstPrevElse && getline(beforeelse) =~# '^\s*\%([}]\s*\)\=else\%(if\)\=\>' +	return beforeelse +    endif + +    if getline(beforeelse) !~# '^\s*if\>' && beforeelse>1 || s:iftoskip && beforeelse>1 + +	if s:iftoskip && getline(beforeelse) =~# '^\s*if\>' +	    let s:iftoskip = s:iftoskip - 1 +	endif + +	let s:level =  s:level + 1 +	let beforeelse = FindTheIfOfAnElse(beforeelse, a:StopAfterFirstPrevElse) +    endif + +    return beforeelse + +endfunction " }}} + +let s:defaultORcase = '^\s*\%(default\|case\).*:' + +function! FindTheSwitchIndent (lnum) " {{{ + +    let test = GetLastRealCodeLNum(a:lnum - 1) + +    if test <= 1 +	return indent(1) - shiftwidth() * b:PHP_vintage_case_default_indent +    end + +    while getline(test) =~ '^\s*}' && test > 1 +	let test = GetLastRealCodeLNum(FindOpenBracket(test, 0) - 1) + +	if getline(test) =~ '^\s*switch\>' +	    let test = GetLastRealCodeLNum(test - 1) +	endif +    endwhile + +    if getline(test) =~# '^\s*switch\>' +	return indent(test) +    elseif getline(test) =~# s:defaultORcase +	return indent(test) - shiftwidth() * b:PHP_vintage_case_default_indent +    else +	return FindTheSwitchIndent(test) +    endif + +endfunction "}}} + +let s:SynPHPMatchGroups = {'phpParent':1, 'Delimiter':1, 'Define':1, 'Storageclass':1, 'StorageClass':1, 'Structure':1, 'Exception':1} +function! IslinePHP (lnum, tofind) " {{{ +    let cline = getline(a:lnum) + +    if a:tofind=="" +	let tofind = "^\\s*[\"'`]*\\s*\\zs\\S" +    else +	let tofind = a:tofind +    endif + +    let tofind = tofind . '\c' + +    let coltotest = match (cline, tofind) + 1 + +    let synname = synIDattr(synID(a:lnum, coltotest, 0), "name") + +    if synname == 'phpStringSingle' || synname == 'phpStringDouble' || synname == 'phpBacktick' +	if cline !~ '^\s*[''"`]' +	    return "SpecStringEntrails" +	else +	    return synname +	end +    end + +    if get(s:SynPHPMatchGroups, synname) || synname =~ '^php' ||  synname =~? '^javaScript' +	return synname +    else +	return "" +    endif +endfunction " }}} + +let s:autoresetoptions = 0 +if ! s:autoresetoptions +    let s:autoresetoptions = 1 +endif + +function! ResetPhpOptions() +    if ! b:optionsset && &filetype =~ "php" +	if b:PHP_autoformatcomment + +	    setlocal comments=s1:/*,mb:*,ex:*/,://,:# + +	    setlocal formatoptions-=t +	    setlocal formatoptions+=q +	    setlocal formatoptions+=r +	    setlocal formatoptions+=o +	    setlocal formatoptions+=c +	    setlocal formatoptions+=b +	endif +	let b:optionsset = 1 +    endif +endfunc + +call ResetPhpOptions() + +function! GetPhpIndent() + +    let b:GetLastRealCodeLNum_ADD = 0 + +    let UserIsEditing=0 +    if	b:PHP_oldchangetick != b:changedtick +	let b:PHP_oldchangetick = b:changedtick +	let UserIsEditing=1 +    endif + +    if b:PHP_default_indenting +	let b:PHP_default_indenting = g:PHP_default_indenting * shiftwidth() +    endif + +    let cline = getline(v:lnum) + +    if !b:PHP_indentinghuge && b:PHP_lastindented > b:PHP_indentbeforelast +	if b:PHP_indentbeforelast +	    let b:PHP_indentinghuge = 1 +	endif +	let b:PHP_indentbeforelast = b:PHP_lastindented +    endif + +    if b:InPHPcode_checked && prevnonblank(v:lnum - 1) != b:PHP_lastindented +	if b:PHP_indentinghuge +	    let b:PHP_indentinghuge = 0 +	    let b:PHP_CurrentIndentLevel = b:PHP_default_indenting +	endif +	let real_PHP_lastindented = v:lnum +	let b:PHP_LastIndentedWasComment=0 +	let b:PHP_InsideMultilineComment=0 +	let b:PHP_indentbeforelast = 0 + +	let b:InPHPcode = 0 +	let b:InPHPcode_checked = 0 +	let b:InPHPcode_and_script = 0 +	let b:InPHPcode_tofind = "" + +    elseif v:lnum > b:PHP_lastindented +	let real_PHP_lastindented = b:PHP_lastindented +    else +	let real_PHP_lastindented = v:lnum +    endif + +    let b:PHP_lastindented = v:lnum + + +    if !b:InPHPcode_checked " {{{ One time check +	let b:InPHPcode_checked = 1 +	let b:UserIsTypingComment = 0 + +	let synname = "" +	if cline !~ '<?.*?>' +	    let synname = IslinePHP (prevnonblank(v:lnum), "") +	endif + +	if synname!="" +	    if synname == "SpecStringEntrails" +		let b:InPHPcode = -1 " thumb down +		let b:InPHPcode_tofind = "" +	    elseif synname != "phpHereDoc" && synname != "phpHereDocDelimiter" +		let b:InPHPcode = 1 +		let b:InPHPcode_tofind = "" + +		if synname =~# '^php\%(Doc\)\?Comment' +		    let b:UserIsTypingComment = 1 +		    let b:InPHPcode_checked = 0 +		endif + +		if synname =~? '^javaScript' +		    let b:InPHPcode_and_script = 1 +		endif + +	    else +		let b:InPHPcode = 0 + +		let lnum = v:lnum - 1 +		while getline(lnum) !~? '<<<\s*[''"]\=\a\w*[''"]\=$' && lnum > 1 +		    let lnum = lnum - 1 +		endwhile + +		let b:InPHPcode_tofind = substitute( getline(lnum), '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') +	    endif +	else +	    let b:InPHPcode = 0 +	    let b:InPHPcode_tofind = s:PHP_startindenttag +	endif +    endif "!b:InPHPcode_checked }}} + + +    " Test if we are indenting PHP code {{{ +    let lnum = prevnonblank(v:lnum - 1) +    let last_line = getline(lnum) +    let endline= s:endline + +    if b:InPHPcode_tofind!="" +	if cline =~? b:InPHPcode_tofind +	    let b:InPHPcode_tofind = "" +	    let b:UserIsTypingComment = 0 + +	    if b:InPHPcode == -1 +		let b:InPHPcode = 1 +		return -1 +	    end + +	    let b:InPHPcode = 1 + +	    if cline =~ '\*/' +		call cursor(v:lnum, 1) +		if cline !~ '^\*/' +		    call search('\*/', 'W') +		endif +		let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()') + +		let b:PHP_CurrentIndentLevel = b:PHP_default_indenting + +		let b:PHP_LastIndentedWasComment = 0 + +		if cline =~ '^\s*\*/' +		    return indent(lnum) + 1 +		else +		    return indent(lnum) +		endif + +	    elseif cline =~? '<script\>' +		let b:InPHPcode_and_script = 1 +		let b:GetLastRealCodeLNum_ADD = v:lnum +	    endif +	endif +    endif + +    if 1 == b:InPHPcode + +	if !b:InPHPcode_and_script && last_line =~ '\%(<?.*\)\@<!?>\%(.*<?\)\@!' && IslinePHP(lnum, '?>')=~"Delimiter" +	    if cline !~? s:PHP_startindenttag +		let b:InPHPcode = 0 +		let b:InPHPcode_tofind = s:PHP_startindenttag +	    elseif cline =~? '<script\>' +		let b:InPHPcode_and_script = 1 +	    endif + +	elseif last_line =~ '^[^''"`]\+[''"`]$' " a string identifier with nothing after it and no other string identifier before +	    let b:InPHPcode = -1 +	    let b:InPHPcode_tofind = substitute( last_line, '^.*\([''"`]\).*$', '^[^\1]*\1[;,]$', '') +	elseif last_line =~? '<<<\s*[''"]\=\a\w*[''"]\=$' +	    let b:InPHPcode = 0 +	    let b:InPHPcode_tofind = substitute( last_line, '^.*<<<\s*[''"]\=\(\a\w*\)[''"]\=$', '^\\s*\1;\\=$', '') + +	elseif !UserIsEditing && cline =~ '^\s*/\*\%(.*\*/\)\@!' && getline(v:lnum + 1) !~ '^\s*\*' +	    let b:InPHPcode = 0 +	    let b:InPHPcode_tofind = '\*/' + +	elseif cline =~? '^\s*</script>' +	    let b:InPHPcode = 0 +	    let b:InPHPcode_tofind = s:PHP_startindenttag +	endif +    endif " }}} + + +    if 1 > b:InPHPcode && !b:InPHPcode_and_script +	return -1 +    endif + +    " Indent successive // or # comment the same way the first is {{{ +    let addSpecial = 0 +    if cline =~ '^\s*\%(//\|#\|/\*.*\*/\s*$\)' +	let addSpecial = b:PHP_outdentSLComments +	if b:PHP_LastIndentedWasComment == 1 +	    return indent(real_PHP_lastindented) +	endif +	let b:PHP_LastIndentedWasComment = 1 +    else +	let b:PHP_LastIndentedWasComment = 0 +    endif " }}} + +    " Indent multiline /* comments correctly {{{ + +    if b:PHP_InsideMultilineComment || b:UserIsTypingComment +	if cline =~ '^\s*\*\%(\/\)\@!' +	    if last_line =~ '^\s*/\*' +		return indent(lnum) + 1 +	    else +		return indent(lnum) +	    endif +	else +	    let b:PHP_InsideMultilineComment = 0 +	endif +    endif + +    if !b:PHP_InsideMultilineComment && cline =~ '^\s*/\*\%(.*\*/\)\@!' +	if getline(v:lnum + 1) !~ '^\s*\*' +	    return -1 +	endif +	let b:PHP_InsideMultilineComment = 1 +    endif " }}} + + +    " Things always indented at col 1 (PHP delimiter: <?, ?>, Heredoc end) {{{ +    if cline =~# '^\s*<?' && cline !~ '?>' && b:PHP_outdentphpescape +	return 0 +    endif + +    if	cline =~ '^\s*?>' && cline !~# '<?' && b:PHP_outdentphpescape +	return 0 +    endif + +    if cline =~? '^\s*\a\w*;$\|^\a\w*$\|^\s*[''"`][;,]' && cline !~? s:notPhpHereDoc +	return 0 +    endif " }}} + +    let s:level = 0 + +    let lnum = GetLastRealCodeLNum(v:lnum - 1) + +    let last_line = getline(lnum) +    let ind = indent(lnum) + +    if ind==0 && b:PHP_default_indenting +	let ind = b:PHP_default_indenting +    endif + +    if lnum == 0 +	return b:PHP_default_indenting + addSpecial +    endif + + +    if cline =~ '^\s*}\%(}}\)\@!' +	let ind = indent(FindOpenBracket(v:lnum, 1)) +	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting +	return ind +    endif + +    if cline =~ '^\s*\*/' +	call cursor(v:lnum, 1) +	if cline !~ '^\*/' +	    call search('\*/', 'W') +	endif +	let lnum = searchpair('/\*', '', '\*/', s:searchpairflags, 'Skippmatch2()') + +	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting + +	if cline =~ '^\s*\*/' +	    return indent(lnum) + 1 +	else +	    return indent(lnum) +	endif +    endif + + +    if last_line =~ '[;}]'.endline && last_line !~ '^[)\]]' && last_line !~# s:defaultORcase +	if ind==b:PHP_default_indenting +	    return b:PHP_default_indenting + addSpecial +	elseif b:PHP_indentinghuge && ind==b:PHP_CurrentIndentLevel && cline !~# '^\s*\%(else\|\%(case\|default\).*:\|[})];\=\)' && last_line !~# '^\s*\%(\%(}\s*\)\=else\)' && getline(GetLastRealCodeLNum(lnum - 1))=~';'.endline +	    return b:PHP_CurrentIndentLevel + addSpecial +	endif +    endif + +    let LastLineClosed = 0 + +    let terminated = s:terminated + +    let unstated  = s:unstated + + +    if ind != b:PHP_default_indenting && cline =~# '^\s*else\%(if\)\=\>' +	let b:PHP_CurrentIndentLevel = b:PHP_default_indenting +	return indent(FindTheIfOfAnElse(v:lnum, 1)) +    elseif cline =~# s:defaultORcase +	return FindTheSwitchIndent(v:lnum) + shiftwidth() * b:PHP_vintage_case_default_indent +    elseif cline =~ '^\s*)\=\s*{' +	let previous_line = last_line +	let last_line_num = lnum + +	while last_line_num > 1 + +	    if previous_line =~ terminated || previous_line =~ s:structureHead + +		let ind = indent(last_line_num) + +		if  b:PHP_BracesAtCodeLevel +		    let ind = ind + shiftwidth() +		endif + +		return ind +	    endif + +	    let last_line_num = GetLastRealCodeLNum(last_line_num - 1) +	    let previous_line = getline(last_line_num) +	endwhile + +    elseif last_line =~# unstated && cline !~ '^\s*);\='.endline +	let ind = ind + shiftwidth() " we indent one level further when the preceding line is not stated +	return ind + addSpecial + +    elseif (ind != b:PHP_default_indenting || last_line =~ '^[)\]]' ) && last_line =~ terminated +	let previous_line = last_line +	let last_line_num = lnum +	let LastLineClosed = 1 + +	let isSingleLineBlock = 0 +	while 1 +	    if ! isSingleLineBlock && previous_line =~ '^\s*}\|;\s*}'.endline " XXX + +		call cursor(last_line_num, 1) +		if previous_line !~ '^}' +		    call search('}\|;\s*}'.endline, 'W') +		end +		let oldLastLine = last_line_num +		let last_line_num = searchpair('{', '', '}', 'bW', 'Skippmatch()') + +		if getline(last_line_num) =~ '^\s*{' +		    let last_line_num = GetLastRealCodeLNum(last_line_num - 1) +		elseif oldLastLine == last_line_num +		    let isSingleLineBlock = 1 +		    continue +		endif + +		let previous_line = getline(last_line_num) + +		continue +	    else +		let isSingleLineBlock = 0 + +		if getline(last_line_num) =~# '^\s*else\%(if\)\=\>' +		    let last_line_num = FindTheIfOfAnElse(last_line_num, 0) +		    continue +		endif + + +		let last_match = last_line_num + +		let one_ahead_indent = indent(last_line_num) +		let last_line_num = GetLastRealCodeLNum(last_line_num - 1) +		let two_ahead_indent = indent(last_line_num) +		let after_previous_line = previous_line +		let previous_line = getline(last_line_num) + + +		if previous_line =~# s:defaultORcase.'\|{'.endline +		    break +		endif + +		if after_previous_line=~# '^\s*'.s:blockstart.'.*)'.endline && previous_line =~# '[;}]'.endline +		    break +		endif + +		if one_ahead_indent == two_ahead_indent || last_line_num < 1 +		    if previous_line =~# '\%(;\|^\s*}\)'.endline || last_line_num < 1 +			break +		    endif +		endif +	    endif +	endwhile + +	if indent(last_match) != ind +	    let ind = indent(last_match) +	    let b:PHP_CurrentIndentLevel = b:PHP_default_indenting + +	    return ind + addSpecial +	endif +    endif + +    if (last_line !~ '^\s*}\%(}}\)\@!') +	let plinnum = GetLastRealCodeLNum(lnum - 1) +    else +	let plinnum = GetLastRealCodeLNum(FindOpenBracket(lnum, 1) - 1) +    endif + +    let AntepenultimateLine = getline(plinnum) + +    let last_line = substitute(last_line,"\\(//\\|#\\)\\(\\(\\([^\"']*\\([\"']\\)[^\"']*\\5\\)\\+[^\"']*$\\)\\|\\([^\"']*$\\)\\)",'','') + + +    if ind == b:PHP_default_indenting +	if last_line =~ terminated && last_line !~# s:defaultORcase +	    let LastLineClosed = 1 +	endif +    endif + +    if !LastLineClosed + + +	if last_line =~# '[{(\[]'.endline || last_line =~? '\h\w*\s*(.*,$' && AntepenultimateLine !~ '[,(\[]'.endline && BalanceDirection(last_line) > 0 + +	    let dontIndent = 0 +	    if last_line =~ '\S\+\s*{'.endline && last_line !~ '^\s*[)\]]\+\s*{'.endline && last_line !~ s:structureHead +		let dontIndent = 1 +	    endif + +	    if !dontIndent && (!b:PHP_BracesAtCodeLevel || last_line !~# '^\s*{') +		let ind = ind + shiftwidth() +	    endif + +	    if b:PHP_BracesAtCodeLevel || b:PHP_vintage_case_default_indent == 1 +		let b:PHP_CurrentIndentLevel = ind + +		return ind + addSpecial +	    endif + +	elseif last_line =~ '\S\+\s*),'.endline && BalanceDirection(last_line) < 0 +	    call cursor(lnum, 1) +	    call search('),'.endline, 'W') " line never begins with ) so no need for 'c' flag +	    let openedparent = searchpair('(', '', ')', 'bW', 'Skippmatch()') +	    if openedparent != lnum +		let ind = indent(openedparent) +	    endif + +	elseif last_line =~ '^\s*'.s:blockstart +	    let ind = ind + shiftwidth() + + +	elseif AntepenultimateLine =~ '{'.endline && AntepenultimateLine !~? '^\s*use\>' || AntepenultimateLine =~ terminated || AntepenultimateLine =~# s:defaultORcase +	    let ind = ind + shiftwidth() +	endif + +    endif + +    if cline =~  '^\s*[)\]];\=' +	let ind = ind - shiftwidth() +    endif + +    let b:PHP_CurrentIndentLevel = ind +    return ind + addSpecial +endfunction + +endif diff --git a/indent/postscr.vim b/indent/postscr.vim new file mode 100644 index 00000000..53956b24 --- /dev/null +++ b/indent/postscr.vim @@ -0,0 +1,72 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" PostScript indent file +" Language:    PostScript +" Maintainer:  Mike Williams <mrw@netcomuk.co.uk> +" Last Change: 2nd July 2001 +" + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=PostscrIndentGet(v:lnum) +setlocal indentkeys+=0],0=>>,0=%%,0=end,0=restore,0=grestore indentkeys-=:,0#,e + +" Catch multiple instantiations +if exists("*PostscrIndentGet") +  finish +endif + +function! PostscrIndentGet(lnum) +  " Find a non-empty non-comment line above the current line. +  " Note: ignores DSC comments as well! +  let lnum = a:lnum - 1 +  while lnum != 0 +    let lnum = prevnonblank(lnum) +    if getline(lnum) !~ '^\s*%.*$' +      break +    endif +    let lnum = lnum - 1 +  endwhile + +  " Hit the start of the file, use user indent. +  if lnum == 0 +    return -1 +  endif + +  " Start with the indent of the previous line +  let ind = indent(lnum) +  let pline = getline(lnum) + +  " Indent for dicts, arrays, and saves with possible trailing comment +  if pline =~ '\(begin\|<<\|g\=save\|{\|[\)\s*\(%.*\)\=$' +    let ind = ind + shiftwidth() +  endif + +  " Remove indent for popped dicts, and restores. +  if pline =~ '\(end\|g\=restore\)\s*$' +    let ind = ind - shiftwidth() + +  " Else handle immediate dedents of dicts, restores, and arrays. +  elseif getline(a:lnum) =~ '\(end\|>>\|g\=restore\|}\|]\)' +    let ind = ind - shiftwidth() + +  " Else handle DSC comments - always start of line. +  elseif getline(a:lnum) =~ '^\s*%%' +    let ind = 0 +  endif + +  " For now catch excessive left indents if they occur. +  if ind < 0 +    let ind = -1 +  endif + +  return ind +endfunction + +" vim:sw=2 + +endif diff --git a/indent/pov.vim b/indent/pov.vim new file mode 100644 index 00000000..90f2cafb --- /dev/null +++ b/indent/pov.vim @@ -0,0 +1,88 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language: PoV-Ray Scene Description Language +" Maintainer: David Necas (Yeti) <yeti@physics.muni.cz> +" Last Change: 2017 Jun 13 +" URI: http://trific.ath.cx/Ftp/vim/indent/pov.vim + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" Some preliminary settings. +setlocal nolisp " Make sure lisp indenting doesn't supersede us. + +setlocal indentexpr=GetPoVRayIndent() +setlocal indentkeys+==else,=end,0] + +" Only define the function once. +if exists("*GetPoVRayIndent") +  finish +endif + +" Counts matches of a regexp <rexp> in line number <line>. +" Doesn't count matches inside strings and comments (as defined by current +" syntax). +function! s:MatchCount(line, rexp) +  let str = getline(a:line) +  let i = 0 +  let n = 0 +  while i >= 0 +    let i = matchend(str, a:rexp, i) +    if i >= 0 && synIDattr(synID(a:line, i, 0), "name") !~? "string\|comment" +      let n = n + 1 +    endif +  endwhile +  return n +endfunction + +" The main function.  Returns indent amount. +function GetPoVRayIndent() +  " If we are inside a comment (may be nested in obscure ways), give up +  if synIDattr(synID(v:lnum, indent(v:lnum)+1, 0), "name") =~? "string\|comment" +    return -1 +  endif + +  " Search backwards for the frist non-empty, non-comment line. +  let plnum = prevnonblank(v:lnum - 1) +  let plind = indent(plnum) +  while plnum > 0 && synIDattr(synID(plnum, plind+1, 0), "name") =~? "comment" +    let plnum = prevnonblank(plnum - 1) +    let plind = indent(plnum) +  endwhile + +  " Start indenting from zero +  if plnum == 0 +    return 0 +  endif + +  " Analyse previous nonempty line. +  let chg = 0 +  let chg = chg + s:MatchCount(plnum, '[[{(]') +  let chg = chg + s:MatchCount(plnum, '#\s*\%(if\|ifdef\|ifndef\|switch\|while\|macro\|else\)\>') +  let chg = chg - s:MatchCount(plnum, '#\s*end\>') +  let chg = chg - s:MatchCount(plnum, '[]})]') +  " Dirty hack for people writing #if and #else on the same line. +  let chg = chg - s:MatchCount(plnum, '#\s*\%(if\|ifdef\|ifndef\|switch\)\>.*#\s*else\>') +  " When chg > 0, then we opened groups and we should indent more, but when +  " chg < 0, we closed groups and this already affected the previous line, +  " so we should not dedent.  And when everything else fails, scream. +  let chg = chg > 0 ? chg : 0 + +  " Analyse current line +  " FIXME: If we have to dedent, we should try to find the indentation of the +  " opening line. +  let cur = s:MatchCount(v:lnum, '^\s*\%(#\s*\%(end\|else\)\>\|[]})]\)') +  if cur > 0 +    let final = plind + (chg - cur) * shiftwidth() +  else +    let final = plind + chg * shiftwidth() +  endif + +  return final < 0 ? 0 : final +endfunction + +endif diff --git a/indent/prolog.vim b/indent/prolog.vim new file mode 100644 index 00000000..8f66554e --- /dev/null +++ b/indent/prolog.vim @@ -0,0 +1,62 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"  vim: set sw=4 sts=4: +"  Maintainer	: Gergely Kontra <kgergely@mcl.hu> +"  Revised on	: 2002.02.18. 23:34:05 +"  Language	: Prolog + +" TODO: +"   checking with respect to syntax highlighting +"   ignoring multiline comments +"   detecting multiline strings + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif + +let b:did_indent = 1 + +setlocal indentexpr=GetPrologIndent() +setlocal indentkeys-=:,0# +setlocal indentkeys+=0%,-,0;,>,0) + +" Only define the function once. +"if exists("*GetPrologIndent") +"    finish +"endif + +function! GetPrologIndent() +    " Find a non-blank line above the current line. +    let pnum = prevnonblank(v:lnum - 1) +    " Hit the start of the file, use zero indent. +    if pnum == 0 +       return 0 +    endif +    let line = getline(v:lnum) +    let pline = getline(pnum) + +    let ind = indent(pnum) +    " Previous line was comment -> use previous line's indent +    if pline =~ '^\s*%' +	retu ind +    endif +    " Check for clause head on previous line +    if pline =~ ':-\s*\(%.*\)\?$' +	let ind = ind + shiftwidth() +    " Check for end of clause on previous line +    elseif pline =~ '\.\s*\(%.*\)\?$' +	let ind = ind - shiftwidth() +    endif +    " Check for opening conditional on previous line +    if pline =~ '^\s*\([(;]\|->\)' +	let ind = ind + shiftwidth() +    endif +    " Check for closing an unclosed paren, or middle ; or -> +    if line =~ '^\s*\([);]\|->\)' +	let ind = ind - shiftwidth() +    endif +    return ind +endfunction + +endif diff --git a/indent/pyrex.vim b/indent/pyrex.vim new file mode 100644 index 00000000..bf1f703c --- /dev/null +++ b/indent/pyrex.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Pyrex +" Maintainer:	Marco Barisione <marco.bari@people.it> +" URL:		http://marcobari.altervista.org/pyrex_vim.html +" Last Change:	2005 Jun 24 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Use Python formatting rules +runtime! indent/python.vim + +endif diff --git a/indent/python.vim b/indent/python.vim index 48b34469..87a447ed 100644 --- a/indent/python.vim +++ b/indent/python.vim @@ -1,3 +1,205 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:		Python +" Maintainer:		Bram Moolenaar <Bram@vim.org> +" Original Author:	David Bustos <bustos@caltech.edu> +" Last Change:		2013 Jul 9 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" Some preliminary settings +setlocal nolisp		" Make sure lisp indenting doesn't supersede us +setlocal autoindent	" indentexpr isn't much help otherwise + +setlocal indentexpr=GetPythonIndent(v:lnum) +setlocal indentkeys+=<:>,=elif,=except + +" Only define the function once. +if exists("*GetPythonIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +" Come here when loading the script the first time. + +let s:maxoff = 50	" maximum number of lines to look backwards for () + +function GetPythonIndent(lnum) + +  " If this line is explicitly joined: If the previous line was also joined, +  " line it up with that one, otherwise add two 'shiftwidth' +  if getline(a:lnum - 1) =~ '\\$' +    if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$' +      return indent(a:lnum - 1) +    endif +    return indent(a:lnum - 1) + (exists("g:pyindent_continue") ? eval(g:pyindent_continue) : (shiftwidth() * 2)) +  endif + +  " If the start of the line is in a string don't change the indent. +  if has('syntax_items') +	\ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$" +    return -1 +  endif + +  " Search backwards for the previous non-empty line. +  let plnum = prevnonblank(v:lnum - 1) + +  if plnum == 0 +    " This is the first non-empty line, use zero indent. +    return 0 +  endif + +  " If the previous line is inside parenthesis, use the indent of the starting +  " line. +  " Trick: use the non-existing "dummy" variable to break out of the loop when +  " going too far back. +  call cursor(plnum, 1) +  let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW', +	  \ "line('.') < " . (plnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") +  if parlnum > 0 +    let plindent = indent(parlnum) +    let plnumstart = parlnum +  else +    let plindent = indent(plnum) +    let plnumstart = plnum +  endif + + +  " When inside parenthesis: If at the first line below the parenthesis add +  " two 'shiftwidth', otherwise same as previous line. +  " i = (a +  "       + b +  "       + c) +  call cursor(a:lnum, 1) +  let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', +	  \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") +  if p > 0 +    if p == plnum +      " When the start is inside parenthesis, only indent one 'shiftwidth'. +      let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', +	  \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") +      if pp > 0 +	return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth()) +      endif +      return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2)) +    endif +    if plnumstart == p +      return indent(plnum) +    endif +    return plindent +  endif + + +  " Get the line and remove a trailing comment. +  " Use syntax highlighting attributes when possible. +  let pline = getline(plnum) +  let pline_len = strlen(pline) +  if has('syntax_items') +    " If the last character in the line is a comment, do a binary search for +    " the start of the comment.  synID() is slow, a linear search would take +    " too long on a long line. +    if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$" +      let min = 1 +      let max = pline_len +      while min < max +	let col = (min + max) / 2 +	if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$" +	  let max = col +	else +	  let min = col + 1 +	endif +      endwhile +      let pline = strpart(pline, 0, min - 1) +    endif +  else +    let col = 0 +    while col < pline_len +      if pline[col] == '#' +	let pline = strpart(pline, 0, col) +	break +      endif +      let col = col + 1 +    endwhile +  endif + +  " If the previous line ended with a colon, indent this line +  if pline =~ ':\s*$' +    return plindent + shiftwidth() +  endif + +  " If the previous line was a stop-execution statement... +  if getline(plnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\)\>' +    " See if the user has already dedented +    if indent(a:lnum) > indent(plnum) - shiftwidth() +      " If not, recommend one dedent +      return indent(plnum) - shiftwidth() +    endif +    " Otherwise, trust the user +    return -1 +  endif + +  " If the current line begins with a keyword that lines up with "try" +  if getline(a:lnum) =~ '^\s*\(except\|finally\)\>' +    let lnum = a:lnum - 1 +    while lnum >= 1 +      if getline(lnum) =~ '^\s*\(try\|except\)\>' +	let ind = indent(lnum) +	if ind >= indent(a:lnum) +	  return -1	" indent is already less than this +	endif +	return ind	" line up with previous try or except +      endif +      let lnum = lnum - 1 +    endwhile +    return -1		" no matching "try"! +  endif + +  " If the current line begins with a header keyword, dedent +  if getline(a:lnum) =~ '^\s*\(elif\|else\)\>' + +    " Unless the previous line was a one-liner +    if getline(plnumstart) =~ '^\s*\(for\|if\|try\)\>' +      return plindent +    endif + +    " Or the user has already dedented +    if indent(a:lnum) <= plindent - shiftwidth() +      return -1 +    endif + +    return plindent - shiftwidth() +  endif + +  " When after a () construct we probably want to go back to the start line. +  " a = (b +  "       + c) +  " here +  if parlnum > 0 +    return plindent +  endif + +  return -1 + +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'python') == -1  " PEP8 compatible Python indent file diff --git a/indent/r.vim b/indent/r.vim new file mode 100644 index 00000000..e23f8a24 --- /dev/null +++ b/indent/r.vim @@ -0,0 +1,525 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	R +" Author:	Jakson Alves de Aquino <jalvesaq@gmail.com> +" Homepage:     https://github.com/jalvesaq/R-Vim-runtime +" Last Change:	Thu Feb 18, 2016  06:32AM + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentkeys=0{,0},:,!^F,o,O,e +setlocal indentexpr=GetRIndent() + +" Only define the function once. +if exists("*GetRIndent") +  finish +endif + +" Options to make the indentation more similar to Emacs/ESS: +if !exists("g:r_indent_align_args") +  let g:r_indent_align_args = 1 +endif +if !exists("g:r_indent_ess_comments") +  let g:r_indent_ess_comments = 0 +endif +if !exists("g:r_indent_comment_column") +  let g:r_indent_comment_column = 40 +endif +if ! exists("g:r_indent_ess_compatible") +  let g:r_indent_ess_compatible = 0 +endif +if ! exists("g:r_indent_op_pattern") +  let g:r_indent_op_pattern = '\(&\||\|+\|-\|\*\|/\|=\|\~\|%\|->\)\s*$' +endif + +function s:RDelete_quotes(line) +  let i = 0 +  let j = 0 +  let line1 = "" +  let llen = strlen(a:line) +  while i < llen +    if a:line[i] == '"' +      let i += 1 +      let line1 = line1 . 's' +      while !(a:line[i] == '"' && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen +        let i += 1 +      endwhile +      if a:line[i] == '"' +        let i += 1 +      endif +    else +      if a:line[i] == "'" +        let i += 1 +        let line1 = line1 . 's' +        while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen +          let i += 1 +        endwhile +        if a:line[i] == "'" +          let i += 1 +        endif +      else +        if a:line[i] == "`" +          let i += 1 +          let line1 = line1 . 's' +          while a:line[i] != "`" && i < llen +            let i += 1 +          endwhile +          if a:line[i] == "`" +            let i += 1 +          endif +        endif +      endif +    endif +    if i == llen +      break +    endif +    let line1 = line1 . a:line[i] +    let j += 1 +    let i += 1 +  endwhile +  return line1 +endfunction + +" Convert foo(bar()) int foo() +function s:RDelete_parens(line) +  if s:Get_paren_balance(a:line, "(", ")") != 0 +    return a:line +  endif +  let i = 0 +  let j = 0 +  let line1 = "" +  let llen = strlen(a:line) +  while i < llen +    let line1 = line1 . a:line[i] +    if a:line[i] == '(' +      let nop = 1 +      while nop > 0 && i < llen +        let i += 1 +        if a:line[i] == ')' +          let nop -= 1 +        else +          if a:line[i] == '(' +            let nop += 1 +          endif +        endif +      endwhile +      let line1 = line1 . a:line[i] +    endif +    let i += 1 +  endwhile +  return line1 +endfunction + +function! s:Get_paren_balance(line, o, c) +  let line2 = substitute(a:line, a:o, "", "g") +  let openp = strlen(a:line) - strlen(line2) +  let line3 = substitute(line2, a:c, "", "g") +  let closep = strlen(line2) - strlen(line3) +  return openp - closep +endfunction + +function! s:Get_matching_brace(linenr, o, c, delbrace) +  let line = SanitizeRLine(getline(a:linenr)) +  if a:delbrace == 1 +    let line = substitute(line, '{$', "", "") +  endif +  let pb = s:Get_paren_balance(line, a:o, a:c) +  let i = a:linenr +  while pb != 0 && i > 1 +    let i -= 1 +    let pb += s:Get_paren_balance(SanitizeRLine(getline(i)), a:o, a:c) +  endwhile +  return i +endfunction + +" This function is buggy because there 'if's without 'else' +" It must be rewritten relying more on indentation +function! s:Get_matching_if(linenr, delif) +  let line = SanitizeRLine(getline(a:linenr)) +  if a:delif +    let line = substitute(line, "if", "", "g") +  endif +  let elsenr = 0 +  let i = a:linenr +  let ifhere = 0 +  while i > 0 +    let line2 = substitute(line, '\<else\>', "xxx", "g") +    let elsenr += strlen(line) - strlen(line2) +    if line =~ '.*\s*if\s*()' || line =~ '.*\s*if\s*()' +      let elsenr -= 1 +      if elsenr == 0 +        let ifhere = i +        break +      endif +    endif +    let i -= 1 +    let line = SanitizeRLine(getline(i)) +  endwhile +  if ifhere +    return ifhere +  else +    return a:linenr +  endif +endfunction + +function! s:Get_last_paren_idx(line, o, c, pb) +  let blc = a:pb +  let line = substitute(a:line, '\t', s:curtabstop, "g") +  let theidx = -1 +  let llen = strlen(line) +  let idx = 0 +  while idx < llen +    if line[idx] == a:o +      let blc -= 1 +      if blc == 0 +        let theidx = idx +      endif +    else +      if line[idx] == a:c +        let blc += 1 +      endif +    endif +    let idx += 1 +  endwhile +  return theidx + 1 +endfunction + +" Get previous relevant line. Search back until getting a line that isn't +" comment or blank +function s:Get_prev_line(lineno) +  let lnum = a:lineno - 1 +  let data = getline( lnum ) +  while lnum > 0 && (data =~ '^\s*#' || data =~ '^\s*$') +    let lnum = lnum - 1 +    let data = getline( lnum ) +  endwhile +  return lnum +endfunction + +" This function is also used by r-plugin/common_global.vim +" Delete from '#' to the end of the line, unless the '#' is inside a string. +function SanitizeRLine(line) +  let newline = s:RDelete_quotes(a:line) +  let newline = s:RDelete_parens(newline) +  let newline = substitute(newline, '#.*', "", "") +  let newline = substitute(newline, '\s*$', "", "") +  if &filetype == "rhelp" && newline =~ '^\\method{.*}{.*}(.*' +    let newline = substitute(newline, '^\\method{\(.*\)}{.*}', '\1', "") +  endif +  return newline +endfunction + +function GetRIndent() + +  let clnum = line(".")    " current line + +  let cline = getline(clnum) +  if cline =~ '^\s*#' +    if g:r_indent_ess_comments == 1 +      if cline =~ '^\s*###' +        return 0 +      endif +      if cline !~ '^\s*##' +        return g:r_indent_comment_column +      endif +    endif +  endif + +  let cline = SanitizeRLine(cline) + +  if cline =~ '^\s*}' || cline =~ '^\s*}\s*)$' +    let indline = s:Get_matching_brace(clnum, '{', '}', 1) +    if indline > 0 && indline != clnum +      let iline = SanitizeRLine(getline(indline)) +      if s:Get_paren_balance(iline, "(", ")") == 0 || iline =~ '(\s*{$' +        return indent(indline) +      else +        let indline = s:Get_matching_brace(indline, '(', ')', 1) +        return indent(indline) +      endif +    endif +  endif + +  " Find the first non blank line above the current line +  let lnum = s:Get_prev_line(clnum) +  " Hit the start of the file, use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let line = SanitizeRLine(getline(lnum)) + +  if &filetype == "rhelp" +    if cline =~ '^\\dontshow{' || cline =~ '^\\dontrun{' || cline =~ '^\\donttest{' || cline =~ '^\\testonly{' +      return 0 +    endif +    if line =~ '^\\examples{' || line =~ '^\\usage{' || line =~ '^\\dontshow{' || line =~ '^\\dontrun{' || line =~ '^\\donttest{' || line =~ '^\\testonly{' +      return 0 +    endif +  endif + +  if &filetype == "rnoweb" && line =~ "^<<.*>>=" +    return 0 +  endif + +  if cline =~ '^\s*{' && s:Get_paren_balance(cline, '{', '}') > 0 +    if g:r_indent_ess_compatible && line =~ ')$' +      let nlnum = lnum +      let nline = line +      while s:Get_paren_balance(nline, '(', ')') < 0 +        let nlnum = s:Get_prev_line(nlnum) +        let nline = SanitizeRLine(getline(nlnum)) . nline +      endwhile +      if nline =~ '^\s*function\s*(' && indent(nlnum) == shiftwidth() +        return 0 +      endif +    endif +    if s:Get_paren_balance(line, "(", ")") == 0 +      return indent(lnum) +    endif +  endif + +  " line is an incomplete command: +  if line =~ '\<\(if\|while\|for\|function\)\s*()$' || line =~ '\<else$' || line =~ '<-$' || line =~ '->$' +    return indent(lnum) + shiftwidth() +  endif + +  " Deal with () and [] + +  let pb = s:Get_paren_balance(line, '(', ')') + +  if line =~ '^\s*{$' || line =~ '(\s*{' || (pb == 0 && (line =~ '{$' || line =~ '(\s*{$')) +    return indent(lnum) + shiftwidth() +  endif + +  let s:curtabstop = repeat(' ', &tabstop) + +  if g:r_indent_align_args == 1 +    if pb > 0 && line =~ '{$' +      return s:Get_last_paren_idx(line, '(', ')', pb) + shiftwidth() +    endif + +    let bb = s:Get_paren_balance(line, '[', ']') + +    if pb > 0 +      if &filetype == "rhelp" +        let ind = s:Get_last_paren_idx(line, '(', ')', pb) +      else +        let ind = s:Get_last_paren_idx(getline(lnum), '(', ')', pb) +      endif +      return ind +    endif + +    if pb < 0 && line =~ '.*[,&|\-\*+<>]$' +      let lnum = s:Get_prev_line(lnum) +      while pb < 1 && lnum > 0 +        let line = SanitizeRLine(getline(lnum)) +        let line = substitute(line, '\t', s:curtabstop, "g") +        let ind = strlen(line) +        while ind > 0 +          if line[ind] == ')' +            let pb -= 1 +          else +            if line[ind] == '(' +              let pb += 1 +            endif +          endif +          if pb == 1 +            return ind + 1 +          endif +          let ind -= 1 +        endwhile +        let lnum -= 1 +      endwhile +      return 0 +    endif + +    if bb > 0 +      let ind = s:Get_last_paren_idx(getline(lnum), '[', ']', bb) +      return ind +    endif +  endif + +  let post_block = 0 +  if line =~ '}$' && s:Get_paren_balance(line, '{', '}') < 0 +    let lnum = s:Get_matching_brace(lnum, '{', '}', 0) +    let line = SanitizeRLine(getline(lnum)) +    if lnum > 0 && line =~ '^\s*{' +      let lnum = s:Get_prev_line(lnum) +      let line = SanitizeRLine(getline(lnum)) +    endif +    let pb = s:Get_paren_balance(line, '(', ')') +    let post_block = 1 +  endif + +  " Indent after operator pattern +  let olnum = s:Get_prev_line(lnum) +  let oline = getline(olnum) +  if olnum > 0 +    if line =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 +      if oline =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 +        return indent(lnum) +      else +        return indent(lnum) + shiftwidth() +      endif +    else +      if oline =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 +        return indent(lnum) - shiftwidth() +      endif +    endif +  endif + +  let post_fun = 0 +  if pb < 0 && line !~ ')\s*[,&|\-\*+<>]$' +    let post_fun = 1 +    while pb < 0 && lnum > 0 +      let lnum -= 1 +      let linepiece = SanitizeRLine(getline(lnum)) +      let pb += s:Get_paren_balance(linepiece, "(", ")") +      let line = linepiece . line +    endwhile +    if line =~ '{$' && post_block == 0 +      return indent(lnum) + shiftwidth() +    endif + +    " Now we can do some tests again +    if cline =~ '^\s*{' +      return indent(lnum) +    endif +    if post_block == 0 +      let newl = SanitizeRLine(line) +      if newl =~ '\<\(if\|while\|for\|function\)\s*()$' || newl =~ '\<else$' || newl =~ '<-$' +        return indent(lnum) + shiftwidth() +      endif +    endif +  endif + +  if cline =~ '^\s*else' +    if line =~ '<-\s*if\s*()' +      return indent(lnum) + shiftwidth() +    else +      if line =~ '\<if\s*()' +        return indent(lnum) +      else +        return indent(lnum) - shiftwidth() +      endif +    endif +  endif + +  let bb = s:Get_paren_balance(line, '[', ']') +  if bb < 0 && line =~ '.*]' +    while bb < 0 && lnum > 0 +      let lnum -= 1 +      let linepiece = SanitizeRLine(getline(lnum)) +      let bb += s:Get_paren_balance(linepiece, "[", "]") +      let line = linepiece . line +    endwhile +    let line = s:RDelete_parens(line) +  endif + +  let plnum = s:Get_prev_line(lnum) +  let ppost_else = 0 +  if plnum > 0 +    let pline = SanitizeRLine(getline(plnum)) +    let ppost_block = 0 +    if pline =~ '}$' +      let ppost_block = 1 +      let plnum = s:Get_matching_brace(plnum, '{', '}', 0) +      let pline = SanitizeRLine(getline(plnum)) +      if pline =~ '^\s*{$' && plnum > 0 +        let plnum = s:Get_prev_line(plnum) +        let pline = SanitizeRLine(getline(plnum)) +      endif +    endif + +    if pline =~ 'else$' +      let ppost_else = 1 +      let plnum = s:Get_matching_if(plnum, 0) +      let pline = SanitizeRLine(getline(plnum)) +    endif + +    if pline =~ '^\s*else\s*if\s*(' +      let pplnum = s:Get_prev_line(plnum) +      let ppline = SanitizeRLine(getline(pplnum)) +      while ppline =~ '^\s*else\s*if\s*(' || ppline =~ '^\s*if\s*()\s*\S$' +        let plnum = pplnum +        let pline = ppline +        let pplnum = s:Get_prev_line(plnum) +        let ppline = SanitizeRLine(getline(pplnum)) +      endwhile +      while ppline =~ '\<\(if\|while\|for\|function\)\s*()$' || ppline =~ '\<else$' || ppline =~ '<-$' +        let plnum = pplnum +        let pline = ppline +        let pplnum = s:Get_prev_line(plnum) +        let ppline = SanitizeRLine(getline(pplnum)) +      endwhile +    endif + +    let ppb = s:Get_paren_balance(pline, '(', ')') +    if ppb < 0 && (pline =~ ')\s*{$' || pline =~ ')$') +      while ppb < 0 && plnum > 0 +        let plnum -= 1 +        let linepiece = SanitizeRLine(getline(plnum)) +        let ppb += s:Get_paren_balance(linepiece, "(", ")") +        let pline = linepiece . pline +      endwhile +      let pline = s:RDelete_parens(pline) +    endif +  endif + +  let ind = indent(lnum) + +  if g:r_indent_align_args == 0 && pb != 0 +    let ind += pb * shiftwidth() +    return ind +  endif + +  if g:r_indent_align_args == 0 && bb != 0 +    let ind += bb * shiftwidth() +    return ind +  endif + +  if plnum > 0 +    let pind = indent(plnum) +  else +    let pind = 0 +  endif + +  if ind == pind || (ind == (pind  + shiftwidth()) && pline =~ '{$' && ppost_else == 0) +    return ind +  endif + +  let pline = getline(plnum) +  let pbb = s:Get_paren_balance(pline, '[', ']') + +  while pind < ind && plnum > 0 && ppb == 0 && pbb == 0 +    let ind = pind +    let plnum = s:Get_prev_line(plnum) +    let pline = getline(plnum) +    let ppb = s:Get_paren_balance(pline, '(', ')') +    let pbb = s:Get_paren_balance(pline, '[', ']') +    while pline =~ '^\s*else' +      let plnum = s:Get_matching_if(plnum, 1) +      let pline = getline(plnum) +      let ppb = s:Get_paren_balance(pline, '(', ')') +      let pbb = s:Get_paren_balance(pline, '[', ']') +    endwhile +    let pind = indent(plnum) +    if ind == (pind  + shiftwidth()) && pline =~ '{$' +      return ind +    endif +  endwhile + +  return ind + +endfunction + +" vim: sw=2 + +endif diff --git a/indent/readline.vim b/indent/readline.vim new file mode 100644 index 00000000..eca4d736 --- /dev/null +++ b/indent/readline.vim @@ -0,0 +1,40 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             readline configuration file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetReadlineIndent() +setlocal indentkeys=!^F,o,O,=$else,=$endif +setlocal nosmartindent + +if exists("*GetReadlineIndent") +  finish +endif + +function GetReadlineIndent() +  let lnum = prevnonblank(v:lnum - 1) +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) + +  if getline(lnum) =~ '^\s*$\(if\|else\)\>' +    let ind = ind + shiftwidth() +  endif + +  if getline(v:lnum) =~ '^\s*$\(else\|endif\)\>' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/rhelp.vim b/indent/rhelp.vim new file mode 100644 index 00000000..a676a3a0 --- /dev/null +++ b/indent/rhelp.vim @@ -0,0 +1,112 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	R Documentation (Help), *.Rd +" Author:	Jakson Alves de Aquino <jalvesaq@gmail.com> +" Homepage:     https://github.com/jalvesaq/R-Vim-runtime +" Last Change:	Tue Apr 07, 2015  04:38PM + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +runtime indent/r.vim +let s:RIndent = function(substitute(&indentexpr, "()", "", "")) +let b:did_indent = 1 + +setlocal noautoindent +setlocal nocindent +setlocal nosmartindent +setlocal nolisp +setlocal indentkeys=0{,0},:,!^F,o,O,e +setlocal indentexpr=GetCorrectRHelpIndent() + +" Only define the functions once. +if exists("*GetRHelpIndent") +  finish +endif + +function s:SanitizeRHelpLine(line) +  let newline = substitute(a:line, '\\\\', "x", "g") +  let newline = substitute(newline, '\\{', "x", "g") +  let newline = substitute(newline, '\\}', "x", "g") +  let newline = substitute(newline, '\\%', "x", "g") +  let newline = substitute(newline, '%.*', "", "") +  let newline = substitute(newline, '\s*$', "", "") +  return newline +endfunction + +function GetRHelpIndent() + +  let clnum = line(".")    " current line +  if clnum == 1 +    return 0 +  endif +  let cline = getline(clnum) + +  if cline =~ '^\s*}\s*$' +    let i = clnum +    let bb = -1 +    while bb != 0 && i > 1 +      let i -= 1 +      let line = s:SanitizeRHelpLine(getline(i)) +      let line2 = substitute(line, "{", "", "g") +      let openb = strlen(line) - strlen(line2) +      let line3 = substitute(line2, "}", "", "g") +      let closeb = strlen(line2) - strlen(line3) +      let bb += openb - closeb +    endwhile +    return indent(i) +  endif + +  if cline =~ '^\s*#ifdef\>' || cline =~ '^\s*#endif\>' +    return 0 +  endif + +  let lnum = clnum - 1 +  let line = getline(lnum) +  if line =~ '^\s*#ifdef\>' || line =~ '^\s*#endif\>' +    let lnum -= 1 +    let line = getline(lnum) +  endif +  while lnum > 1 && (line =~ '^\s*$' || line =~ '^#ifdef' || line =~ '^#endif') +    let lnum -= 1 +    let line = getline(lnum) +  endwhile +  if lnum == 1 +    return 0 +  endif +  let line = s:SanitizeRHelpLine(line) +  let line2 = substitute(line, "{", "", "g") +  let openb = strlen(line) - strlen(line2) +  let line3 = substitute(line2, "}", "", "g") +  let closeb = strlen(line2) - strlen(line3) +  let bb = openb - closeb + +  let ind = indent(lnum) + (bb * shiftwidth()) + +  if line =~ '^\s*}\s*$' +    let ind = indent(lnum) +  endif + +  if ind < 0 +    return 0 +  endif + +  return ind +endfunction + +function GetCorrectRHelpIndent() +  let lastsection = search('^\\[a-z]*{', "bncW") +  let secname = getline(lastsection) +  if secname =~ '^\\usage{' || secname =~ '^\\examples{' || secname =~ '^\\dontshow{' || secname =~ '^\\dontrun{' || secname =~ '^\\donttest{' || secname =~ '^\\testonly{' || secname =~ '^\\method{.*}{.*}(' +    return s:RIndent() +  else +    return GetRHelpIndent() +  endif +endfunction + +" vim: sw=2 + +endif diff --git a/indent/rmd.vim b/indent/rmd.vim new file mode 100644 index 00000000..c9acd656 --- /dev/null +++ b/indent/rmd.vim @@ -0,0 +1,51 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Rmd +" Author:	Jakson Alves de Aquino <jalvesaq@gmail.com> +" Homepage:     https://github.com/jalvesaq/R-Vim-runtime +" Last Change:	Tue Apr 07, 2015  04:38PM + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +runtime indent/r.vim +let s:RIndent = function(substitute(&indentexpr, "()", "", "")) +let b:did_indent = 1 + +setlocal indentkeys=0{,0},:,!^F,o,O,e +setlocal indentexpr=GetRmdIndent() + +if exists("*GetRmdIndent") +  finish +endif + +function GetMdIndent() +  let pline = getline(v:lnum - 1) +  let cline = getline(v:lnum) +  if prevnonblank(v:lnum - 1) < v:lnum - 1 || cline =~ '^\s*[-\+\*]\s' || cline =~ '^\s*\d\+\.\s\+' +    return indent(v:lnum) +  elseif pline =~ '^\s*[-\+\*]\s' +    return indent(v:lnum - 1) + 2 +  elseif pline =~ '^\s*\d\+\.\s\+' +    return indent(v:lnum - 1) + 3 +  endif +  return indent(prevnonblank(v:lnum - 1)) +endfunction + +function GetRmdIndent() +  if getline(".") =~ '^[ \t]*```{r .*}$' || getline(".") =~ '^[ \t]*```$' +    return 0 +  endif +  if search('^[ \t]*```{r', "bncW") > search('^[ \t]*```$', "bncW") +    return s:RIndent() +  else +    return GetMdIndent() +  endif +endfunction + +" vim: sw=2 + +endif diff --git a/indent/rnoweb.vim b/indent/rnoweb.vim new file mode 100644 index 00000000..7499970f --- /dev/null +++ b/indent/rnoweb.vim @@ -0,0 +1,51 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Rnoweb +" Author:	Jakson Alves de Aquino <jalvesaq@gmail.com> +" Homepage:     https://github.com/jalvesaq/R-Vim-runtime +" Last Change:	Fri Apr 15, 2016  10:58PM + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +runtime indent/tex.vim + +function! s:NoTeXIndent() +  return indent(line(".")) +endfunction + +if &indentexpr == "" || &indentexpr == "GetRnowebIndent()" +  let s:TeXIndent = function("s:NoTeXIndent") +else +  let s:TeXIndent = function(substitute(&indentexpr, "()", "", "")) +endif + +unlet b:did_indent +runtime indent/r.vim +let s:RIndent = function(substitute(&indentexpr, "()", "", "")) +let b:did_indent = 1 + +setlocal indentkeys=0{,0},!^F,o,O,e,},=\bibitem,=\item +setlocal indentexpr=GetRnowebIndent() + +if exists("*GetRnowebIndent") +  finish +endif + +function GetRnowebIndent() +  let curline = getline(".") +  if curline =~ '^<<.*>>=$' || curline =~ '^\s*@$' +    return 0 +  endif +  if search("^<<", "bncW") > search("^@", "bncW") +    return s:RIndent() +  endif +  return s:TeXIndent() +endfunction + +" vim: sw=2 + +endif diff --git a/indent/rpl.vim b/indent/rpl.vim new file mode 100644 index 00000000..a963363f --- /dev/null +++ b/indent/rpl.vim @@ -0,0 +1,67 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	RPL/2 +" Version:	0.2 +" Last Change:	2017 Jun 13 +" Maintainer:	BERTRAND Joël <rpl2@free.fr> + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentkeys+==~end,=~case,=~if,=~then,=~else,=~do,=~until,=~while,=~repeat,=~select,=~default,=~for,=~start,=~next,=~step,<<>,<>> + +" Define the appropriate indent function but only once +setlocal indentexpr=RplGetFreeIndent() +if exists("*RplGetFreeIndent") +  finish +endif + +let b:undo_indent = "set ai< indentkeys< indentexpr<" + +function RplGetIndent(lnum) +  let ind = indent(a:lnum) +  let prevline=getline(a:lnum) +  " Strip tail comment +  let prevstat=substitute(prevline, '!.*$', '', '') + +  " Add a shiftwidth to statements following if, iferr, then, else, elseif, +  " case, select, default, do, until, while, repeat, for, start +  if prevstat =~? '\<\(if\|iferr\|do\|while\)\>' && prevstat =~? '\<end\>' +  elseif prevstat =~? '\(^\|\s\+\)<<\($\|\s\+\)' && prevstat =~? '\s\+>>\($\|\s\+\)' +  elseif prevstat =~? '\<\(if\|iferr\|then\|else\|elseif\|select\|case\|do\|until\|while\|repeat\|for\|start\|default\)\>' || prevstat =~? '\(^\|\s\+\)<<\($\|\s\+\)' +    let ind = ind + shiftwidth() +  endif + +  " Subtract a shiftwidth from then, else, elseif, end, until, repeat, next, +  " step +  let line = getline(v:lnum) +  if line =~? '^\s*\(then\|else\|elseif\|until\|repeat\|next\|step\|default\|end\)\>' +    let ind = ind - shiftwidth() +  elseif line =~? '^\s*>>\($\|\s\+\)' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +function RplGetFreeIndent() +  " Find the previous non-blank line +  let lnum = prevnonblank(v:lnum - 1) + +  " Use zero indent at the top of the file +  if lnum == 0 +    return 0 +  endif + +  let ind=RplGetIndent(lnum) +  return ind +endfunction + +" vim:sw=2 tw=130 + +endif diff --git a/indent/rrst.vim b/indent/rrst.vim new file mode 100644 index 00000000..2266e8b1 --- /dev/null +++ b/indent/rrst.vim @@ -0,0 +1,51 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Rrst +" Author:	Jakson Alves de Aquino <jalvesaq@gmail.com> +" Homepage:     https://github.com/jalvesaq/R-Vim-runtime +" Last Change:	Tue Apr 07, 2015  04:38PM + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +runtime indent/r.vim +let s:RIndent = function(substitute(&indentexpr, "()", "", "")) +let b:did_indent = 1 + +setlocal indentkeys=0{,0},:,!^F,o,O,e +setlocal indentexpr=GetRrstIndent() + +if exists("*GetRrstIndent") +  finish +endif + +function GetRstIndent() +  let pline = getline(v:lnum - 1) +  let cline = getline(v:lnum) +  if prevnonblank(v:lnum - 1) < v:lnum - 1 || cline =~ '^\s*[-\+\*]\s' || cline =~ '^\s*\d\+\.\s\+' +    return indent(v:lnum) +  elseif pline =~ '^\s*[-\+\*]\s' +    return indent(v:lnum - 1) + 2 +  elseif pline =~ '^\s*\d\+\.\s\+' +    return indent(v:lnum - 1) + 3 +  endif +  return indent(prevnonblank(v:lnum - 1)) +endfunction + +function GetRrstIndent() +  if getline(".") =~ '^\.\. {r .*}$' || getline(".") =~ '^\.\. \.\.$' +    return 0 +  endif +  if search('^\.\. {r', "bncW") > search('^\.\. \.\.$', "bncW") +    return s:RIndent() +  else +    return GetRstIndent() +  endif +endfunction + +" vim: sw=2 + +endif diff --git a/indent/rst.vim b/indent/rst.vim new file mode 100644 index 00000000..20a67731 --- /dev/null +++ b/indent/rst.vim @@ -0,0 +1,63 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             reStructuredText Documentation Format +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2011-08-03 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetRSTIndent() +setlocal indentkeys=!^F,o,O +setlocal nosmartindent + +if exists("*GetRSTIndent") +  finish +endif + +let s:itemization_pattern = '^\s*[-*+]\s' +let s:enumeration_pattern = '^\s*\%(\d\+\|#\)\.\s\+' + +function GetRSTIndent() +  let lnum = prevnonblank(v:lnum - 1) +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) +  let line = getline(lnum) + +  if line =~ s:itemization_pattern +    let ind += 2 +  elseif line =~ s:enumeration_pattern +    let ind += matchend(line, s:enumeration_pattern) +  endif + +  let line = getline(v:lnum - 1) + +  " Indent :FIELD: lines.  Don’t match if there is no text after the field or +  " if the text ends with a sent-ender. +   if line =~ '^:.\+:\s\{-1,\}\S.\+[^.!?:]$' +     return matchend(line, '^:.\{-1,}:\s\+') +   endif + +  if line =~ '^\s*$' +    execute lnum +    call search('^\s*\%([-*+]\s\|\%(\d\+\|#\)\.\s\|\.\.\|$\)', 'bW') +    let line = getline('.') +    if line =~ s:itemization_pattern +      let ind -= 2 +    elseif line =~ s:enumeration_pattern +      let ind -= matchend(line, s:enumeration_pattern) +    elseif line =~ '^\s*\.\.' +      let ind -= 3 +    endif +  endif + +  return ind +endfunction + +endif diff --git a/indent/ruby.vim b/indent/ruby.vim index 3617a925..a4b9e043 100644 --- a/indent/ruby.vim +++ b/indent/ruby.vim @@ -1,3 +1,702 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:		Ruby +" Maintainer:		Nikolai Weibull <now at bitwi.se> +" URL:			https://github.com/vim-ruby/vim-ruby +" Release Coordinator:	Doug Kearns <dougkearns@gmail.com> + +" 0. Initialization {{{1 +" ================= + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +if !exists('g:ruby_indent_access_modifier_style') +  " Possible values: "normal", "indent", "outdent" +  let g:ruby_indent_access_modifier_style = 'normal' +endif + +if !exists('g:ruby_indent_block_style') +  " Possible values: "expression", "do" +  let g:ruby_indent_block_style = 'expression' +endif + +setlocal nosmartindent + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetRubyIndent(v:lnum) +setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,. +setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue,==begin,==end +setlocal indentkeys+==private,=protected,=public + +" Only define the function once. +if exists("*GetRubyIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 1. Variables {{{1 +" ============ + +" Regex of syntax group names that are or delimit strings/symbols or are comments. +let s:syng_strcom = '\<ruby\%(Regexp\|RegexpDelimiter\|RegexpEscape' . +      \ '\|Symbol\|String\|StringDelimiter\|StringEscape\|ASCIICode' . +      \ '\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|Comment\|Documentation\)\>' + +" Regex of syntax group names that are strings. +let s:syng_string = +      \ '\<ruby\%(String\|Interpolation\|NoInterpolation\|StringEscape\)\>' + +" Regex of syntax group names that are strings or documentation. +let s:syng_stringdoc = +      \'\<ruby\%(String\|Interpolation\|NoInterpolation\|StringEscape\|Documentation\)\>' + +" 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."'" + +" Regex used for words that, at the start of a line, add a level of indent. +let s:ruby_indent_keywords = +      \ '^\s*\zs\<\%(module\|class\|if\|for' . +      \   '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue' . +      \   '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . +      \ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' . +      \    '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>' + +" Regex used for words that, at the start of a line, remove a level of indent. +let s:ruby_deindent_keywords = +      \ '^\s*\zs\<\%(ensure\|else\|rescue\|elsif\|when\|end\):\@!\>' + +" Regex that defines the start-match for the 'end' keyword. +"let s:end_start_regex = '\%(^\|[^.]\)\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\|do\)\>' +" TODO: the do here should be restricted somewhat (only at end of line)? +let s:end_start_regex = +      \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . +      \ '\<\%(module\|class\|if\|for\|while\|until\|case\|unless\|begin' . +      \   '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . +      \ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>' + +" Regex that defines the middle-match for the 'end' keyword. +let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>\|when\|elsif\):\@!\>' + +" Regex that defines the end-match for the 'end' keyword. +let s:end_end_regex = '\%(^\|[^.:@$]\)\@<=\<end:\@!\>' + +" Expression used for searchpair() call for finding match for 'end' keyword. +let s:end_skip_expr = s:skip_expr . +      \ ' || (expand("<cword>") == "do"' . +      \ ' && getline(".") =~ "^\\s*\\<\\(while\\|until\\|for\\):\\@!\\>")' + +" Regex that defines continuation lines, not including (, {, or [. +let s:non_bracket_continuation_regex = +      \ '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Regex that defines continuation lines. +let s:continuation_regex = +      \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Regex that defines continuable keywords +let s:continuable_regex = +      \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . +      \ '\<\%(if\|for\|while\|until\|unless\):\@!\>' + +" Regex that defines bracket continuations +let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$' + +" Regex that defines dot continuations +let s:dot_continuation_regex = '%\@<!\.\s*\%(#.*\)\=$' + +" Regex that defines backslash continuations +let s:backslash_continuation_regex = '%\@<!\\\s*$' + +" Regex that defines end of bracket continuation followed by another continuation +let s:bracket_switch_continuation_regex = '^\([^(]\+\zs).\+\)\+'.s:continuation_regex + +" Regex that defines the first part of a splat pattern +let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' + +" Regex that describes all indent access modifiers +let s:access_modifier_regex = '\C^\s*\%(public\|protected\|private\)\s*\%(#.*\)\=$' + +" Regex that describes the indent access modifiers (excludes public) +let s:indent_access_modifier_regex = '\C^\s*\%(protected\|private\)\s*\%(#.*\)\=$' + +" Regex that defines blocks. +" +" Note that there's a slight problem with this regex and s:continuation_regex. +" Code like this will be matched by both: +" +"   method_call do |(a, b)| +" +" The reason is that the pipe matches a hanging "|" operator. +" +let s:block_regex = +      \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|[^|]*|\)\=\s*\%(#.*\)\=$' + +let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex + +" Regex that describes a leading operator (only a method call's dot for now) +let s:leading_operator_regex = '^\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 + +" 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 string or documentation. +function s:IsInStringOrDocumentation(lnum, col) +  return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_stringdoc +endfunction + +" Check if the character at lnum:col is inside a string delimiter +function s:IsInStringDelimiter(lnum, col) +  return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'rubyStringDelimiter' +endfunction + +" 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 =~ '^=begin' +      if in_block +        let in_block = 0 +      else +        break +      endif +    elseif !in_block && line =~ '^=end' +      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 + +" Find line above 'lnum' that started the continuation 'lnum' may be part of. +function s:GetMSL(lnum) +  " Start on the line we're at and use its indent. +  let msl = a:lnum +  let msl_body = getline(msl) +  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) + +    if !s:Match(msl, s:backslash_continuation_regex) && +          \ s:Match(lnum, s:backslash_continuation_regex) +      " If the current line doesn't end in a backslash, but the previous one +      " does, look for that line's msl +      " +      " Example: +      "   foo = "bar" \ +      "     "baz" +      " +      let msl = lnum +    elseif s:Match(msl, s:leading_operator_regex) +      " If the current line starts with a leading operator, keep its indent +      " and keep looking for an MSL. +      let msl = lnum +    elseif s:Match(lnum, s:splat_regex) +      " If the above line looks like the "*" of a splat, use the current one's +      " indentation. +      " +      " Example: +      "   Hash[* +      "     method_call do +      "       something +      " +      return msl +    elseif s:Match(lnum, s:non_bracket_continuation_regex) && +          \ s:Match(msl, s:non_bracket_continuation_regex) +      " If the current line is a non-bracket continuation and so is the +      " previous one, keep its indent and continue looking for an MSL. +      " +      " Example: +      "   method_call one, +      "     two, +      "     three +      " +      let msl = lnum +    elseif s:Match(lnum, s:dot_continuation_regex) && +          \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) +      " If the current line is a bracket continuation or a block-starter, but +      " the previous is a dot, keep going to see if the previous line is the +      " start of another continuation. +      " +      " Example: +      "   parent. +      "     method_call { +      "     three +      " +      let msl = lnum +    elseif s:Match(lnum, s:non_bracket_continuation_regex) && +          \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) +      " If the current line is a bracket continuation or a block-starter, but +      " the previous is a non-bracket one, respect the previous' indentation, +      " and stop here. +      " +      " Example: +      "   method_call one, +      "     two { +      "     three +      " +      return lnum +    elseif s:Match(lnum, s:bracket_continuation_regex) && +          \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) +      " If both lines are bracket continuations (the current may also be a +      " block-starter), use the current one's and stop here +      " +      " Example: +      "   method_call( +      "     other_method_call( +      "       foo +      return msl +    elseif s:Match(lnum, s:block_regex) && +          \ !s:Match(msl, s:continuation_regex) && +          \ !s:Match(msl, s:block_continuation_regex) +      " If the previous line is a block-starter and the current one is +      " mostly ordinary, use the current one as the MSL. +      " +      " Example: +      "   method_call do +      "     something +      "     something_else +      return msl +    else +      let col = match(line, s:continuation_regex) + 1 +      if (col > 0 && !s:IsInStringOrComment(lnum, col)) +            \ || s:IsInString(lnum, strlen(line)) +        let msl = lnum +      else +        break +      endif +    endif + +    let msl_body = getline(msl) +    let lnum = s:PrevNonBlankNonString(lnum - 1) +  endwhile +  return msl +endfunction + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:ExtraBrackets(lnum) +  let opening = {'parentheses': [], 'braces': [], 'brackets': []} +  let closing = {'parentheses': [], 'braces': [], 'brackets': []} + +  let line = getline(a:lnum) +  let pos  = match(line, '[][(){}]', 0) + +  " Save any encountered opening brackets, and remove them once a matching +  " closing one has been found. If a closing bracket shows up that doesn't +  " close anything, save it for later. +  while pos != -1 +    if !s:IsInStringOrComment(a:lnum, pos + 1) +      if line[pos] == '(' +        call add(opening.parentheses, {'type': '(', 'pos': pos}) +      elseif line[pos] == ')' +        if empty(opening.parentheses) +          call add(closing.parentheses, {'type': ')', 'pos': pos}) +        else +          let opening.parentheses = opening.parentheses[0:-2] +        endif +      elseif line[pos] == '{' +        call add(opening.braces, {'type': '{', 'pos': pos}) +      elseif line[pos] == '}' +        if empty(opening.braces) +          call add(closing.braces, {'type': '}', 'pos': pos}) +        else +          let opening.braces = opening.braces[0:-2] +        endif +      elseif line[pos] == '[' +        call add(opening.brackets, {'type': '[', 'pos': pos}) +      elseif line[pos] == ']' +        if empty(opening.brackets) +          call add(closing.brackets, {'type': ']', 'pos': pos}) +        else +          let opening.brackets = opening.brackets[0:-2] +        endif +      endif +    endif + +    let pos = match(line, '[][(){}]', pos + 1) +  endwhile + +  " Find the rightmost brackets, since they're the ones that are important in +  " both opening and closing cases +  let rightmost_opening = {'type': '(', 'pos': -1} +  let rightmost_closing = {'type': ')', 'pos': -1} + +  for opening in opening.parentheses + opening.braces + opening.brackets +    if opening.pos > rightmost_opening.pos +      let rightmost_opening = opening +    endif +  endfor + +  for closing in closing.parentheses + closing.braces + closing.brackets +    if closing.pos > rightmost_closing.pos +      let rightmost_closing = closing +    endif +  endfor + +  return [rightmost_opening, rightmost_closing] +endfunction + +function s:Match(lnum, regex) +  let line   = getline(a:lnum) +  let offset = match(line, '\C'.a:regex) +  let col    = offset + 1 + +  while offset > -1 && s:IsInStringOrComment(a:lnum, col) +    let offset = match(line, '\C'.a:regex, offset + 1) +    let col = offset + 1 +  endwhile + +  if offset > -1 +    return col +  else +    return 0 +  endif +endfunction + +" Locates the containing class/module's definition line, ignoring nested classes +" along the way. +" +function! s:FindContainingClass() +  let saved_position = getpos('.') + +  while searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', +        \ s:end_skip_expr) > 0 +    if expand('<cword>') =~# '\<class\|module\>' +      let found_lnum = line('.') +      call setpos('.', saved_position) +      return found_lnum +    endif +  endwhile + +  call setpos('.', saved_position) +  return 0 +endfunction + +" 3. GetRubyIndent Function {{{1 +" ========================= + +function GetRubyIndent(...) +  " 3.1. Setup {{{2 +  " ---------- + +  " The value of a single shift-width +  let sw = shiftwidth() + +  " For the current line, use the first argument if given, else v:lnum +  let clnum = a:0 ? a:1 : v:lnum + +  " Set up variables for restoring position in file.  Could use clnum here. +  let vcol = col('.') + +  " 3.2. Work on the current line {{{2 +  " ----------------------------- + +  " Get the current line. +  let line = getline(clnum) +  let ind = -1 + +  " If this line is an access modifier keyword, align according to the closest +  " class declaration. +  if g:ruby_indent_access_modifier_style == 'indent' +    if s:Match(clnum, s:access_modifier_regex) +      let class_line = s:FindContainingClass() +      if class_line > 0 +        return indent(class_line) + sw +      endif +    endif +  elseif g:ruby_indent_access_modifier_style == 'outdent' +    if s:Match(clnum, s:access_modifier_regex) +      let class_line = s:FindContainingClass() +      if class_line > 0 +        return indent(class_line) +      endif +    endif +  endif + +  " 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(clnum, col) +    call cursor(clnum, col) +    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 +      elseif g:ruby_indent_block_style == 'do' +        let ind = indent(line('.')) +      else " g:ruby_indent_block_style == 'expression' +        let ind = indent(s:GetMSL(line('.'))) +      endif +    endif +    return ind +  endif + +  " If we have a =begin or =end set indent to first column. +  if match(line, '^\s*\%(=begin\|=end\)$') != -1 +    return 0 +  endif + +  " If we have a deindenting keyword, find its match and indent to its level. +  " TODO: this is messy +  if s:Match(clnum, s:ruby_deindent_keywords) +    call cursor(clnum, 1) +    if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', +          \ s:end_skip_expr) > 0 +      let msl  = s:GetMSL(line('.')) +      let line = getline(line('.')) + +      if strpart(line, 0, col('.') - 1) =~ '=\s*$' && +            \ strpart(line, col('.') - 1, 2) !~ 'do' +        " assignment to case/begin/etc, on the same line, hanging indent +        let ind = virtcol('.') - 1 +      elseif g:ruby_indent_block_style == 'do' +        " align to line of the "do", not to the MSL +        let ind = indent(line('.')) +      elseif getline(msl) =~ '=\s*\(#.*\)\=$' +        " in the case of assignment to the MSL, align to the starting line, +        " not to the MSL +        let ind = indent(line('.')) +      else +        " align to the MSL +        let ind = indent(msl) +      endif +    endif +    return ind +  endif + +  " If we are in a multi-line string or line-comment, don't do anything to it. +  if s:IsInStringOrDocumentation(clnum, matchend(line, '^\s*') + 1) +    return indent('.') +  endif + +  " If we are at the closing delimiter of a "<<" heredoc-style string, set the +  " indent to 0. +  if line =~ '^\k\+\s*$' +        \ && s:IsInStringDelimiter(clnum, 1) +        \ && search('\V<<'.line, 'nbW') > 0 +    return 0 +  endif + +  " If the current line starts with a leading operator, add a level of indent. +  if s:Match(clnum, s:leading_operator_regex) +    return indent(s:GetMSL(clnum)) + sw +  endif + +  " 3.3. Work on the previous line. {{{2 +  " ------------------------------- + +  " Find a non-blank, non-multi-line string line above the current line. +  let lnum = s:PrevNonBlankNonString(clnum - 1) + +  " If the line is empty and inside a string, use the previous line. +  if line =~ '^\s*$' && lnum != prevnonblank(clnum - 1) +    return indent(prevnonblank(clnum)) +  endif + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  " Set up variables for the previous line. +  let line = getline(lnum) +  let ind = indent(lnum) + +  if g:ruby_indent_access_modifier_style == 'indent' +    " If the previous line was a private/protected keyword, add a +    " level of indent. +    if s:Match(lnum, s:indent_access_modifier_regex) +      return indent(lnum) + sw +    endif +  elseif g:ruby_indent_access_modifier_style == 'outdent' +    " If the previous line was a private/protected/public keyword, add +    " a level of indent, since the keyword has been out-dented. +    if s:Match(lnum, s:access_modifier_regex) +      return indent(lnum) + sw +    endif +  endif + +  if s:Match(lnum, s:continuable_regex) && s:Match(lnum, s:continuation_regex) +    return indent(s:GetMSL(lnum)) + sw + sw +  endif + +  " If the previous line ended with a block opening, add a level of indent. +  if s:Match(lnum, s:block_regex) +    let msl = s:GetMSL(lnum) + +    if g:ruby_indent_block_style == 'do' +      " don't align to the msl, align to the "do" +      let ind = indent(lnum) + sw +    elseif getline(msl) =~ '=\s*\(#.*\)\=$' +      " in the case of assignment to the msl, align to the starting line, +      " not to the msl +      let ind = indent(lnum) + sw +    else +      let ind = indent(msl) + sw +    endif +    return ind +  endif + +  " If the previous line started with a leading operator, use its MSL's level +  " of indent +  if s:Match(lnum, s:leading_operator_regex) +    return indent(s:GetMSL(lnum)) +  endif + +  " If the previous line ended with the "*" of a splat, add a level of indent +  if line =~ s:splat_regex +    return indent(lnum) + sw +  endif + +  " If the previous line contained unclosed opening brackets and we are still +  " in them, find the rightmost one and add indent depending on the bracket +  " type. +  " +  " If it contained hanging closing brackets, find the rightmost one, find its +  " match and indent according to that. +  if line =~ '[[({]' || line =~ '[])}]\s*\%(#.*\)\=$' +    let [opening, closing] = s:ExtraBrackets(lnum) + +    if opening.pos != -1 +      if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 +        if col('.') + 1 == col('$') +          return ind + sw +        else +          return virtcol('.') +        endif +      else +        let nonspace = matchend(line, '\S', opening.pos + 1) - 1 +        return nonspace > 0 ? nonspace : ind + sw +      endif +    elseif closing.pos != -1 +      call cursor(lnum, closing.pos + 1) +      normal! % + +      if s:Match(line('.'), s:ruby_indent_keywords) +        return indent('.') + sw +      else +        return indent(s:GetMSL(line('.'))) +      endif +    else +      call cursor(clnum, vcol) +    end +  endif + +  " If the previous line ended with an "end", match that "end"s beginning's +  " indent. +  let col = s:Match(lnum, '\%(^\|[^.:@$]\)\<end\>\s*\%(#.*\)\=$') +  if col > 0 +    call cursor(lnum, col) +    if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', +          \ s:end_skip_expr) > 0 +      let n = line('.') +      let ind = indent('.') +      let msl = s:GetMSL(n) +      if msl != n +        let ind = indent(msl) +      end +      return ind +    endif +  end + +  let col = s:Match(lnum, s:ruby_indent_keywords) +  if col > 0 +    call cursor(lnum, col) +    let ind = virtcol('.') - 1 + sw +    " TODO: make this better (we need to count them) (or, if a searchpair +    " fails, we know that something is lacking an end and thus we indent a +    " level +    if s:Match(lnum, s:end_end_regex) +      let ind = indent('.') +    endif +    return ind +  endif + +  " 3.4. Work on the MSL line. {{{2 +  " -------------------------- + +  " Set up variables to use and search for MSL to the previous line. +  let p_lnum = lnum +  let lnum = s:GetMSL(lnum) + +  " If the previous line wasn't a MSL. +  if p_lnum != lnum +    " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. +    if s:Match(p_lnum, s:bracket_switch_continuation_regex) +      return ind - 1 +    " If previous line is a continuation return its indent. +    " TODO: the || s:IsInString() thing worries me a bit. +    elseif s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) +      return ind +    endif +  endif + +  " Set up more variables, now that we know we wasn't continuation bound. +  let line = getline(lnum) +  let msl_ind = indent(lnum) + +  " If the MSL line had an indenting keyword in it, add a level of indent. +  " TODO: this does not take into account contrived things such as +  " module Foo; class Bar; end +  if s:Match(lnum, s:ruby_indent_keywords) +    let ind = msl_ind + sw +    if s:Match(lnum, s:end_end_regex) +      let ind = ind - sw +    endif +    return ind +  endif + +  " If the previous line ended with [*+/.,-=], but wasn't a block ending or a +  " closing bracket, indent one extra level. +  if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') +    if lnum == p_lnum +      let ind = msl_ind + sw +    else +      let ind = msl_ind +    endif +    return ind +  endif + +  " }}}2 + +  return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 et: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ruby') == -1  " Vim indent file diff --git a/indent/rust.vim b/indent/rust.vim index 042e2ab5..5f5c74b9 100644 --- a/indent/rust.vim +++ b/indent/rust.vim @@ -1,3 +1,220 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:         Rust +" Author:           Chris Morgan <me@chrismorgan.info> +" Last Change:      2017 Jun 13 +" For bugs, patches and license go to https://github.com/rust-lang/rust.vim + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +	finish +endif +let b:did_indent = 1 + +setlocal cindent +setlocal cinoptions=L0,(0,Ws,J1,j1 +setlocal cinkeys=0{,0},!^F,o,O,0[,0] +" Don't think cinwords will actually do anything at all... never mind +setlocal cinwords=for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fn,extern + +" Some preliminary settings +setlocal nolisp		" Make sure lisp indenting doesn't supersede us +setlocal autoindent	" indentexpr isn't much help otherwise +" Also do indentkeys, otherwise # gets shoved to column 0 :-/ +setlocal indentkeys=0{,0},!^F,o,O,0[,0] + +setlocal indentexpr=GetRustIndent(v:lnum) + +" Only define the function once. +if exists("*GetRustIndent") +	finish +endif + +let s:save_cpo = &cpo +set cpo&vim + +" Come here when loading the script the first time. + +function! s:get_line_trimmed(lnum) +	" Get the line and remove a trailing comment. +	" Use syntax highlighting attributes when possible. +	" NOTE: this is not accurate; /* */ or a line continuation could trick it +	let line = getline(a:lnum) +	let line_len = strlen(line) +	if has('syntax_items') +		" If the last character in the line is a comment, do a binary search for +		" the start of the comment.  synID() is slow, a linear search would take +		" too long on a long line. +		if synIDattr(synID(a:lnum, line_len, 1), "name") =~ 'Comment\|Todo' +			let min = 1 +			let max = line_len +			while min < max +				let col = (min + max) / 2 +				if synIDattr(synID(a:lnum, col, 1), "name") =~ 'Comment\|Todo' +					let max = col +				else +					let min = col + 1 +				endif +			endwhile +			let line = strpart(line, 0, min - 1) +		endif +		return substitute(line, "\s*$", "", "") +	else +		" Sorry, this is not complete, nor fully correct (e.g. string "//"). +		" Such is life. +		return substitute(line, "\s*//.*$", "", "") +	endif +endfunction + +function! s:is_string_comment(lnum, col) +	if has('syntax_items') +		for id in synstack(a:lnum, a:col) +			let synname = synIDattr(id, "name") +			if synname == "rustString" || synname =~ "^rustComment" +				return 1 +			endif +		endfor +	else +		" without syntax, let's not even try +		return 0 +	endif +endfunction + +function GetRustIndent(lnum) + +	" Starting assumption: cindent (called at the end) will do it right +	" normally. We just want to fix up a few cases. + +	let line = getline(a:lnum) + +	if has('syntax_items') +		let synname = synIDattr(synID(a:lnum, 1, 1), "name") +		if synname == "rustString" +			" If the start of the line is in a string, don't change the indent +			return -1 +		elseif synname =~ '\(Comment\|Todo\)' +					\ && line !~ '^\s*/\*'  " not /* opening line +			if synname =~ "CommentML" " multi-line +				if line !~ '^\s*\*' && getline(a:lnum - 1) =~ '^\s*/\*' +					" This is (hopefully) the line after a /*, and it has no +					" leader, so the correct indentation is that of the +					" previous line. +					return GetRustIndent(a:lnum - 1) +				endif +			endif +			" If it's in a comment, let cindent take care of it now. This is +			" for cases like "/*" where the next line should start " * ", not +			" "* " as the code below would otherwise cause for module scope +			" Fun fact: "  /*\n*\n*/" takes two calls to get right! +			return cindent(a:lnum) +		endif +	endif + +	" cindent gets second and subsequent match patterns/struct members wrong, +	" as it treats the comma as indicating an unfinished statement:: +	" +	" match a { +	"     b => c, +	"         d => e, +	"         f => g, +	" }; + +	" Search backwards for the previous non-empty line. +	let prevlinenum = prevnonblank(a:lnum - 1) +	let prevline = s:get_line_trimmed(prevlinenum) +	while prevlinenum > 1 && prevline !~ '[^[:blank:]]' +		let prevlinenum = prevnonblank(prevlinenum - 1) +		let prevline = s:get_line_trimmed(prevlinenum) +	endwhile + +	" 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*[\[\]{}]' +				\ && prevline !~ '^\s*fn\s' +				\ && prevline !~ '([^()]\+,$' +				\ && s:get_line_trimmed(a:lnum) !~ '^\s*\S\+\s*=>' +		" Oh ho! The previous line ended in a comma! I bet cindent will try to +		" take this too far... For now, let's normally use the previous line's +		" indent. + +		" One case where this doesn't work out is where *this* line contains +		" square or curly brackets; then we normally *do* want to be indenting +		" further. +		" +		" Another case where we don't want to is one like a function +		" definition with arguments spread over multiple lines: +		" +		" fn foo(baz: Baz, +		"        baz: Baz) // <-- cindent gets this right by itself +		" +		" Another case is similar to the previous, except calling a function +		" instead of defining it, or any conditional expression that leaves +		" an open paren: +		" +		" foo(baz, +		"     baz); +		" +		" if baz && (foo || +		"            bar) { +		" +		" Another case is when the current line is a new match arm. +		" +		" There are probably other cases where we don't want to do this as +		" well. Add them as needed. +		return indent(prevlinenum) +	endif + +	if !has("patch-7.4.355") +		" cindent before 7.4.355 doesn't do the module scope well at all; e.g.:: +		" +		" static FOO : &'static [bool] = [ +		" true, +		"	 false, +		"	 false, +		"	 true, +		"	 ]; +		" +		"	 uh oh, next statement is indented further! + +		" Note that this does *not* apply the line continuation pattern properly; +		" that's too hard to do correctly for my liking at present, so I'll just +		" start with these two main cases (square brackets and not returning to +		" column zero) + +		call cursor(a:lnum, 1) +		if searchpair('{\|(', '', '}\|)', 'nbW', +					\ 's:is_string_comment(line("."), col("."))') == 0 +			if searchpair('\[', '', '\]', 'nbW', +						\ 's:is_string_comment(line("."), col("."))') == 0 +				" Global scope, should be zero +				return 0 +			else +				" At the module scope, inside square brackets only +				"if getline(a:lnum)[0] == ']' || search('\[', '', '\]', 'nW') == a:lnum +				if line =~ "^\\s*]" +					" It's the closing line, dedent it +					return 0 +				else +					return shiftwidth() +				endif +			endif +		endif +	endif + +	" Fall back on cindent, which does it mostly right +	return cindent(a:lnum) +endfunction + +let &cpo = s:save_cpo +unlet s:save_cpo + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1  " Vim indent file diff --git a/indent/sas.vim b/indent/sas.vim new file mode 100644 index 00000000..0f8adfdb --- /dev/null +++ b/indent/sas.vim @@ -0,0 +1,142 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     SAS +" Maintainer:   Zhen-Huan Hu <wildkeny@gmail.com> +" Version:      3.0.1 +" Last Change:  Mar 13, 2017 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetSASIndent() +setlocal indentkeys+=;,=~data,=~proc,=~macro + +if exists("*GetSASIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Regex that captures the start of a data/proc section +let s:section_str = '\v%(^|;)\s*%(data|proc)>' +" Regex that captures the end of a run-processing section +let s:section_run = '\v%(^|;)\s*run\s*;' +" Regex that captures the end of a data/proc section +let s:section_end = '\v%(^|;)\s*%(quit|enddata)\s*;' + +" Regex that captures the start of a control block (anything inside a section) +let s:block_str = '\v<%(do>%([^;]+<%(to|over)>[^;]+)=|%(define|layout|method|select)>[^;]+|begingraph)\s*;' +" Regex that captures the end of a control block (anything inside a section) +let s:block_end = '\v<%(end|endlayout|endgraph)\s*;' + +" Regex that captures the start of a macro +let s:macro_str = '\v%(^|;)\s*\%macro>' +" Regex that captures the end of a macro +let s:macro_end = '\v%(^|;)\s*\%mend\s*;' + +" Regex that defines the end of the program +let s:program_end = '\v%(^|;)\s*endsas\s*;' + +" List of procs supporting run-processing +let s:run_processing_procs = [ +      \ 'catalog', 'chart', 'datasets', 'document', 'ds2', 'plot', 'sql', +      \ 'gareabar', 'gbarline', 'gchart', 'gkpi', 'gmap', 'gplot', 'gradar', 'greplay', 'gslide', 'gtile', +      \ 'anova', 'arima', 'catmod', 'factex', 'glm', 'model', 'optex', 'plan', 'reg', +      \ 'iml', +      \ ] + +" Find the line number of previous keyword defined by the regex +function! s:PrevMatch(lnum, regex) +  let prev_lnum = prevnonblank(a:lnum - 1) +  while prev_lnum > 0 +    let prev_line = getline(prev_lnum) +    if prev_line =~ a:regex +      break +    else +      let prev_lnum = prevnonblank(prev_lnum - 1) +    endif +  endwhile +  return prev_lnum +endfunction + +" Main function +function! GetSASIndent() +  let prev_lnum = prevnonblank(v:lnum - 1) +  if prev_lnum ==# 0 +    " Leave the indentation of the first line unchanged +    return indent(1) +  else +    let prev_line = getline(prev_lnum) +    " Previous non-blank line contains the start of a macro/section/block +    " while not the end of a macro/section/block (at the same line) +    if (prev_line =~ s:section_str && prev_line !~ s:section_run && prev_line !~ s:section_end) || +          \ (prev_line =~ s:block_str && prev_line !~ s:block_end) || +          \ (prev_line =~ s:macro_str && prev_line !~ s:macro_end) +      let ind = indent(prev_lnum) + &sts +    elseif prev_line =~ s:section_run && prev_line !~ s:section_end +      let prev_section_str_lnum = s:PrevMatch(v:lnum, s:section_str) +      let prev_section_end_lnum = max([ +            \ s:PrevMatch(v:lnum, s:section_end), +            \ s:PrevMatch(v:lnum, s:macro_end  ), +            \ s:PrevMatch(v:lnum, s:program_end)]) +      " Check if the section supports run-processing +      if prev_section_end_lnum < prev_section_str_lnum && +            \ getline(prev_section_str_lnum) =~ '\v%(^|;)\s*proc\s+%(' . +            \ join(s:run_processing_procs, '|') . ')>' +        let ind = indent(prev_lnum) + &sts +      else +        let ind = indent(prev_lnum) +      endif +    else +      let ind = indent(prev_lnum) +    endif +  endif +  " Re-adjustments based on the inputs of the current line +  let curr_line = getline(v:lnum) +  if curr_line =~ s:program_end +    " End of the program +    " Same indentation as the first non-blank line +    return indent(nextnonblank(1)) +  elseif curr_line =~ s:macro_end +    " Current line is the end of a macro +    " Match the indentation of the start of the macro +    return indent(s:PrevMatch(v:lnum, s:macro_str)) +  elseif curr_line =~ s:block_end && curr_line !~ s:block_str +    " Re-adjust if current line is the end of a block +    " while not the beginning of a block (at the same line) +    " Returning the indent of previous block start directly +    " would not work due to nesting +    let ind = ind - &sts +  elseif curr_line =~ s:section_str || curr_line =~ s:section_run || curr_line =~ s:section_end +    " Re-adjust if current line is the start/end of a section +    " since the end of a section could be inexplicit +    let prev_section_str_lnum = s:PrevMatch(v:lnum, s:section_str) +    " Check if the previous section supports run-processing +    if getline(prev_section_str_lnum) =~ '\v%(^|;)\s*proc\s+%(' . +          \ join(s:run_processing_procs, '|') . ')>' +      let prev_section_end_lnum = max([ +            \ s:PrevMatch(v:lnum, s:section_end), +            \ s:PrevMatch(v:lnum, s:macro_end  ), +            \ s:PrevMatch(v:lnum, s:program_end)]) +    else +      let prev_section_end_lnum = max([ +            \ s:PrevMatch(v:lnum, s:section_end), +            \ s:PrevMatch(v:lnum, s:section_run), +            \ s:PrevMatch(v:lnum, s:macro_end  ), +            \ s:PrevMatch(v:lnum, s:program_end)]) +    endif +    if prev_section_end_lnum < prev_section_str_lnum +      let ind = ind - &sts +    endif +  endif +  return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/sass.vim b/indent/sass.vim new file mode 100644 index 00000000..89c2f485 --- /dev/null +++ b/indent/sass.vim @@ -0,0 +1,42 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Sass +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2017 Jun 13 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent sw=2 et +setlocal indentexpr=GetSassIndent() +setlocal indentkeys=o,O,*<Return>,<:>,!^F + +" Only define the function once. +if exists("*GetSassIndent") +  finish +endif + +let s:property = '^\s*:\|^\s*[[:alnum:]#{}-]\+\%(:\|\s*=\)' +let s:extend = '^\s*\%(@extend\|@include\|+\)' + +function! GetSassIndent() +  let lnum = prevnonblank(v:lnum-1) +  let line = substitute(getline(lnum),'\s\+$','','') +  let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','') +  let lastcol = strlen(line) +  let line = substitute(line,'^\s\+','','') +  let indent = indent(lnum) +  let cindent = indent(v:lnum) +  if line !~ s:property && line !~ s:extend && cline =~ s:property +    return indent + shiftwidth() +  else +    return -1 +  endif +endfunction + +" vim:set sw=2: + +endif diff --git a/indent/scala.vim b/indent/scala.vim index da6c2f5c..78dcf8ad 100644 --- a/indent/scala.vim +++ b/indent/scala.vim @@ -1,3 +1,616 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Scala (http://scala-lang.org/) +" Original Author:      Stefan Matthias Aust +" Modifications By:     Derek Wyatt +" URL:                  https://github.com/derekwyatt/vim-scala +" Last Change:          2016 Aug 26 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetScalaIndent() +setlocal indentkeys=0{,0},0),!^F,<>>,o,O,e,=case,<CR> + +if exists("*GetScalaIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +let s:defMatcher = '\%(\%(private\|protected\)\%(\[[^\]]*\]\)\?\s\+\|abstract\s\+\|override\s\+\)*\<def\>' +let s:funcNameMatcher = '\w\+' +let s:typeSpecMatcher = '\%(\s*\[\_[^\]]*\]\)' +let s:defArgMatcher = '\%((\_.\{-})\)' +let s:returnTypeMatcher = '\%(:\s*\w\+' . s:typeSpecMatcher . '\?\)' +let g:fullDefMatcher = '^\s*' . s:defMatcher . '\s\+' . s:funcNameMatcher . '\s*' . s:typeSpecMatcher . '\?\s*' . s:defArgMatcher . '\?\s*' . s:returnTypeMatcher . '\?\s*[={]' + +function! scala#ConditionalConfirm(msg) +  if 0 +    call confirm(a:msg) +  endif +endfunction + +function! scala#GetLine(lnum) +  let line = substitute(getline(a:lnum), '//.*$', '', '') +  let line = substitute(line, '"\(.\|\\"\)\{-}"', '""', 'g') +  return line +endfunction + +function! scala#CountBrackets(line, openBracket, closedBracket) +  let line = substitute(a:line, '"\(.\|\\"\)\{-}"', '', 'g') +  let open = substitute(line, '[^' . a:openBracket . ']', '', 'g') +  let close = substitute(line, '[^' . a:closedBracket . ']', '', 'g') +  return strlen(open) - strlen(close) +endfunction + +function! scala#CountParens(line) +  return scala#CountBrackets(a:line, '(', ')') +endfunction + +function! scala#CountCurlies(line) +  return scala#CountBrackets(a:line, '{', '}') +endfunction + +function! scala#LineEndsInIncomplete(line) +  if a:line =~ '[.,]\s*$' +    return 1 +  else +    return 0 +  endif +endfunction + +function! scala#LineIsAClosingXML(line) +  if a:line =~ '^\s*</\w' +    return 1 +  else +    return 0 +  endif +endfunction + +function! scala#LineCompletesXML(lnum, line) +  let savedpos = getpos('.') +  call setpos('.', [savedpos[0], a:lnum, 0, savedpos[3]]) +  let tag = substitute(a:line, '^.*</\([^>]*\)>.*$', '\1', '') +  let [lineNum, colnum] = searchpairpos('<' . tag . '>', '', '</' . tag . '>', 'Wbn') +  call setpos('.', savedpos) +  let pline = scala#GetLine(prevnonblank(lineNum - 1)) +  if pline =~ '=\s*$' +    return 1 +  else +    return 0 +  endif +endfunction + +function! scala#IsParentCase() +  let savedpos = getpos('.') +  call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]]) +  let [l, c] = searchpos('^\s*\%(' . s:defMatcher . '\|\%(\<case\>\)\)', 'bnW') +  let retvalue = -1 +  if l != 0 && search('\%' . l . 'l\s*\<case\>', 'bnW') +    let retvalue = l +  endif +  call setpos('.', savedpos) +  return retvalue +endfunction + +function! scala#CurlyMatcher() +  let matchline = scala#GetLineThatMatchesBracket('{', '}') +  if scala#CountParens(scala#GetLine(matchline)) < 0 +    let savedpos = getpos('.') +    call setpos('.', [savedpos[0], matchline, 9999, savedpos[3]]) +    call searchpos('{', 'Wbc') +    call searchpos(')', 'Wb') +    let [lnum, colnum] = searchpairpos('(', '', ')', 'Wbn') +    call setpos('.', savedpos) +    let line = scala#GetLine(lnum) +    if line =~ '^\s*' . s:defMatcher +      return lnum +    else +      return matchline +    endif +  else +    return matchline +  endif +endfunction + +function! scala#GetLineAndColumnThatMatchesCurly() +  return scala#GetLineAndColumnThatMatchesBracket('{', '}') +endfunction + +function! scala#GetLineAndColumnThatMatchesParen() +  return scala#GetLineAndColumnThatMatchesBracket('(', ')') +endfunction + +function! scala#GetLineAndColumnThatMatchesBracket(openBracket, closedBracket) +  let savedpos = getpos('.') +  let curline = scala#GetLine(line('.')) +  if curline =~ a:closedBracket . '.*' . a:openBracket . '.*' . a:closedBracket +    call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]]) +    call searchpos(a:closedBracket . '\ze[^' . a:closedBracket . a:openBracket . ']*' . a:openBracket, 'W') +  else +    call setpos('.', [savedpos[0], savedpos[1], 9999, savedpos[3]]) +    call searchpos(a:closedBracket, 'Wbc') +  endif +  let [lnum, colnum] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn') +  call setpos('.', savedpos) +  return [lnum, colnum] +endfunction + +function! scala#GetLineThatMatchesCurly() +  return scala#GetLineThatMatchesBracket('{', '}') +endfunction + +function! scala#GetLineThatMatchesParen() +  return scala#GetLineThatMatchesBracket('(', ')') +endfunction + +function! scala#GetLineThatMatchesBracket(openBracket, closedBracket) +  let [lnum, colnum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket) +  return lnum +endfunction + +function! scala#NumberOfBraceGroups(line) +  let line = substitute(a:line, '[^()]', '', 'g') +  if strlen(line) == 0 +    return 0 +  endif +  let line = substitute(line, '^)*', '', 'g') +  if strlen(line) == 0 +    return 0 +  endif +  let line = substitute(line, '^(', '', 'g') +  if strlen(line) == 0 +    return 0 +  endif +  let c = 1 +  let counter = 0 +  let groupCount = 0 +  while counter < strlen(line) +    let char = strpart(line, counter, 1) +    if char == '(' +      let c = c + 1 +    elseif char == ')' +      let c = c - 1 +    endif +    if c == 0 +      let groupCount = groupCount + 1 +    endif +    let counter = counter + 1 +  endwhile +  return groupCount +endfunction + +function! scala#MatchesIncompleteDefValr(line) +  if a:line =~ '^\s*\%(' . s:defMatcher . '\|\<va[lr]\>\).*[=({]\s*$' +    return 1 +  else +    return 0 +  endif +endfunction + +function! scala#LineIsCompleteIf(line) +  if scala#CountBrackets(a:line, '{', '}') == 0 && +   \ scala#CountBrackets(a:line, '(', ')') == 0 && +   \ a:line =~ '^\s*\<if\>\s*([^)]*)\s*\S.*$' +    return 1 +  else +    return 0 +  endif +endfunction + +function! scala#LineCompletesIfElse(lnum, line) +  if a:line =~ '^\s*\%(\<if\>\|\%(}\s*\)\?\<else\>\)' +    return 0 +  endif +  let result = search('^\%(\s*\<if\>\s*(.*).*\n\|\s*\<if\>\s*(.*)\s*\n.*\n\)\%(\s*\<else\>\s*\<if\>\s*(.*)\s*\n.*\n\)*\%(\s*\<else\>\s*\n\|\s*\<else\>[^{]*\n\)\?\%' . a:lnum . 'l', 'Wbn') +  if result != 0 && scala#GetLine(prevnonblank(a:lnum - 1)) !~ '{\s*$' +    return result +  endif +  return 0 +endfunction + +function! scala#GetPrevCodeLine(lnum) +  " This needs to skip comment lines +  return prevnonblank(a:lnum - 1) +endfunction + +function! scala#InvertBracketType(openBracket, closedBracket) +  if a:openBracket == '(' +    return [ '{', '}' ] +  else +    return [ '(', ')' ] +  endif +endfunction + +function! scala#Testhelper(lnum, line, openBracket, closedBracket, iteration) +  let bracketCount = scala#CountBrackets(a:line, a:openBracket, a:closedBracket) +  " There are more '}' braces than '{' on this line so it may be completing the function definition +  if bracketCount < 0 +    let [matchedLNum, matchedColNum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket) +    if matchedLNum == a:lnum +      return -1 +    endif +    let matchedLine = scala#GetLine(matchedLNum) +    if ! scala#MatchesIncompleteDefValr(matchedLine) +      let bracketLine = substitute(substitute(matchedLine, '\%' . matchedColNum . 'c.*$', '', ''), '[^{}()]', '', 'g') +      if bracketLine =~ '}$' +        return scala#Testhelper(matchedLNum, matchedLine, '{', '}', a:iteration + 1) +      elseif bracketLine =~ ')$' +        return scala#Testhelper(matchedLNum, matchedLine, '(', ')', a:iteration + 1) +      else +        let prevCodeLNum = scala#GetPrevCodeLine(matchedLNum) +        if scala#MatchesIncompleteDefValr(scala#GetLine(prevCodeLNum)) +          return prevCodeLNum +        else +          return -1 +        endif +      endif +    else +      " return indent value instead +      return matchedLNum +    endif +  " There's an equal number of '{' and '}' on this line so it may be a single line function definition +  elseif bracketCount == 0 +    if a:iteration == 0 +      let otherBracketType = scala#InvertBracketType(a:openBracket, a:closedBracket) +      return scala#Testhelper(a:lnum, a:line, otherBracketType[0], otherBracketType[1], a:iteration + 1) +    else +      let prevCodeLNum = scala#GetPrevCodeLine(a:lnum) +      let prevCodeLine = scala#GetLine(prevCodeLNum) +      if scala#MatchesIncompleteDefValr(prevCodeLine) && prevCodeLine !~ '{\s*$' +        return prevCodeLNum +      else +        let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line) +        if possibleIfElse != 0 +          let defValrLine = prevnonblank(possibleIfElse - 1) +          let possibleDefValr = scala#GetLine(defValrLine) +          if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' +            return possibleDefValr +          else +            return -1 +          endif +        else +          return -1 +        endif +      endif +    endif +  else +    return -1 +  endif +endfunction + +function! scala#Test(lnum, line, openBracket, closedBracket) +  return scala#Testhelper(a:lnum, a:line, a:openBracket, a:closedBracket, 0) +endfunction + +function! scala#LineCompletesDefValr(lnum, line) +  let bracketCount = scala#CountBrackets(a:line, '{', '}') +  if bracketCount < 0 +    let matchedBracket = scala#GetLineThatMatchesBracket('{', '}') +    if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket)) +      let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1)) +      if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr) +        return 1 +      else +        return 0 +      endif +    else +      return 0 +    endif +  elseif bracketCount == 0 +    let bracketCount = scala#CountBrackets(a:line, '(', ')') +    if bracketCount < 0 +      let matchedBracket = scala#GetLineThatMatchesBracket('(', ')') +      if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket)) +        let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1)) +        if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr) +          return 1 +        else +          return 0 +        endif +      else +        return 0 +      endif +    elseif bracketCount == 0 +      let possibleDefValr = scala#GetLine(prevnonblank(a:lnum - 1)) +      if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' +        return 1 +      else +        let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line) +        if possibleIfElse != 0 +          let possibleDefValr = scala#GetLine(prevnonblank(possibleIfElse - 1)) +          if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' +            return 2 +          else +            return 0 +          endif +        else +          return 0 +        endif +      endif +    else +      return 0 +    endif +  endif +endfunction + +function! scala#SpecificLineCompletesBrackets(lnum, openBracket, closedBracket) +  let savedpos = getpos('.') +  call setpos('.', [savedpos[0], a:lnum, 9999, savedpos[3]]) +  let retv = scala#LineCompletesBrackets(a:openBracket, a:closedBracket) +  call setpos('.', savedpos) + +  return retv +endfunction + +function! scala#LineCompletesBrackets(openBracket, closedBracket) +  let savedpos = getpos('.') +  let offline = 0 +  while offline == 0 +    let [lnum, colnum] = searchpos(a:closedBracket, 'Wb') +    let [lnumA, colnumA] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn') +    if lnum != lnumA +      let [lnumB, colnumB] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbnr') +      let offline = 1 +    endif +  endwhile +  call setpos('.', savedpos) +  if lnumA == lnumB && colnumA == colnumB +    return lnumA +  else +    return -1 +  endif +endfunction + +function! GetScalaIndent() +  " Find a non-blank line above the current line. +  let prevlnum = prevnonblank(v:lnum - 1) + +  " Hit the start of the file, use zero indent. +  if prevlnum == 0 +    return 0 +  endif + +  let ind = indent(prevlnum) +  let originalIndentValue = ind +  let prevline = scala#GetLine(prevlnum) +  let curlnum = v:lnum +  let curline = scala#GetLine(curlnum) +  if get(g:, 'scala_scaladoc_indent', 0) +    let star_indent = 2 +  else +    let star_indent = 1 +  end + +  if prevline =~ '^\s*/\*\*' +    if prevline =~ '\*/\s*$' +      return ind +    else +      return ind + star_indent +    endif +  endif + +  if curline =~ '^\s*\*' +    return cindent(curlnum) +  endif + +  " If this line starts with a { then make it indent the same as the previous line +  if curline =~ '^\s*{' +    call scala#ConditionalConfirm("1") +    " Unless, of course, the previous one is a { as well +    if prevline !~ '^\s*{' +      call scala#ConditionalConfirm("2") +      return indent(prevlnum) +    endif +  endif + +  " '.' continuations +  if curline =~ '^\s*\.' +    if prevline =~ '^\s*\.' +      return ind +    else +      return ind + shiftwidth() +    endif +  endif + +  " Indent html literals +  if prevline !~ '/>\s*$' && prevline =~ '^\s*<[a-zA-Z][^>]*>\s*$' +    call scala#ConditionalConfirm("3") +    return ind + shiftwidth() +  endif + +  " assumes curly braces around try-block +  if curline =~ '^\s*}\s*\<catch\>' +    return ind - shiftwidth() +  elseif curline =~ '^\s*\<catch\>' +    return ind +  endif + +  " Add a shiftwidth()' after lines that start a block +  " If 'if', 'for' or 'while' end with ), this is a one-line block +  " If 'val', 'var', 'def' end with =, this is a one-line block +  if (prevline =~ '^\s*\<\%(\%(}\?\s*else\s\+\)\?if\|for\|while\)\>.*[)=]\s*$' && scala#NumberOfBraceGroups(prevline) <= 1) +        \ || prevline =~ '^\s*' . s:defMatcher . '.*=\s*$' +        \ || prevline =~ '^\s*\<va[lr]\>.*[=]\s*$' +        \ || prevline =~ '^\s*\%(}\s*\)\?\<else\>\s*$' +        \ || prevline =~ '=\s*$' +    call scala#ConditionalConfirm("4") +    let ind = ind + shiftwidth() +  elseif prevline =~ '^\s*\<\%(}\?\s*else\s\+\)\?if\>' && curline =~ '^\s*}\?\s*\<else\>' +    return ind +  endif + +  let lineCompletedBrackets = 0 +  let bracketCount = scala#CountBrackets(prevline, '{', '}') +  if bracketCount > 0 || prevline =~ '.*{\s*$' +    call scala#ConditionalConfirm("5b") +    let ind = ind + shiftwidth() +  elseif bracketCount < 0 +    call scala#ConditionalConfirm("6b") +    " if the closing brace actually completes the braces entirely, then we +    " have to indent to line that started the whole thing +    let completeLine = scala#LineCompletesBrackets('{', '}') +    if completeLine != -1 +      call scala#ConditionalConfirm("8b") +      let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1)) +      " However, what actually started this part looks like it was a function +      " definition, so we need to indent to that line instead.  This is +      " actually pretty weak at the moment. +      if prevCompleteLine =~ '=\s*$' +        call scala#ConditionalConfirm("9b") +        let ind = indent(prevnonblank(completeLine - 1)) +      else +        call scala#ConditionalConfirm("10b") +        let ind = indent(completeLine) +      endif +    else +      let lineCompletedBrackets = 1 +    endif +  endif + +  if ind == originalIndentValue +    let bracketCount = scala#CountBrackets(prevline, '(', ')') +    if bracketCount > 0 || prevline =~ '.*(\s*$' +      call scala#ConditionalConfirm("5a") +      let ind = ind + shiftwidth() +    elseif bracketCount < 0 +      call scala#ConditionalConfirm("6a") +      " if the closing brace actually completes the braces entirely, then we +      " have to indent to line that started the whole thing +      let completeLine = scala#LineCompletesBrackets('(', ')') +      if completeLine != -1 && prevline !~ '^.*{\s*$' +        call scala#ConditionalConfirm("8a") +        let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1)) +        " However, what actually started this part looks like it was a function +        " definition, so we need to indent to that line instead.  This is +        " actually pretty weak at the moment. +        if prevCompleteLine =~ '=\s*$' +          call scala#ConditionalConfirm("9a") +          let ind = indent(prevnonblank(completeLine - 1)) +        else +          call scala#ConditionalConfirm("10a") +          let ind = indent(completeLine) +        endif +      else +        " This is the only part that's different from from the '{', '}' one below +        " Yup... some refactoring is necessary at some point. +        let ind = ind + (bracketCount * shiftwidth()) +        let lineCompletedBrackets = 1 +      endif +    endif +  endif + +  if curline =~ '^\s*}\?\s*\<else\>\%(\s\+\<if\>\s*(.*)\)\?\s*{\?\s*$' && +   \ ! scala#LineIsCompleteIf(prevline) && +   \ prevline !~ '^.*}\s*$' +    let ind = ind - shiftwidth() +  endif + +  " Subtract a shiftwidth()' on '}' or html +  let curCurlyCount = scala#CountCurlies(curline) +  if curCurlyCount < 0 +    call scala#ConditionalConfirm("14a") +    let matchline = scala#CurlyMatcher() +    return indent(matchline) +  elseif curline =~ '^\s*</[a-zA-Z][^>]*>' +    call scala#ConditionalConfirm("14c") +    return ind - shiftwidth() +  endif + +  let prevParenCount = scala#CountParens(prevline) +  if prevline =~ '^\s*\<for\>.*$' && prevParenCount > 0 +    call scala#ConditionalConfirm("15") +    let ind = indent(prevlnum) + 5 +  endif + +  let prevCurlyCount = scala#CountCurlies(prevline) +  if prevCurlyCount == 0 && prevline =~ '^.*\%(=>\|⇒\)\s*$' && prevline !~ '^\s*this\s*:.*\%(=>\|⇒\)\s*$' && curline !~ '^\s*\<case\>' +    call scala#ConditionalConfirm("16") +    let ind = ind + shiftwidth() +  endif + +  if ind == originalIndentValue && curline =~ '^\s*\<case\>' +    call scala#ConditionalConfirm("17") +    let parentCase = scala#IsParentCase() +    if parentCase != -1 +      call scala#ConditionalConfirm("17a") +      return indent(parentCase) +    endif +  endif + +  if prevline =~ '^\s*\*/' +   \ || prevline =~ '*/\s*$' +    call scala#ConditionalConfirm("18") +    let ind = ind - star_indent +  endif + +  if scala#LineEndsInIncomplete(prevline) +    call scala#ConditionalConfirm("19") +    return ind +  endif + +  if scala#LineIsAClosingXML(prevline) +    if scala#LineCompletesXML(prevlnum, prevline) +      call scala#ConditionalConfirm("20a") +      return ind - shiftwidth() +    else +      call scala#ConditionalConfirm("20b") +      return ind +    endif +  endif + +  if ind == originalIndentValue +    "let indentMultiplier = scala#LineCompletesDefValr(prevlnum, prevline) +    "if indentMultiplier != 0 +    "  call scala#ConditionalConfirm("19a") +    "  let ind = ind - (indentMultiplier * shiftwidth()) +    let defValrLine = scala#Test(prevlnum, prevline, '{', '}') +    if defValrLine != -1 +      call scala#ConditionalConfirm("21a") +      let ind = indent(defValrLine) +    elseif lineCompletedBrackets == 0 +      call scala#ConditionalConfirm("21b") +      if scala#GetLine(prevnonblank(prevlnum - 1)) =~ '^.*\<else\>\s*\%(//.*\)\?$' +        call scala#ConditionalConfirm("21c") +        let ind = ind - shiftwidth() +      elseif scala#LineCompletesIfElse(prevlnum, prevline) +        call scala#ConditionalConfirm("21d") +        let ind = ind - shiftwidth() +      elseif scala#CountParens(curline) < 0 && curline =~ '^\s*)' && scala#GetLine(scala#GetLineThatMatchesBracket('(', ')')) =~ '.*(\s*$' +        " Handles situations that look like this: +        " +        "   val a = func( +        "     10 +        "   ) +        " +        " or +        " +        "   val a = func( +        "     10 +        "   ).somethingHere() +        call scala#ConditionalConfirm("21e") +        let ind = ind - shiftwidth() +      endif +    endif +  endif + +  call scala#ConditionalConfirm("returning " . ind) + +  return ind +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:set sw=2 sts=2 ts=8 et: +" vim600:fdm=marker fdl=1 fdc=0: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'scala') == -1  " Vim indent file diff --git a/indent/scheme.vim b/indent/scheme.vim new file mode 100644 index 00000000..cdcca5e4 --- /dev/null +++ b/indent/scheme.vim @@ -0,0 +1,15 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Scheme +" Maintainer:	Sergey Khorev <sergey.khorev@gmail.com> +" Last Change:	2005 Jun 24 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +runtime! indent/lisp.vim + +endif diff --git a/indent/scss.vim b/indent/scss.vim new file mode 100644 index 00000000..6f62e718 --- /dev/null +++ b/indent/scss.vim @@ -0,0 +1,16 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	SCSS +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2010 Jul 26 + +if exists("b:did_indent") +  finish +endif + +runtime! indent/css.vim + +" vim:set sw=2: + +endif diff --git a/indent/sdl.vim b/indent/sdl.vim new file mode 100644 index 00000000..131dce06 --- /dev/null +++ b/indent/sdl.vim @@ -0,0 +1,97 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	SDL +" Maintainer:	Michael Piefel <entwurf@piefel.de> +" Last Change:	10 December 2011 + +" Shamelessly stolen from the Vim-Script indent file + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetSDLIndent() +setlocal indentkeys+==~end,=~state,*<Return> + +" Only define the function once. +if exists("*GetSDLIndent") +"  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +function! GetSDLIndent() +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) +  let virtuality = '^\s*\(\(virtual\|redefined\|finalized\)\s\+\)\=\s*' + +  " Add a single space to comments which use asterisks +  if getline(lnum) =~ '^\s*\*' +    let ind = ind - 1 +  endif +  if getline(v:lnum) =~ '^\s*\*' +    let ind = ind + 1 +  endif + +  " Add a 'shiftwidth' after states, different blocks, decision (and alternatives), inputs +  if (getline(lnum) =~? '^\s*\(start\|state\|system\|package\|connection\|channel\|alternative\|macro\|operator\|newtype\|select\|substructure\|decision\|generator\|refinement\|service\|method\|exceptionhandler\|asntype\|syntype\|value\|(.*):\|\(priority\s\+\)\=input\|provided\)' +    \ || getline(lnum) =~? virtuality . '\(process\|procedure\|block\|object\)') +    \ && getline(lnum) !~? 'end[[:alpha:]]\+;$' +    let ind = ind + shiftwidth() +  endif + +  " Subtract a 'shiftwidth' after states +  if getline(lnum) =~? '^\s*\(stop\|return\>\|nextstate\)' +    let ind = ind - shiftwidth() +  endif + +  " Subtract a 'shiftwidth' on on end (uncompleted line) +  if getline(v:lnum) =~? '^\s*end\>' +    let ind = ind - shiftwidth() +  endif + +  " Put each alternatives where the corresponding decision was +  if getline(v:lnum) =~? '^\s*\((.*)\|else\):' +    normal k +    let ind = indent(searchpair('^\s*decision', '', '^\s*enddecision', 'bW', +      \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "sdlString"')) +  endif + +  " Put each state where the preceding state was +  if getline(v:lnum) =~? '^\s*state\>' +    let ind = indent(search('^\s*start', 'bW')) +  endif + +  " Systems and packages are always in column 0 +  if getline(v:lnum) =~? '^\s*\(\(end\)\=system\|\(end\)\=package\)' +    return 0 +  endif + +  " Put each end* where the corresponding begin was +  if getline(v:lnum) =~? '^\s*end[[:alpha:]]' +    normal k +    let partner=matchstr(getline(v:lnum), '\(' . virtuality . 'end\)\@<=[[:alpha:]]\+') +    let ind = indent(searchpair(virtuality . partner, '', '^\s*end' . partner, 'bW', +      \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "sdlString"')) +  endif + +  return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:sw=2 + +endif diff --git a/indent/sh.vim b/indent/sh.vim new file mode 100644 index 00000000..23a2d2ce --- /dev/null +++ b/indent/sh.vim @@ -0,0 +1,203 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:            Shell Script +" Maintainer:          Christian Brabandt <cb@256bit.org> +" Previous Maintainer: Peter Aronoff <telemachus@arpinum.org> +" Original Author:     Nikolai Weibull <now@bitwi.se> +" Latest Revision:     2017-08-08 +" License:             Vim (see :h license) +" Repository:          https://github.com/chrisbra/vim-sh-indent +" Changelog: +"          20170808: - better indent of line continuation +"          20170502: - get rid of buffer-shiftwidth function +"          20160912: - preserve indentation of here-doc blocks +"          20160627: - detect heredocs correctly +"          20160213: - detect function definition correctly +"          20160202: - use shiftwidth() function +"          20151215: - set b:undo_indent variable +"          20150728: - add foreach detection for zsh + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetShIndent() +setlocal indentkeys+=0=then,0=do,0=else,0=elif,0=fi,0=esac,0=done,0=end,),0=;;,0=;& +setlocal indentkeys+=0=fin,0=fil,0=fip,0=fir,0=fix +setlocal indentkeys-=:,0# +setlocal nosmartindent + +let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<' + +if exists("*GetShIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +let s:sh_indent_defaults = { +      \ 'default': function('shiftwidth'), +      \ 'continuation-line': function('shiftwidth'), +      \ 'case-labels': function('shiftwidth'), +      \ 'case-statements': function('shiftwidth'), +      \ 'case-breaks': 0 } + +function! s:indent_value(option) +  let Value = exists('b:sh_indent_options') +            \ && has_key(b:sh_indent_options, a:option) ? +            \ b:sh_indent_options[a:option] : +            \ s:sh_indent_defaults[a:option] +  if type(Value) == type(function('type')) +    return Value() +  endif +  return Value +endfunction + +function! GetShIndent() +  let lnum = prevnonblank(v:lnum - 1) +  if lnum == 0 +    return 0 +  endif + +  let pnum = prevnonblank(lnum - 1) + +  let ind = indent(lnum) +  let line = getline(lnum) +  if line =~ '^\s*\%(if\|then\|do\|else\|elif\|case\|while\|until\|for\|select\|foreach\)\>' +    if line !~ '\<\%(fi\|esac\|done\|end\)\>\s*\%(#.*\)\=$' +      let ind += s:indent_value('default') +    endif +  elseif s:is_case_label(line, pnum) +    if !s:is_case_ended(line) +      let ind += s:indent_value('case-statements') +    endif +  elseif line =~ '^\s*\<\k\+\>\s*()\s*{' || line =~ '^\s*{' || line =~ '^\s*function\s*\w\S\+\s*\%(()\)\?\s*{' +    if line !~ '}\s*\%(#.*\)\=$' +      let ind += s:indent_value('default') +    endif +  elseif s:is_continuation_line(line) +    if pnum == 0 || !s:is_continuation_line(getline(pnum)) +      let ind += s:indent_value('continuation-line') +    endif +  elseif pnum != 0 && s:is_continuation_line(getline(pnum)) +    let ind = indent(s:find_continued_lnum(pnum)) +  endif + +  let pine = line +  let line = getline(v:lnum) +  if line =~ '^\s*\%(then\|do\|else\|elif\|fi\|done\|end\)\>' || line =~ '^\s*}' +    let ind -= s:indent_value('default') +  elseif line =~ '^\s*esac\>' && s:is_case_empty(getline(v:lnum - 1)) +    let ind -= s:indent_value('default') +  elseif line =~ '^\s*esac\>' +    let ind -= (s:is_case_label(pine, lnum) && s:is_case_ended(pine) ? +             \ 0 : s:indent_value('case-statements')) + +             \ s:indent_value('case-labels') +    if s:is_case_break(pine) +      let ind += s:indent_value('case-breaks') +    endif +  elseif s:is_case_label(line, lnum) +    if s:is_case(pine) +      let ind = indent(lnum) + s:indent_value('case-labels') +    else +      let ind -= (s:is_case_label(pine, lnum) && s:is_case_ended(pine) ? +                  \ 0 : s:indent_value('case-statements')) - +                  \ s:indent_value('case-breaks') +    endif +  elseif s:is_case_break(line) +    let ind -= s:indent_value('case-breaks') +  elseif s:is_here_doc(line) +    let ind = 0 +  " statements, executed within a here document. Keep the current indent +  elseif match(map(synstack(v:lnum, 1), 'synIDattr(v:val, "name")'), '\c\mheredoc') > -1 +    return indent(v:lnum) +  endif + +  return ind +endfunction + +function! s:is_continuation_line(line) +  return a:line =~ '\%(\%(^\|[^\\]\)\\\|&&\|||\||\)' . +                 \ '\s*\({\s*\)\=\(#.*\)\=$' +endfunction + +function! s:find_continued_lnum(lnum) +  let i = a:lnum +  while i > 1 && s:is_continuation_line(getline(i - 1)) +    let i -= 1 +  endwhile +  return i +endfunction + +function! s:is_case_label(line, pnum) +  if a:line !~ '^\s*(\=.*)' +    return 0 +  endif + +  if a:pnum > 0 +    let pine = getline(a:pnum) +    if !(s:is_case(pine) || s:is_case_ended(pine)) +      return 0 +    endif +  endif + +  let suffix = substitute(a:line, '^\s*(\=', "", "") +  let nesting = 0 +  let i = 0 +  let n = strlen(suffix) +  while i < n +    let c = suffix[i] +    let i += 1 +    if c == '\\' +      let i += 1 +    elseif c == '(' +      let nesting += 1 +    elseif c == ')' +      if nesting == 0 +        return 1 +      endif +      let nesting -= 1 +    endif +  endwhile +  return 0 +endfunction + +function! s:is_case(line) +  return a:line =~ '^\s*case\>' +endfunction + +function! s:is_case_break(line) +  return a:line =~ '^\s*;[;&]' +endfunction + +function! s:is_here_doc(line) +    if a:line =~ '^\w\+$' +	let here_pat = '<<-\?'. s:escape(a:line). '\$' +	return search(here_pat, 'bnW') > 0 +    endif +    return 0 +endfunction + +function! s:is_case_ended(line) +  return s:is_case_break(a:line) || a:line =~ ';[;&]\s*\%(#.*\)\=$' +endfunction + +function! s:is_case_empty(line) +  if a:line =~ '^\s*$' || a:line =~ '^\s*#' +    return s:is_case_empty(getline(v:lnum - 1)) +  else +    return a:line =~ '^\s*case\>' +  endif +endfunction + +function! s:escape(pattern) +    return '\V'. escape(a:pattern, '\\') +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/sml.vim b/indent/sml.vim new file mode 100644 index 00000000..286daf68 --- /dev/null +++ b/indent/sml.vim @@ -0,0 +1,221 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     SML +" Maintainer:	Saikat Guha <sg266@cornell.edu> +" 				Hubert Chao <hc85@cornell.edu> +" Original OCaml Version: +" 				Jean-Francois Yuen  <jfyuen@ifrance.com> +"               Mike Leary          <leary@nwlink.com> +"               Markus Mottl        <markus@oefai.at> +" OCaml URL:    http://www.oefai.at/~markus/vim/indent/ocaml.vim +" Last Change:  2003 Jan 04	- Adapted to SML +" 				2002 Nov 06 - Some fixes (JY) +"               2002 Oct 28 - Fixed bug with indentation of ']' (MM) +"               2002 Oct 22 - Major rewrite (JY) + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal expandtab +setlocal indentexpr=GetSMLIndent() +setlocal indentkeys+=0=and,0=else,0=end,0=handle,0=if,0=in,0=let,0=then,0=val,0=fun,0=\|,0=*),0) +setlocal nolisp +setlocal nosmartindent +setlocal textwidth=80 +setlocal shiftwidth=2 + +" Comment formatting +if (has("comments")) +  set comments=sr:(*,mb:*,ex:*) +  set fo=cqort +endif + +" Only define the function once. +"if exists("*GetSMLIndent") +"finish +"endif + +" Define some patterns: +let s:beflet = '^\s*\(initializer\|method\|try\)\|\(\<\(begin\|do\|else\|in\|then\|try\)\|->\|;\)\s*$' +let s:letpat = '^\s*\(let\|type\|module\|class\|open\|exception\|val\|include\|external\)\>' +let s:letlim = '\(\<\(sig\|struct\)\|;;\)\s*$' +let s:lim = '^\s*\(exception\|external\|include\|let\|module\|open\|type\|val\)\>' +let s:module = '\<\%(let\|sig\|struct\)\>' +let s:obj = '^\s*\(constraint\|inherit\|initializer\|method\|val\)\>\|\<\(object\|object\s*(.*)\)\s*$' +let s:type = '^\s*\%(let\|type\)\>.*=' +let s:val = '^\s*\(val\|external\)\>.*:' + +" Skipping pattern, for comments +function! s:SkipPattern(lnum, pat) +  let def = prevnonblank(a:lnum - 1) +  while def > 0 && getline(def) =~ a:pat +    let def = prevnonblank(def - 1) +  endwhile +  return def +endfunction + +" Indent for ';;' to match multiple 'let' +function! s:GetInd(lnum, pat, lim) +  let llet = search(a:pat, 'bW') +  let old = indent(a:lnum) +  while llet > 0 +    let old = indent(llet) +    let nb = s:SkipPattern(llet, '^\s*(\*.*\*)\s*$') +    if getline(nb) =~ a:lim +      return old +    endif +    let llet = search(a:pat, 'bW') +  endwhile +  return old +endfunction + +" Indent pairs +function! s:FindPair(pstart, pmid, pend) +  call search(a:pend, 'bW') +"  return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) +  let lno = searchpair(a:pstart, a:pmid, a:pend, 'bW', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"') +  if lno == -1 +	return indent(lno) +  else +	return col(".") - 1 +  endif +endfunction + +function! s:FindLet(pstart, pmid, pend) +  call search(a:pend, 'bW') +"  return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) +  let lno = searchpair(a:pstart, a:pmid, a:pend, 'bW', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"') +  let moduleLine = getline(lno) +  if lno == -1 || moduleLine =~ '^\s*\(fun\|structure\|signature\)\>' +	return indent(lno) +  else +	return col(".") - 1 +  endif +endfunction + +" Indent 'let' +"function! s:FindLet(pstart, pmid, pend) +"  call search(a:pend, 'bW') +"  return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") =~ "^\\s*let\\>.*=.*\\<in\\s*$" || getline(prevnonblank(".") - 1) =~ "^\\s*let\\>.*=\\s*$\\|" . s:beflet')) +"endfunction + +function! GetSMLIndent() +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) +  let lline = getline(lnum) + +	" Return double 'shiftwidth' after lines matching: +	if lline =~ '^\s*|.*=>\s*$' +		return ind + 2 *shiftwidth() +	elseif lline =~ '^\s*val\>.*=\s*$' +		return ind + shiftwidth() +	endif + +  let line = getline(v:lnum) + +	" Indent lines starting with 'end' to matching module +	if line =~ '^\s*end\>' +		return s:FindLet(s:module, '', '\<end\>') + +	" Match 'else' with 'if' +	elseif line =~ '^\s*else\>' +	  	if lline !~ '^\s*\(if\|else\|then\)\>' +				return s:FindPair('\<if\>', '', '\<then\>') +	  	else +		  return ind +		endif + +	" Match 'then' with 'if' +	elseif line =~ '^\s*then\>' +  	if lline !~ '^\s*\(if\|else\|then\)\>' +		  return s:FindPair('\<if\>', '', '\<then\>') +	else +	  return ind +	endif + +	" Indent if current line begins with ']' +	elseif line =~ '^\s*\]' +		return s:FindPair('\[','','\]') + +  " Indent current line starting with 'in' to last matching 'let' +	elseif line =~ '^\s*in\>' +		let ind = s:FindLet('\<let\>','','\<in\>') + +	" Indent from last matching module if line matches: +	elseif line =~ '^\s*\(fun\|val\|open\|structure\|and\|datatype\|type\|exception\)\>' +		cursor(lnum,1) +  		let lastModule = indent(searchpair(s:module, '', '\<end\>', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) +		if lastModule == -1 +			return 0 +		else +			return lastModule + shiftwidth() +		endif + +	" Indent lines starting with '|' from matching 'case', 'handle' +	elseif line =~ '^\s*|' +		" cursor(lnum,1) +		let lastSwitch = search('\<\(case\|handle\|fun\|datatype\)\>','bW') +		let switchLine = getline(lastSwitch) +		let switchLineIndent = indent(lastSwitch) +		if lline =~ '^\s*|' +		  return ind +		endif +		if switchLine =~ '\<case\>' +			return col(".") + 2 +		elseif switchLine =~ '\<handle\>' +			return switchLineIndent + shiftwidth() +		elseif switchLine =~ '\<datatype\>' +			call search('=') +			return col(".") - 1 +		else +			return switchLineIndent + 2 +		endif + + +  " Indent if last line ends with 'sig', 'struct', 'let', 'then', 'else', +  " 'in' +  elseif lline =~ '\<\(sig\|struct\|let\|in\|then\|else\)\s*$' +		let ind = ind + shiftwidth() + +  " Indent if last line ends with 'of', align from 'case' +  elseif lline =~ '\<\(of\)\s*$' +		call search('\<case\>',"bW") +		let ind = col(".")+4 + +	" Indent if current line starts with 'of' +  elseif line =~ '^\s*of\>' +		call search('\<case\>',"bW") +		let ind = col(".")+1 + + +	" Indent if last line starts with 'fun', 'case', 'fn' +	elseif lline =~ '^\s*\(fun\|fn\|case\)\>' +		let ind = ind + shiftwidth() + +	endif + +	" Don't indent 'let' if last line started with 'fun', 'fn' +	if line =~ '^\s*let\>' +		if lline =~ '^\s*\(fun\|fn\)' +			let ind = ind - shiftwidth() +		endif +  endif + +  return ind + +endfunction + +" vim:sw=2 + +endif diff --git a/indent/sql.vim b/indent/sql.vim new file mode 100644 index 00000000..f7eaf3fd --- /dev/null +++ b/indent/sql.vim @@ -0,0 +1,43 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file loader +" Language:    SQL +" Maintainer:  David Fishburn <fishburn at ianywhere dot com> +" Last Change: Thu Sep 15 2005 10:27:51 AM +" Version:     1.0 +" Download:    http://vim.sourceforge.net/script.php?script_id=495 + +" Description: Checks for a: +"                  buffer local variable, +"                  global variable, +"              If the above exist, it will source the type specified. +"              If none exist, it will source the default sqlanywhere.vim file. + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif + +" Default to the standard Vim distribution file +let filename = 'sqlanywhere' + +" Check for overrides.  Buffer variables have the highest priority. +if exists("b:sql_type_override") +    " Check the runtimepath to see if the file exists +    if globpath(&runtimepath, 'indent/'.b:sql_type_override.'.vim') != '' +        let filename = b:sql_type_override +    endif +elseif exists("g:sql_type_default") +    if globpath(&runtimepath, 'indent/'.g:sql_type_default.'.vim') != '' +        let filename = g:sql_type_default +    endif +endif + +" Source the appropriate file +exec 'runtime indent/'.filename.'.vim' + + +" vim:sw=4: + +endif diff --git a/indent/sqlanywhere.vim b/indent/sqlanywhere.vim new file mode 100644 index 00000000..afcfaf14 --- /dev/null +++ b/indent/sqlanywhere.vim @@ -0,0 +1,397 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    SQL +" Maintainer:  David Fishburn <dfishburn dot vim at gmail dot com> +" Last Change: 2017 Jun 13 +" Version:     3.0 +" Download:    http://vim.sourceforge.net/script.php?script_id=495 + +" Notes: +"    Indenting keywords are based on Oracle and Sybase Adaptive Server +"    Anywhere (ASA).  Test indenting was done with ASA stored procedures and +"    fuctions and Oracle packages which contain stored procedures and +"    functions. +"    This has not been tested against Microsoft SQL Server or +"    Sybase Adaptive Server Enterprise (ASE) which use the Transact-SQL +"    syntax.  That syntax does not have end tags for IF's, which makes +"    indenting more difficult. +" +" Known Issues: +"    The Oracle MERGE statement does not have an end tag associated with +"    it, this can leave the indent hanging to the right one too many. +" +" History: +"    3.0 (Dec 2012) +"        Added cpo check +" +"    2.0 +"        Added the FOR keyword to SQLBlockStart to handle (Alec Tica): +"            for i in 1..100 loop +"              |<-- I expect to have indentation here +"            end loop; +" + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent     = 1 +let b:current_indent = "sqlanywhere" + +setlocal indentkeys-=0{ +setlocal indentkeys-=0} +setlocal indentkeys-=: +setlocal indentkeys-=0# +setlocal indentkeys-=e + +" This indicates formatting should take place when one of these +" expressions is used.  These expressions would normally be something +" you would type at the BEGINNING of a line +" SQL is generally case insensitive, so this files assumes that +" These keywords are something that would trigger an indent LEFT, not +" an indent right, since the SQLBlockStart is used for those keywords +setlocal indentkeys+==~end,=~else,=~elseif,=~elsif,0=~when,0=) + +" GetSQLIndent is executed whenever one of the expressions +" in the indentkeys is typed +setlocal indentexpr=GetSQLIndent() + +" Only define the functions once. +if exists("*GetSQLIndent") +    finish +endif +let s:keepcpo= &cpo +set cpo&vim + +" List of all the statements that start a new block. +" These are typically words that start a line. +" IS is excluded, since it is difficult to determine when the +" ending block is (especially for procedures/functions). +let s:SQLBlockStart = '^\s*\%('. +                \ 'if\|else\|elseif\|elsif\|'. +                \ 'while\|loop\|do\|for\|'. +                \ 'begin\|'. +                \ 'case\|when\|merge\|exception'. +                \ '\)\>' +let s:SQLBlockEnd = '^\s*\(end\)\>' + +" The indent level is also based on unmatched paranethesis +" If a line has an extra "(" increase the indent +" If a line has an extra ")" decrease the indent +function! s:CountUnbalancedParan( line, paran_to_check ) +    let l = a:line +    let lp = substitute(l, '[^(]', '', 'g') +    let l = a:line +    let rp = substitute(l, '[^)]', '', 'g') + +    if a:paran_to_check =~ ')' +        " echom 'CountUnbalancedParan ) returning: ' . +        " \ (strlen(rp) - strlen(lp)) +        return (strlen(rp) - strlen(lp)) +    elseif a:paran_to_check =~ '(' +        " echom 'CountUnbalancedParan ( returning: ' . +        " \ (strlen(lp) - strlen(rp)) +        return (strlen(lp) - strlen(rp)) +    else +        " echom 'CountUnbalancedParan unknown paran to check: ' . +        " \ a:paran_to_check +        return 0 +    endif +endfunction + +" Unindent commands based on previous indent level +function! s:CheckToIgnoreRightParan( prev_lnum, num_levels ) +    let lnum = a:prev_lnum +    let line = getline(lnum) +    let ends = 0 +    let num_right_paran = a:num_levels +    let ignore_paran = 0 +    let vircol = 1 + +    while num_right_paran > 0 +        silent! exec 'norm! '.lnum."G\<bar>".vircol."\<bar>" +        let right_paran = search( ')', 'W' ) +        if right_paran != lnum +            " This should not happen since there should be at least +            " num_right_paran matches for this line +            break +        endif +        let vircol      = virtcol(".") + +        " if getline(".") =~ '^)' +        let matching_paran = searchpair('(', '', ')', 'bW', +                    \ 's:IsColComment(line("."), col("."))') + +        if matching_paran < 1 +            " No match found +            " echom 'CTIRP - no match found, ignoring' +            break +        endif + +        if matching_paran == lnum +            " This was not an unmatched parantenses, start the search again +            " again after this column +            " echom 'CTIRP - same line match, ignoring' +            continue +        endif + +        " echom 'CTIRP - match: ' . line(".") . '  ' . getline(".") + +        if getline(matching_paran) =~? '\(if\|while\)\>' +            " echom 'CTIRP - if/while ignored: ' . line(".") . '  ' . getline(".") +            let ignore_paran = ignore_paran + 1 +        endif + +        " One match found, decrease and check for further matches +        let num_right_paran = num_right_paran - 1 + +    endwhile + +    " Fallback - just move back one +    " return a:prev_indent - shiftwidth() +    return ignore_paran +endfunction + +" Based on the keyword provided, loop through previous non empty +" non comment lines to find the statement that initated the keyword. +" Return its indent level +"    CASE .. +"    WHEN ... +" Should return indent level of CASE +"    EXCEPTION .. +"    WHEN ... +"         something; +"    WHEN ... +" Should return indent level of exception. +function! s:GetStmtStarterIndent( keyword, curr_lnum ) +    let lnum  = a:curr_lnum + +    " Default - reduce indent by 1 +    let ind = indent(a:curr_lnum) - shiftwidth() + +    if a:keyword =~? 'end' +        exec 'normal! ^' +        let stmts = '^\s*\%('. +                    \ '\<begin\>\|' . +                    \ '\%(\%(\<end\s\+\)\@<!\<loop\>\)\|' . +                    \ '\%(\%(\<end\s\+\)\@<!\<case\>\)\|' . +                    \ '\%(\%(\<end\s\+\)\@<!\<for\>\)\|' . +                    \ '\%(\%(\<end\s\+\)\@<!\<if\>\)'. +                    \ '\)' +        let matching_lnum = searchpair(stmts, '', '\<end\>\zs', 'bW', +                    \ 's:IsColComment(line("."), col(".")) == 1') +        exec 'normal! $' +        if matching_lnum > 0 && matching_lnum < a:curr_lnum +            let ind = indent(matching_lnum) +        endif +    elseif a:keyword =~? 'when' +        exec 'normal! ^' +        let matching_lnum = searchpair( +                    \ '\%(\<end\s\+\)\@<!\<case\>\|\<exception\>\|\<merge\>', +                    \ '', +                    \ '\%(\%(\<when\s\+others\>\)\|\%(\<end\s\+case\>\)\)', +                    \ 'bW', +                    \ 's:IsColComment(line("."), col(".")) == 1') +        exec 'normal! $' +        if matching_lnum > 0 && matching_lnum < a:curr_lnum +            let ind = indent(matching_lnum) +        else +            let ind = indent(a:curr_lnum) +        endif +    endif + +    return ind +endfunction + + +" Check if the line is a comment +function! s:IsLineComment(lnum) +    let rc = synIDattr( +                \ synID(a:lnum, +                \     match(getline(a:lnum), '\S')+1, 0) +                \ , "name") +                \ =~? "comment" + +    return rc +endfunction + + +" Check if the column is a comment +function! s:IsColComment(lnum, cnum) +    let rc = synIDattr(synID(a:lnum, a:cnum, 0), "name") +                \           =~? "comment" + +    return rc +endfunction + + +" Instead of returning a column position, return +" an appropriate value as a factor of shiftwidth. +function! s:ModuloIndent(ind) +    let ind = a:ind + +    if ind > 0 +        let modulo = ind % shiftwidth() + +        if modulo > 0 +            let ind = ind - modulo +        endif +    endif + +    return ind +endfunction + + +" Find correct indent of a new line based upon the previous line +function! GetSQLIndent() +    let lnum = v:lnum +    let ind = indent(lnum) + +    " If the current line is a comment, leave the indent as is +    " Comment out this additional check since it affects the +    " indenting of =, and will not reindent comments as it should +    " if s:IsLineComment(lnum) == 1 +    "     return ind +    " endif + +    " Get previous non-blank line +    let prevlnum = prevnonblank(lnum - 1) +    if prevlnum <= 0 +        return ind +    endif + +    if s:IsLineComment(prevlnum) == 1 +        if getline(v:lnum) =~ '^\s*\*' +            let ind = s:ModuloIndent(indent(prevlnum)) +            return ind + 1 +        endif +        " If the previous line is a comment, then return -1 +        " to tell Vim to use the formatoptions setting to determine +        " the indent to use +        " But only if the next line is blank.  This would be true if +        " the user is typing, but it would not be true if the user +        " is reindenting the file +        if getline(v:lnum) =~ '^\s*$' +            return -1 +        endif +    endif + +    " echom 'PREVIOUS INDENT: ' . indent(prevlnum) . '  LINE: ' . getline(prevlnum) + +    " This is the line you just hit return on, it is not the current line +    " which is new and empty +    " Based on this line, we can determine how much to indent the new +    " line + +    " Get default indent (from prev. line) +    let ind      = indent(prevlnum) +    let prevline = getline(prevlnum) + +    " Now check what's on the previous line to determine if the indent +    " should be changed, for example IF, BEGIN, should increase the indent +    " where END IF, END, should decrease the indent. +    if prevline =~? s:SQLBlockStart +        " Move indent in +        let ind = ind + shiftwidth() +        " echom 'prevl - SQLBlockStart - indent ' . ind . '  line: ' . prevline +    elseif prevline =~ '[()]' +        if prevline =~ '(' +            let num_unmatched_left = s:CountUnbalancedParan( prevline, '(' ) +        else +            let num_unmatched_left = 0 +        endif +        if prevline =~ ')' +            let num_unmatched_right  = s:CountUnbalancedParan( prevline, ')' ) +        else +            let num_unmatched_right  = 0 +            " let num_unmatched_right  = s:CountUnbalancedParan( prevline, ')' ) +        endif +        if num_unmatched_left > 0 +            " There is a open left paranethesis +            " increase indent +            let ind = ind + ( shiftwidth() * num_unmatched_left ) +        elseif num_unmatched_right > 0 +            " if it is an unbalanced paranethesis only unindent if +            " it was part of a command (ie create table(..)  ) +            " instead of part of an if (ie if (....) then) which should +            " maintain the indent level +            let ignore = s:CheckToIgnoreRightParan( prevlnum, num_unmatched_right ) +            " echom 'prevl - ) unbalanced - CTIRP - ignore: ' . ignore + +            if prevline =~ '^\s*)' +                let ignore = ignore + 1 +                " echom 'prevl - begins ) unbalanced ignore: ' . ignore +            endif + +            if (num_unmatched_right - ignore) > 0 +                let ind = ind - ( shiftwidth() * (num_unmatched_right - ignore) ) +            endif + +        endif +    endif + + +    " echom 'CURRENT INDENT: ' . ind . '  LINE: '  . getline(v:lnum) + +    " This is a new blank line since we just typed a carriage return +    " Check current line; search for simplistic matching start-of-block +    let line = getline(v:lnum) + +    if line =~? '^\s*els' +        " Any line when you type else will automatically back up one +        " ident level  (ie else, elseif, elsif) +        let ind = ind - shiftwidth() +        " echom 'curr - else - indent ' . ind +    elseif line =~? '^\s*end\>' +        let ind = s:GetStmtStarterIndent('end', v:lnum) +        " General case for end +        " let ind = ind - shiftwidth() +        " echom 'curr - end - indent ' . ind +    elseif line =~? '^\s*when\>' +        let ind = s:GetStmtStarterIndent('when', v:lnum) +        " If the WHEN clause is used with a MERGE or EXCEPTION +        " clause, do not change the indent level, since these +        " statements do not have a corresponding END statement. +        " if stmt_starter =~? 'case' +        "    let ind = ind - shiftwidth() +        " endif +        " elseif line =~ '^\s*)\s*;\?\s*$' +        " elseif line =~ '^\s*)' +    elseif line =~ '^\s*)' +        let num_unmatched_right  = s:CountUnbalancedParan( line, ')' ) +        let ignore = s:CheckToIgnoreRightParan( v:lnum, num_unmatched_right ) +        " If the line ends in a ), then reduce the indent +        " This catches items like: +        " CREATE TABLE T1( +        "    c1 int, +        "    c2 int +        "    ); +        " But we do not want to unindent a line like: +        " IF ( c1 = 1 +        " AND  c2 = 3 ) THEN +        " let num_unmatched_right  = s:CountUnbalancedParan( line, ')' ) +        " if num_unmatched_right > 0 +        " elseif strpart( line, strlen(line)-1, 1 ) =~ ')' +        " let ind = ind - shiftwidth() +        if line =~ '^\s*)' +            " let ignore = ignore + 1 +            " echom 'curr - begins ) unbalanced ignore: ' . ignore +        endif + +        if (num_unmatched_right - ignore) > 0 +            let ind = ind - ( shiftwidth() * (num_unmatched_right - ignore) ) +        endif +        " endif +    endif + +    " echom 'final - indent ' . ind +    return s:ModuloIndent(ind) +endfunction + +"  Restore: +let &cpo= s:keepcpo +unlet s:keepcpo +" vim: ts=4 fdm=marker sw=4 + +endif diff --git a/indent/systemd.vim b/indent/systemd.vim new file mode 100644 index 00000000..b8fad530 --- /dev/null +++ b/indent/systemd.vim @@ -0,0 +1,14 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:  systemd.unit(5) + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Looks a lot like dosini files. +runtime! indent/dosini.vim + +endif diff --git a/indent/systemverilog.vim b/indent/systemverilog.vim new file mode 100644 index 00000000..3d791762 --- /dev/null +++ b/indent/systemverilog.vim @@ -0,0 +1,234 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    SystemVerilog +" Maintainer:  kocha <kocha.lsifrontend@gmail.com> +" Last Change: 12-Aug-2013.  + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=SystemVerilogIndent() +setlocal indentkeys=!^F,o,O,0),0},=begin,=end,=join,=endcase,=join_any,=join_none +setlocal indentkeys+==endmodule,=endfunction,=endtask,=endspecify +setlocal indentkeys+==endclass,=endpackage,=endsequence,=endclocking +setlocal indentkeys+==endinterface,=endgroup,=endprogram,=endproperty,=endchecker +setlocal indentkeys+==`else,=`endif + +" Only define the function once. +if exists("*SystemVerilogIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +function SystemVerilogIndent() + +  if exists('b:systemverilog_indent_width') +    let offset = b:systemverilog_indent_width +  else +    let offset = shiftwidth() +  endif +  if exists('b:systemverilog_indent_modules') +    let indent_modules = offset +  else +    let indent_modules = 0 +  endif + +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let lnum2 = prevnonblank(lnum - 1) +  let curr_line  = getline(v:lnum) +  let last_line  = getline(lnum) +  let last_line2 = getline(lnum2) +  let ind  = indent(lnum) +  let ind2 = indent(lnum - 1) +  let offset_comment1 = 1 +  " Define the condition of an open statement +  "   Exclude the match of //, /* or */ +  let sv_openstat = '\(\<or\>\|\([*/]\)\@<![*(,{><+-/%^&|!=?:]\([*/]\)\@!\)' +  " Define the condition when the statement ends with a one-line comment +  let sv_comment = '\(//.*\|/\*.*\*/\s*\)' +  if exists('b:verilog_indent_verbose') +    let vverb_str = 'INDENT VERBOSE:' +    let vverb = 1 +  else +    let vverb = 0 +  endif + +  " Indent accoding to last line +  " End of multiple-line comment +  if last_line =~ '\*/\s*$' && last_line !~ '/\*.\{-}\*/' +    let ind = ind - offset_comment1 +    if vverb +      echo vverb_str "De-indent after a multiple-line comment." +    endif + +  " Indent after if/else/for/case/always/initial/specify/fork blocks +  elseif last_line =~ '`\@<!\<\(if\|else\)\>' || +    \ last_line =~ '^\s*\<\(for\|case\%[[zx]]\|do\|foreach\|randcase\)\>' || +    \ last_line =~ '^\s*\<\(always\|always_comb\|always_ff\|always_latch\)\>' || +    \ last_line =~ '^\s*\<\(initial\|specify\|fork\|final\)\>' +    if last_line !~ '\(;\|\<end\>\)\s*' . sv_comment . '*$' || +      \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$' +      let ind = ind + offset +      if vverb | echo vverb_str "Indent after a block statement." | endif +    endif +  " Indent after function/task/class/package/sequence/clocking/ +  " interface/covergroup/property/checkerprogram blocks +  elseif last_line =~ '^\s*\<\(function\|task\|class\|package\)\>' || +    \ last_line =~ '^\s*\<\(sequence\|clocking\|interface\)\>' || +    \ last_line =~ '^\s*\(\w\+\s*:\)\=\s*\<covergroup\>' || +    \ last_line =~ '^\s*\<\(property\|checker\|program\)\>' +    if last_line !~ '\<end\>\s*' . sv_comment . '*$' || +      \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$' +      let ind = ind + offset +      if vverb +	echo vverb_str "Indent after function/task/class block statement." +      endif +    endif + +  " Indent after module/function/task/specify/fork blocks +  elseif last_line =~ '^\s*\(\<extern\>\s*\)\=\<module\>' +    let ind = ind + indent_modules +    if vverb && indent_modules +      echo vverb_str "Indent after module statement." +    endif +    if last_line =~ '[(,]\s*' . sv_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*[(,]\s*' . sv_comment . '*$' +      let ind = ind + offset +      if vverb +	echo vverb_str "Indent after a multiple-line module statement." +      endif +    endif + +  " Indent after a 'begin' statement +  elseif last_line =~ '\(\<begin\>\)\(\s*:\s*\w\+\)*' . sv_comment . '*$' && +    \ last_line !~ '\(//\|/\*\).*\(\<begin\>\)' && +    \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' || +    \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' ) +    let ind = ind + offset +    if vverb | echo vverb_str "Indent after begin statement." | endif + +  " Indent after a '{' or a '(' +  elseif last_line =~ '[{(]' . sv_comment . '*$' && +    \ last_line !~ '\(//\|/\*\).*[{(]' && +    \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' || +    \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' ) +    let ind = ind + offset +    if vverb | echo vverb_str "Indent after begin statement." | endif + +  " De-indent for the end of one-line block +  elseif ( last_line !~ '\<begin\>' || +    \ last_line =~ '\(//\|/\*\).*\<begin\>' ) && +    \ last_line2 =~ '\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|final\)\>.*' . +      \ sv_comment . '*$' && +    \ last_line2 !~ '\(//\|/\*\).*\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|final\)\>' && +    \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' && +    \ ( last_line2 !~ '\<begin\>' || +    \ last_line2 =~ '\(//\|/\*\).*\<begin\>' ) +    let ind = ind - offset +    if vverb +      echo vverb_str "De-indent after the end of one-line statement." +    endif + +    " Multiple-line statement (including case statement) +    " Open statement +    "   Ident the first open line +    elseif  last_line =~ sv_openstat . '\s*' . sv_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*' . sv_openstat . '\s*$' && +      \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' +      let ind = ind + offset +      if vverb | echo vverb_str "Indent after an open statement." | endif + +    " Close statement +    "   De-indent for an optional close parenthesis and a semicolon, and only +    "   if there exists precedent non-whitespace char +    elseif last_line =~ ')*\s*;\s*' . sv_comment . '*$' && +      \ last_line !~ '^\s*)*\s*;\s*' . sv_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*\S)*\s*;\s*' . sv_comment . '*$' && +      \ ( last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' && +      \ last_line2 !~ ';\s*//.*$') && +      \ last_line2 !~ '^\s*' . sv_comment . '$' +      let ind = ind - offset +      if vverb | echo vverb_str "De-indent after a close statement." | endif + +  " `ifdef and `else +  elseif last_line =~ '^\s*`\<\(ifdef\|else\)\>' +    let ind = ind + offset +    if vverb +      echo vverb_str "Indent after a `ifdef or `else statement." +    endif + +  endif + +  " Re-indent current line + +  " De-indent on the end of the block +  " join/end/endcase/endfunction/endtask/endspecify +  if curr_line =~ '^\s*\<\(join\|join_any\|join_none\|\|end\|endcase\|while\)\>' || +      \ curr_line =~ '^\s*\<\(endfunction\|endtask\|endspecify\|endclass\)\>' || +      \ curr_line =~ '^\s*\<\(endpackage\|endsequence\|endclocking\|endinterface\)\>' || +      \ curr_line =~ '^\s*\<\(endgroup\|endproperty\|endchecker\|endprogram\)\>' || +      \ curr_line =~ '^\s*}' +    let ind = ind - offset +    if vverb | echo vverb_str "De-indent the end of a block." | endif +  elseif curr_line =~ '^\s*\<endmodule\>' +    let ind = ind - indent_modules +    if vverb && indent_modules +      echo vverb_str "De-indent the end of a module." +    endif + +  " De-indent on a stand-alone 'begin' +  elseif curr_line =~ '^\s*\<begin\>' +    if last_line !~ '^\s*\<\(function\|task\|specify\|module\|class\|package\)\>' || +      \ last_line !~ '^\s*\<\(sequence\|clocking\|interface\|covergroup\)\>' || +      \ last_line !~ '^\s*\<\(property\|checker\|program\)\>' && +      \ last_line !~ '^\s*\()*\s*;\|)\+\)\s*' . sv_comment . '*$' && +      \ ( last_line =~ +      \ '\<\(`\@<!if\|`\@<!else\|for\|case\%[[zx]]\|always\|initial\|do\|foreach\|randcase\|final\)\>' || +      \ last_line =~ ')\s*' . sv_comment . '*$' || +      \ last_line =~ sv_openstat . '\s*' . sv_comment . '*$' ) +      let ind = ind - offset +      if vverb +	echo vverb_str "De-indent a stand alone begin statement." +      endif +    endif + +  " De-indent after the end of multiple-line statement +  elseif curr_line =~ '^\s*)' && +    \ ( last_line =~ sv_openstat . '\s*' . sv_comment . '*$' || +    \ last_line !~ sv_openstat . '\s*' . sv_comment . '*$' && +    \ last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' ) +    let ind = ind - offset +    if vverb +      echo vverb_str "De-indent the end of a multiple statement." +    endif + +  " De-indent `else and `endif +  elseif curr_line =~ '^\s*`\<\(else\|endif\)\>' +    let ind = ind - offset +    if vverb | echo vverb_str "De-indent `else and `endif statement." | endif + +  endif + +  " Return the indention +  return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:sw=2 + +endif diff --git a/indent/tcl.vim b/indent/tcl.vim new file mode 100644 index 00000000..7641e144 --- /dev/null +++ b/indent/tcl.vim @@ -0,0 +1,79 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	    Tcl +" Maintainer:	    Nikolai Weibull <now@bitwi.se> +" Latest Revision:  2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetTclIndent() +setlocal indentkeys=0{,0},!^F,o,O,0] +setlocal nosmartindent + +if exists("*GetTclIndent") +  finish +endif + +function s:prevnonblanknoncomment(lnum) +  let lnum = prevnonblank(a:lnum) +  while lnum > 0 +    let line = getline(lnum) +    if line !~ '^\s*\(#\|$\)' +      break +    endif +    let lnum = prevnonblank(lnum - 1) +  endwhile +  return lnum +endfunction + +function s:count_braces(lnum, count_open) +  let n_open = 0 +  let n_close = 0 +  let line = getline(a:lnum) +  let pattern = '[{}]' +  let i = match(line, pattern) +  while i != -1 +    if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'tcl\%(Comment\|String\)' +      if line[i] == '{' +        let n_open += 1 +      elseif line[i] == '}' +        if n_open > 0 +          let n_open -= 1 +        else +          let n_close += 1 +        endif +      endif +    endif +    let i = match(line, pattern, i + 1) +  endwhile +  return a:count_open ? n_open : n_close +endfunction + +function GetTclIndent() +  let line = getline(v:lnum) +  if line =~ '^\s*\*' +    return cindent(v:lnum) +  elseif line =~ '^\s*}' +    return indent(v:lnum) - shiftwidth() +  endif + +  let pnum = s:prevnonblanknoncomment(v:lnum - 1) +  if pnum == 0 +    return 0 +  endif + +  let ind = indent(pnum) + s:count_braces(pnum, 1) * shiftwidth() + +  let pline = getline(pnum) +  if pline =~ '}\s*$' +    let ind -= (s:count_braces(pnum, 0) - (pline =~ '^\s*}' ? 1 : 0)) * shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/tcsh.vim b/indent/tcsh.vim new file mode 100644 index 00000000..43d19a1e --- /dev/null +++ b/indent/tcsh.vim @@ -0,0 +1,53 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:		C-shell (tcsh) +" Maintainer:		GI <a@b.c>, where a='gi1242+vim', b='gmail', c='com' +" Last Modified:	Sat 10 Dec 2011 09:23:00 AM EST + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif + +let b:did_indent = 1 + +setlocal indentexpr=TcshGetIndent() +setlocal indentkeys+=e,0=end,0=endsw indentkeys-=0{,0},0),:,0# + +" Only define the function once. +if exists("*TcshGetIndent") +    finish +endif + +function TcshGetIndent() +    " Find a non-blank line above the current line. +    let lnum = prevnonblank(v:lnum - 1) + +    " Hit the start of the file, use zero indent. +    if lnum == 0 +	return 0 +    endif + +    " Add indent if previous line begins with while or foreach +    " OR line ends with case <str>:, default:, else, then or \ +    let ind = indent(lnum) +    let line = getline(lnum) +    if line =~ '\v^\s*%(while|foreach)>|^\s*%(case\s.*:|default:|else)\s*$|%(<then|\\)$' +	let ind = ind + shiftwidth() +    endif + +    if line =~ '\v^\s*breaksw>' +	let ind = ind - shiftwidth() +    endif + +    " Subtract indent if current line has on end, endif, case commands +    let line = getline(v:lnum) +    if line =~ '\v^\s*%(else|end|endif)\s*$' +	let ind = ind - shiftwidth() +    endif + +    return ind +endfunction + +endif diff --git a/indent/teraterm.vim b/indent/teraterm.vim new file mode 100644 index 00000000..5aff4012 --- /dev/null +++ b/indent/teraterm.vim @@ -0,0 +1,59 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Tera Term Language (TTL) +"		Based on Tera Term Version 4.92 +" Maintainer:	Ken Takata +" URL:		https://github.com/k-takata/vim-teraterm +" Last Change:	2017 Jun 13 +" Filenames:	*.ttl +" License:	VIM License + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal nosmartindent +setlocal noautoindent +setlocal indentexpr=GetTeraTermIndent(v:lnum) +setlocal indentkeys=!^F,o,O,e +setlocal indentkeys+==elseif,=endif,=loop,=next,=enduntil,=endwhile + +if exists("*GetTeraTermIndent") +  finish +endif + +function! GetTeraTermIndent(lnum) +  let l:prevlnum = prevnonblank(a:lnum-1) +  if l:prevlnum == 0 +    " top of file +    return 0 +  endif + +  " grab the previous and current line, stripping comments. +  let l:prevl = substitute(getline(l:prevlnum), ';.*$', '', '') +  let l:thisl = substitute(getline(a:lnum), ';.*$', '', '') +  let l:previ = indent(l:prevlnum) + +  let l:ind = l:previ + +  if l:prevl =~ '^\s*if\>.*\<then\>' +    " previous line opened a block +    let l:ind += shiftwidth() +  endif +  if l:prevl =~ '^\s*\%(elseif\|else\|do\|until\|while\|for\)\>' +    " previous line opened a block +    let l:ind += shiftwidth() +  endif +  if l:thisl =~ '^\s*\%(elseif\|else\|endif\|enduntil\|endwhile\|loop\|next\)\>' +    " this line closed a block +    let l:ind -= shiftwidth() +  endif + +  return l:ind +endfunction + +" vim: ts=8 sw=2 sts=2 + +endif diff --git a/indent/tex.vim b/indent/tex.vim index 14af7b28..ca1d0a5a 100644 --- a/indent/tex.vim +++ b/indent/tex.vim @@ -1,3 +1,424 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     LaTeX +" Maintainer:   Yichao Zhou <broken.zhou AT gmail.com> +" Created:      Sat, 16 Feb 2002 16:50:19 +0100 +" Version: 0.9.4 +"   Please email me if you found something I can do.  Comments, bug report and +"   feature request are welcome. + +" Last Update:  {{{ +"               25th Sep 2002, by LH : +"               (*) better support for the option +"               (*) use some regex instead of several '||'. +"               Oct 9th, 2003, by JT: +"               (*) don't change indentation of lines starting with '%' +"               2005/06/15, Moshe Kaminsky <kaminsky AT math.huji.ac.il> +"               (*) New variables: +"                   g:tex_items, g:tex_itemize_env, g:tex_noindent_env +"               2011/3/6, by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Don't change indentation of lines starting with '%' +"                   I don't see any code with '%' and it doesn't work properly +"                   so I add some code. +"               (*) New features: Add smartindent-like indent for "{}" and  "[]". +"               (*) New variables: g:tex_indent_brace +"               2011/9/25, by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Bug fix: smartindent-like indent for "[]" +"               (*) New features: Align with "&". +"               (*) New variable: g:tex_indent_and. +"               2011/10/23 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Bug fix: improve the smartindent-like indent for "{}" and +"               "[]". +"               2012/02/27 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Bug fix: support default folding marker. +"               (*) Indent with "&" is not very handy.  Make it not enable by +"               default. +"               2012/03/06 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Modify "&" behavior and make it default again.  Now "&" +"               won't align when there are more then one "&" in the previous +"               line. +"               (*) Add indent "\left(" and "\right)" +"               (*) Trust user when in "verbatim" and "lstlisting" +"               2012/03/11 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Modify "&" so that only indent when current line start with +"                   "&". +"               2012/03/12 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Modify indentkeys. +"               2012/03/18 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Add &cpo +"               2013/05/02 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Fix problem about GetTeXIndent checker. Thank Albert Netymk +"                   for reporting this. +"               2014/06/23 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Remove the feature g:tex_indent_and because it is buggy. +"               (*) If there is not any obvious indentation hints, we do not +"                   alert our user's current indentation. +"               (*) g:tex_indent_brace now only works if the open brace is the +"                   last character of that line. +"               2014/08/03 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Indent current line if last line has larger indentation +"               2016/11/08 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Fix problems for \[ and \].  Thanks Bruno for reporting. +"               2017/04/30 by Yichao Zhou <broken.zhou AT gmail.com> +"               (*) Fix a bug between g:tex_noindent_env and g:tex_indent_items +"                   Now g:tex_noindent_env='document\|verbatim\|itemize' (Emacs +"                   style) is supported.  Thanks Miles Wheeler for reporting. +" +" }}} + +" Document: {{{ +" +" To set the following options (ok, currently it's just one), add a line like +"   let g:tex_indent_items = 1 +" to your ~/.vimrc. +" +" * g:tex_indent_brace +" +"   If this variable is unset or non-zero, it will use smartindent-like style +"   for "{}" and "[]".  Now this only works if the open brace is the last +"   character of that line. +" +"         % Example 1 +"         \usetikzlibrary{ +"           external +"         } +" +"         % Example 2 +"         \tikzexternalize[ +"           prefix=tikz] +" +" * g:tex_indent_items +" +"   If this variable is set, item-environments are indented like Emacs does +"   it, i.e., continuation lines are indented with a shiftwidth. +" +"   NOTE: I've already set the variable below; delete the corresponding line +"   if you don't like this behaviour. +" +"   Per default, it is unset. +" +"              set                                unset +"   ---------------------------------------------------------------- +"       \begin{itemize}                      \begin{itemize} +"         \item blablabla                      \item blablabla +"           bla bla bla                        bla bla bla +"         \item blablabla                      \item blablabla +"           bla bla bla                        bla bla bla +"       \end{itemize}                        \end{itemize} +" +" +" * g:tex_items +" +"   A list of tokens to be considered as commands for the beginning of an item +"   command. The tokens should be separated with '\|'. The initial '\' should +"   be escaped. The default is '\\bibitem\|\\item'. +" +" * g:tex_itemize_env +" +"   A list of environment names, separated with '\|', where the items (item +"   commands matching g:tex_items) may appear. The default is +"   'itemize\|description\|enumerate\|thebibliography'. +" +" * g:tex_noindent_env +" +"   A list of environment names. separated with '\|', where no indentation is +"   required. The default is 'document\|verbatim'. +" }}} + +" Only define the function once +if exists("b:did_indent") +    finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Define global variable {{{ + +let b:did_indent = 1 + +if !exists("g:tex_indent_items") +    let g:tex_indent_items = 1 +endif +if !exists("g:tex_indent_brace") +    let g:tex_indent_brace = 1 +endif +if !exists("g:tex_max_scan_line") +    let g:tex_max_scan_line = 60 +endif +if g:tex_indent_items +    if !exists("g:tex_itemize_env") +        let g:tex_itemize_env = 'itemize\|description\|enumerate\|thebibliography' +    endif +    if !exists('g:tex_items') +        let g:tex_items = '\\bibitem\|\\item' +    endif +else +    let g:tex_items = '' +endif + +if !exists("g:tex_noindent_env") +    let g:tex_noindent_env = 'document\|verbatim\|lstlisting' +endif "}}} + +" VIM Setting " {{{ +setlocal autoindent +setlocal nosmartindent +setlocal indentexpr=GetTeXIndent() +setlocal indentkeys& +exec 'setlocal indentkeys+=[,(,{,),},],\&' . substitute(g:tex_items, '^\|\(\\|\)', ',=', 'g') +let g:tex_items = '^\s*' . substitute(g:tex_items, '^\(\^\\s\*\)*', '', '') +" }}} + +function! GetTeXIndent() " {{{ +    " Find a non-blank line above the current line. +    let lnum = prevnonblank(v:lnum - 1) +    let cnum = v:lnum + +    " Comment line is not what we need. +    while lnum != 0 && getline(lnum) =~ '^\s*%' +        let lnum = prevnonblank(lnum - 1) +    endwhile + +    " At the start of the file use zero indent. +    if lnum == 0 +        return 0 +    endif + +    let line = substitute(getline(lnum), '\s*%.*', '','g')     " last line +    let cline = substitute(getline(v:lnum), '\s*%.*', '', 'g') " current line + +    "  We are in verbatim, so do what our user what. +    if synIDattr(synID(v:lnum, indent(v:lnum), 1), "name") == "texZone" +        if empty(cline) +            return indent(lnum) +        else +            return indent(v:lnum) +        end +    endif + +    if lnum == 0 +        return 0 +    endif + +    let ind = indent(lnum) +    let stay = 1 + +    " New code for comment: retain the indent of current line +    if cline =~ '^\s*%' +        return indent(v:lnum) +    endif + +    " Add a 'shiftwidth' after beginning of environments. +    " Don't add it for \begin{document} and \begin{verbatim} +    " if line =~ '^\s*\\begin{\(.*\)}'  && line !~ 'verbatim' +    " LH modification : \begin does not always start a line +    " ZYC modification : \end after \begin won't cause wrong indent anymore +    if line =~ '\\begin{.*}'  +        if line !~ g:tex_noindent_env +            let ind = ind + shiftwidth() +            let stay = 0 +        endif + +        if g:tex_indent_items +            " Add another sw for item-environments +            if line =~ g:tex_itemize_env +                let ind = ind + shiftwidth() +                let stay = 0 +            endif +        endif +    endif + +    if cline =~ '\\end{.*}' +        let retn = s:GetEndIndentation(v:lnum) +        if retn != -1 +            return retn +        endif +    end +    " Subtract a 'shiftwidth' when an environment ends +    if cline =~ '\\end{.*}' +                \ && cline !~ g:tex_noindent_env +                \ && cline !~ '\\begin{.*}.*\\end{.*}' +        if g:tex_indent_items +            " Remove another sw for item-environments +            if cline =~ g:tex_itemize_env +                let ind = ind - shiftwidth() +                let stay = 0 +            endif +        endif + +        let ind = ind - shiftwidth() +        let stay = 0 +    endif + +    if g:tex_indent_brace +        if line =~ '[[{]$' +            let ind += shiftwidth() +            let stay = 0 +        endif + +        if cline =~ '^\s*\\\?[\]}]' && s:CheckPairedIsLastCharacter(v:lnum, indent(v:lnum)) +            let ind -= shiftwidth() +            let stay = 0 +        endif + +        if line !~ '^\s*\\\?[\]}]' +            for i in range(indent(lnum)+1, strlen(line)-1) +                let char = line[i] +                if char == ']' || char == '}' +                    if s:CheckPairedIsLastCharacter(lnum, i) +                        let ind -= shiftwidth() +                        let stay = 0 +                    endif +                endif +            endfor +        endif +    endif + +    " Special treatment for 'item' +    " ---------------------------- + +    if g:tex_indent_items +        " '\item' or '\bibitem' itself: +        if cline =~ g:tex_items +            let ind = ind - shiftwidth() +            let stay = 0 +        endif +        " lines following to '\item' are intented once again: +        if line =~ g:tex_items +            let ind = ind + shiftwidth() +            let stay = 0 +        endif +    endif + +    if stay +        " If there is no obvious indentation hint, we trust our user. +        if empty(cline) +            return ind +        else +            return max([indent(v:lnum), s:GetLastBeginIndentation(v:lnum)]) +        endif +    else +        return ind +    endif +endfunction "}}} + +function! s:GetLastBeginIndentation(lnum) " {{{ +    let matchend = 1 +    for lnum in range(a:lnum-1, max([a:lnum - g:tex_max_scan_line, 1]), -1) +        let line = getline(lnum) +        if line =~ '\\end{.*}' +            let matchend += 1 +        endif +        if line =~ '\\begin{.*}' +            let matchend -= 1 +        endif +        if matchend == 0 +            if line =~ g:tex_noindent_env +                return indent(lnum) +            endif +            if line =~ g:tex_itemize_env +                return indent(lnum) + 2 * shiftwidth() +            endif +            return indent(lnum) + shiftwidth() +        endif +    endfor +    return -1 +endfunction + +function! s:GetEndIndentation(lnum) " {{{ +    if getline(a:lnum) =~ '\\begin{.*}.*\\end{.*}' +        return -1 +    endif + +    let min_indent = 100 +    let matchend = 1 +    for lnum in range(a:lnum-1, max([a:lnum-g:tex_max_scan_line, 1]), -1) +        let line = getline(lnum) +        if line =~ '\\end{.*}' +            let matchend += 1 +        endif +        if line =~ '\\begin{.*}' +            let matchend -= 1 +        endif +        if matchend == 0 +            return indent(lnum) +        endif +        if !empty(line) +            let min_indent = min([min_indent, indent(lnum)]) +        endif +    endfor +    return min_indent - shiftwidth() +endfunction + +" Most of the code is from matchparen.vim +function! s:CheckPairedIsLastCharacter(lnum, col) "{{{ +    let c_lnum = a:lnum +    let c_col = a:col+1 + +    let line = getline(c_lnum) +    if line[c_col-1] == '\' +        let c_col = c_col + 1 +    endif +    let c = line[c_col-1] + +    let plist = split(&matchpairs, '.\zs[:,]') +    let i = index(plist, c) +    if i < 0 +        return 0 +    endif + +    " Figure out the arguments for searchpairpos(). +    if i % 2 == 0 +        let s_flags = 'nW' +        let c2 = plist[i + 1] +    else +        let s_flags = 'nbW' +        let c2 = c +        let c = plist[i - 1] +    endif +    if c == '[' +        let c = '\[' +        let c2 = '\]' +    endif + +    " Find the match.  When it was just before the cursor move it there for a +    " moment. +    let save_cursor = winsaveview() +    call cursor(c_lnum, c_col) + +    " When not in a string or comment ignore matches inside them. +    " We match "escape" for special items, such as lispEscapeSpecial. +    let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' . +                \ '=~?  "string\\|character\\|singlequote\\|escape\\|comment"' +    execute 'if' s_skip '| let s_skip = 0 | endif' + +    let stopline = max([0, c_lnum - g:tex_max_scan_line]) + +    " Limit the search time to 300 msec to avoid a hang on very long lines. +    " This fails when a timeout is not supported. +    try +        let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 100) +    catch /E118/ +    endtry + +    call winrestview(save_cursor) + +    if m_lnum > 0 +        let line = getline(m_lnum) +        return strlen(line) == m_col +    endif + +    return 0 +endfunction "}}} + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: set sw=4 textwidth=80: + +endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1  " LaTeX indent file (part of LaTeX Box) diff --git a/indent/tf.vim b/indent/tf.vim new file mode 100644 index 00000000..69bd783f --- /dev/null +++ b/indent/tf.vim @@ -0,0 +1,76 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:     tf (TinyFugue) +" Maintainer:   Christian J. Robinson <heptite@gmail.com> +" URL:          http://www.vim.org/scripts/script.php?script_id=174 +" Last Change:  2017 Feb 25  + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetTFIndent() +setlocal indentkeys-=0{,0} indentkeys-=0# indentkeys-=: +setlocal indentkeys+==/endif,=/then,=/else,=/done,0; + +" Only define the function once: +if exists("*GetTFIndent") +  finish +endif + +function GetTFIndent() +	" Find a non-blank line above the current line: +	let lnum = prevnonblank(v:lnum - 1) + +	" No indent for the start of the file: +	if lnum == 0 +		return 0 +	endif + +	let ind = indent(lnum) +	let line = getline(lnum) + +	" No indentation if the previous line didn't end with "\": +	" (Could be annoying, but it lets you know if you made a mistake.) +	if line !~ '\\$' +		return 0 +	endif + +	if line =~ '\(/def.*\\\|/for.*\(%;\s*\)\@\<!\\\)$' +		let ind = ind + shiftwidth() +	elseif line =~ '\(/if\|/else\|/then\)' +		if line !~ '/endif' +			let ind = ind + shiftwidth() +		endif +	elseif line =~ '/while' +		if line !~ '/done' +			let ind = ind + shiftwidth() +		endif +	endif + +	let line = getline(v:lnum) + +	if line =~ '\(/else\|/endif\|/then\)' +		if line !~ '/if' +			let ind = ind - shiftwidth() +		endif +	elseif line =~ '/done' +		if line !~ '/while' +			let ind = ind - shiftwidth() +		endif +	endif + +	" Comments at the beginning of a line: +	if line =~ '^\s*;' +		let ind = 0 +	endif + + +	return ind + +endfunction + +endif diff --git a/indent/tilde.vim b/indent/tilde.vim new file mode 100644 index 00000000..58e6723c --- /dev/null +++ b/indent/tilde.vim @@ -0,0 +1,40 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +"Description: Indent scheme for the tilde weblanguage +"Author: Tobias Rundström <tobi@tobi.nu> +"URL: http://tilde.tildesoftware.net +"Last Change: May  8 09:15:09 CEST 2002 + +if exists ("b:did_indent") +	finish +endif + +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetTildeIndent(v:lnum) +setlocal indentkeys=o,O,) + +if exists("*GetTildeIndent") +	finish +endif + +function GetTildeIndent(lnum) +	let plnum = prevnonblank(v:lnum-1) + +	if plnum == 0 +		return 0 +	endif + +	if getline(v:lnum) =~ '^\s*\~\(endif\|else\|elseif\|end\)\>' +		return indent(v:lnum) - shiftwidth() +	endif + +	if getline(plnum) =~ '^\s*\~\(if\|foreach\|foreach_row\|xml_loop\|file_loop\|file_write\|file_append\|imap_loopsections\|imap_index\|imap_list\|ldap_search\|post_loopall\|post_loop\|file_loop\|sql_loop_num\|sql_dbmsselect\|search\|sql_loop\|post\|for\|function_define\|silent\|while\|setvalbig\|mail_create\|systempipe\|mail_send\|dual\|elseif\|else\)\>' +		return indent(plnum) + shiftwidth() +	else +		return -1 +	endif +endfunction + +endif diff --git a/indent/treetop.vim b/indent/treetop.vim new file mode 100644 index 00000000..542aabb2 --- /dev/null +++ b/indent/treetop.vim @@ -0,0 +1,42 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Treetop +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2011-03-14 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetTreetopIndent() +setlocal indentkeys=0{,0},!^F,o,O,=end +setlocal nosmartindent + +if exists("*GetTreetopIndent") +  finish +endif + +function GetTreetopIndent() +  let pnum = prevnonblank(v:lnum - 1) +  if pnum == 0 +    return 0 +  endif + +  let ind = indent(pnum) +  let line = getline(pnum) + +  if line =~ '^\s*\%(grammar\|module\|rule\)\>' +    let ind += shiftwidth() +  endif + +  let line = getline(v:lnum) +  if line =~ '^\s*end\>' +    let ind -= shiftwidth() +  end + +  retur ind +endfunction + +endif diff --git a/indent/vb.vim b/indent/vb.vim new file mode 100644 index 00000000..853d8e38 --- /dev/null +++ b/indent/vb.vim @@ -0,0 +1,82 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	VisualBasic (ft=vb) / Basic (ft=basic) / SaxBasic (ft=vb) +" Author:	Johannes Zellner <johannes@zellner.org> +" Last Change:	Fri, 18 Jun 2004 07:22:42 CEST +"		Small update 2010 Jul 28 by Maxim Kim + +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=VbGetIndent(v:lnum) +setlocal indentkeys& +setlocal indentkeys+==~else,=~elseif,=~end,=~wend,=~case,=~next,=~select,=~loop,<:> + +let b:undo_indent = "set ai< indentexpr< indentkeys<" + +" Only define the function once. +if exists("*VbGetIndent") +    finish +endif + +fun! VbGetIndent(lnum) +    " labels and preprocessor get zero indent immediately +    let this_line = getline(a:lnum) +    let LABELS_OR_PREPROC = '^\s*\(\<\k\+\>:\s*$\|#.*\)' +    if this_line =~? LABELS_OR_PREPROC +	return 0 +    endif + +    " Find a non-blank line above the current line. +    " Skip over labels and preprocessor directives. +    let lnum = a:lnum +    while lnum > 0 +	let lnum = prevnonblank(lnum - 1) +	let previous_line = getline(lnum) +	if previous_line !~? LABELS_OR_PREPROC +	    break +	endif +    endwhile + +    " Hit the start of the file, use zero indent. +    if lnum == 0 +	return 0 +    endif + +    let ind = indent(lnum) + +    " Add +    if previous_line =~? '^\s*\<\(begin\|\%(\%(private\|public\|friend\)\s\+\)\=\%(function\|sub\|property\)\|select\|case\|default\|if\|else\|elseif\|do\|for\|while\|enum\|with\)\>' +	let ind = ind + shiftwidth() +    endif + +    " Subtract +    if this_line =~? '^\s*\<end\>\s\+\<select\>' +	if previous_line !~? '^\s*\<select\>' +	    let ind = ind - 2 * shiftwidth() +	else +	    " this case is for an empty 'select' -- 'end select' +	    " (w/o any case statements) like: +	    " +	    " select case readwrite +	    " end select +	    let ind = ind - shiftwidth() +	endif +    elseif this_line =~? '^\s*\<\(end\|else\|elseif\|until\|loop\|next\|wend\)\>' +	let ind = ind - shiftwidth() +    elseif this_line =~? '^\s*\<\(case\|default\)\>' +	if previous_line !~? '^\s*\<select\>' +	    let ind = ind - shiftwidth() +	endif +    endif + +    return ind +endfun + +" vim:sw=4 + +endif diff --git a/indent/verilog.vim b/indent/verilog.vim new file mode 100644 index 00000000..e8dd64a6 --- /dev/null +++ b/indent/verilog.vim @@ -0,0 +1,233 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Language:     Verilog HDL +" Maintainer:	Chih-Tsun Huang <cthuang@cs.nthu.edu.tw> +" Last Change:	2017 Aug 25 by Chih-Tsun Huang +" URL:		    http://www.cs.nthu.edu.tw/~cthuang/vim/indent/verilog.vim +" +" Credits: +"   Suggestions for improvement, bug reports by +"     Takuya Fujiwara <tyru.exe@gmail.com> +"     Thilo Six <debian@Xk2c.de> +"     Leo Butlero <lbutler@brocade.com> +" +" Buffer Variables: +"     b:verilog_indent_modules : indenting after the declaration +"				 of module blocks +"     b:verilog_indent_width   : indenting width +"     b:verilog_indent_verbose : verbose to each indenting +" + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetVerilogIndent() +setlocal indentkeys=!^F,o,O,0),=begin,=end,=join,=endcase +setlocal indentkeys+==endmodule,=endfunction,=endtask,=endspecify +setlocal indentkeys+==endconfig,=endgenerate,=endprimitive,=endtable +setlocal indentkeys+==`else,=`elsif,=`endif + +" Only define the function once. +if exists("*GetVerilogIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +function GetVerilogIndent() + +  if exists('b:verilog_indent_width') +    let offset = b:verilog_indent_width +  else +    let offset = shiftwidth() +  endif +  if exists('b:verilog_indent_modules') +    let indent_modules = offset +  else +    let indent_modules = 0 +  endif + +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif + +  let lnum2 = prevnonblank(lnum - 1) +  let curr_line  = getline(v:lnum) +  let last_line  = getline(lnum) +  let last_line2 = getline(lnum2) +  let ind  = indent(lnum) +  let ind2 = indent(lnum - 1) +  let offset_comment1 = 1 +  " Define the condition of an open statement +  "   Exclude the match of //, /* or */ +  let vlog_openstat = '\(\<or\>\|\([*/]\)\@<![*(,{><+-/%^&|!=?:]\([*/]\)\@!\)' +  " Define the condition when the statement ends with a one-line comment +  let vlog_comment = '\(//.*\|/\*.*\*/\s*\)' +  if exists('b:verilog_indent_verbose') +    let vverb_str = 'INDENT VERBOSE:' +    let vverb = 1 +  else +    let vverb = 0 +  endif + +  " Indent accoding to last line +  " End of multiple-line comment +  if last_line =~ '\*/\s*$' && last_line !~ '/\*.\{-}\*/' +    let ind = ind - offset_comment1 +    if vverb +      echo vverb_str "De-indent after a multiple-line comment." +    endif + +  " Indent after if/else/for/case/always/initial/specify/fork blocks +  " Note: We exclude '`if' or '`else' and consider 'end else'  +  "       'end if' is redundant here +  elseif last_line =~ '^\s*\(end\)\=\s*`\@<!\<\(if\|else\)\>' || +    \ last_line =~ '^\s*\<\(for\|case\%[[zx]]\)\>' || +    \ last_line =~ '^\s*\<\(always\|initial\)\>' || +    \ last_line =~ '^\s*\<\(specify\|fork\)\>' +    if last_line !~ '\(;\|\<end\>\)\s*' . vlog_comment . '*$' || +      \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . vlog_comment . '*$' +      let ind = ind + offset +      if vverb | echo vverb_str "Indent after a block statement." | endif +    endif +  " Indent after function/task/config/generate/primitive/table blocks +  elseif last_line =~ '^\s*\<\(function\|task\|config\|generate\|primitive\|table\)\>' +    if last_line !~ '\<end\>\s*' . vlog_comment . '*$' || +      \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . vlog_comment . '*$' +      let ind = ind + offset +      if vverb +	echo vverb_str "Indent after function/task block statement." +      endif +    endif + +  " Indent after module/function/task/specify/fork blocks +  elseif last_line =~ '^\s*\<module\>' +    let ind = ind + indent_modules +    if vverb && indent_modules +      echo vverb_str "Indent after module statement." +    endif +    if last_line =~ '[(,]\s*' . vlog_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*[(,]\s*' . vlog_comment . '*$' +      let ind = ind + offset +      if vverb +	echo vverb_str "Indent after a multiple-line module statement." +      endif +    endif + +  " Indent after a 'begin' statement +  elseif last_line =~ '\(\<begin\>\)\(\s*:\s*\w\+\)*' . vlog_comment . '*$' && +    \ last_line !~ '\(//\|/\*\).*\(\<begin\>\)' && +    \ ( last_line2 !~ vlog_openstat . '\s*' . vlog_comment . '*$' || +    \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . vlog_comment . '*$' ) +    let ind = ind + offset +    if vverb | echo vverb_str "Indent after begin statement." | endif + +  " De-indent for the end of one-line block +  elseif ( last_line !~ '\<begin\>' || +    \ last_line =~ '\(//\|/\*\).*\<begin\>' ) && +    \ last_line2 =~ '\<\(`\@<!if\|`\@<!else\|for\|always\|initial\)\>.*' . +      \ vlog_comment . '*$' && +    \ last_line2 !~ +      \ '\(//\|/\*\).*\<\(`\@<!if\|`\@<!else\|for\|always\|initial\)\>' && +    \ last_line2 !~ vlog_openstat . '\s*' . vlog_comment . '*$' && +    \ ( last_line2 !~ '\<begin\>' || +    \ last_line2 =~ '\(//\|/\*\).*\<begin\>' ) +    let ind = ind - offset +    if vverb +      echo vverb_str "De-indent after the end of one-line statement." +    endif + +    " Multiple-line statement (including case statement) +    " Open statement +    "   Ident the first open line +    elseif  last_line =~ vlog_openstat . '\s*' . vlog_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*' . vlog_openstat . '\s*$' && +      \ last_line2 !~ vlog_openstat . '\s*' . vlog_comment . '*$' +      let ind = ind + offset +      if vverb | echo vverb_str "Indent after an open statement." | endif + +    " Close statement +    "   De-indent for an optional close parenthesis and a semicolon, and only +    "   if there exists precedent non-whitespace char +    elseif last_line =~ ')*\s*;\s*' . vlog_comment . '*$' && +      \ last_line !~ '^\s*)*\s*;\s*' . vlog_comment . '*$' && +      \ last_line !~ '\(//\|/\*\).*\S)*\s*;\s*' . vlog_comment . '*$' && +      \ ( last_line2 =~ vlog_openstat . '\s*' . vlog_comment . '*$' && +      \ last_line2 !~ ';\s*//.*$') && +      \ last_line2 !~ '^\s*' . vlog_comment . '$' +      let ind = ind - offset +      if vverb | echo vverb_str "De-indent after a close statement." | endif + +  " `ifdef or `ifndef or `elsif or `else +  elseif last_line =~ '^\s*`\<\(ifn\?def\|elsif\|else\)\>' +    let ind = ind + offset +    if vverb +      echo vverb_str "Indent after a `ifdef or `ifndef or `elsif or `else statement." +    endif + +  endif + +  " Re-indent current line + +  " De-indent on the end of the block +  " join/end/endcase/endfunction/endtask/endspecify +  if curr_line =~ '^\s*\<\(join\|end\|endcase\)\>' || +    \ curr_line =~ '^\s*\<\(endfunction\|endtask\|endspecify\)\>' || +    \ curr_line =~ '^\s*\<\(endconfig\|endgenerate\|endprimitive\|endtable\)\>' +    let ind = ind - offset +    if vverb | echo vverb_str "De-indent the end of a block." | endif +  elseif curr_line =~ '^\s*\<endmodule\>' +    let ind = ind - indent_modules +    if vverb && indent_modules +      echo vverb_str "De-indent the end of a module." +    endif + +  " De-indent on a stand-alone 'begin' +  elseif curr_line =~ '^\s*\<begin\>' +    if last_line !~ '^\s*\<\(function\|task\|specify\|module\|config\|generate\|primitive\|table\)\>' && +      \ last_line !~ '^\s*\()*\s*;\|)\+\)\s*' . vlog_comment . '*$' && +      \ ( last_line =~ +	\ '\<\(`\@<!if\|`\@<!else\|for\|case\%[[zx]]\|always\|initial\)\>' || +      \ last_line =~ ')\s*' . vlog_comment . '*$' || +      \ last_line =~ vlog_openstat . '\s*' . vlog_comment . '*$' ) +      let ind = ind - offset +      if vverb +	echo vverb_str "De-indent a stand alone begin statement." +      endif +    endif + +  " De-indent after the end of multiple-line statement +  elseif curr_line =~ '^\s*)' && +    \ ( last_line =~ vlog_openstat . '\s*' . vlog_comment . '*$' || +    \ last_line !~ vlog_openstat . '\s*' . vlog_comment . '*$' && +    \ last_line2 =~ vlog_openstat . '\s*' . vlog_comment . '*$' ) +    let ind = ind - offset +    if vverb +      echo vverb_str "De-indent the end of a multiple statement." +    endif + +  " De-indent `elsif or `else or `endif +  elseif curr_line =~ '^\s*`\<\(elsif\|else\|endif\)\>' +    let ind = ind - offset +    if vverb | echo vverb_str "De-indent `elsif or `else or `endif statement." | endif + +  endif + +  " Return the indention +  return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:sw=2 + +endif diff --git a/indent/vhdl.vim b/indent/vhdl.vim new file mode 100644 index 00000000..1b2ff817 --- /dev/null +++ b/indent/vhdl.vim @@ -0,0 +1,438 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" VHDL indent ('93 syntax) +" Language:    VHDL +" Maintainer:  Gerald Lai <laigera+vim?gmail.com> +" Version:     1.60 +" Last Change: 2017 Jun 13 +" URL:         http://www.vim.org/scripts/script.php?script_id=1450 + +" only load this indent file when no other was loaded +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +" setup indent options for local VHDL buffer +setlocal indentexpr=GetVHDLindent() +setlocal indentkeys=!^F,o,O,0(,0) +setlocal indentkeys+==~begin,=~end\ ,=~end\	,=~is,=~select,=~when +setlocal indentkeys+==~if,=~then,=~elsif,=~else +setlocal indentkeys+==~case,=~loop,=~for,=~generate,=~record,=~units,=~process,=~block,=~function,=~component,=~procedure +setlocal indentkeys+==~architecture,=~configuration,=~entity,=~package + +" constants +" not a comment +let s:NC = '\%(--.*\)\@<!' +" end of string +let s:ES = '\s*\%(--.*\)\=$' +" no "end" keyword in front +let s:NE = '\%(\<end\s\+\)\@<!' + +" option to disable alignment of generic/port mappings +if !exists("g:vhdl_indent_genportmap") +  let g:vhdl_indent_genportmap = 1 +endif + +" option to disable alignment of right-hand side assignment "<=" statements +if !exists("g:vhdl_indent_rhsassign") +  let g:vhdl_indent_rhsassign = 1 +endif + +" only define indent function once +if exists("*GetVHDLindent") +  finish +endif + +function GetVHDLindent() +  " store current line & string +  let curn = v:lnum +  let curs = getline(curn) + +  " find previous line that is not a comment +  let prevn = prevnonblank(curn - 1) +  let prevs = getline(prevn) +  while prevn > 0 && prevs =~ '^\s*--' +    let prevn = prevnonblank(prevn - 1) +    let prevs = getline(prevn) +  endwhile +  let prevs_noi = substitute(prevs, '^\s*', '', '') + +  " default indent starts as previous non-comment line's indent +  let ind = prevn > 0 ? indent(prevn) : 0 +  " backup default +  let ind2 = ind + +  " indent:   special; kill string so it would not affect other filters +  " keywords: "report" + string +  " where:    anywhere in current or previous line +  let s0 = s:NC.'\<report\>\s*".*"' +  if curs =~? s0 +    let curs = "" +  endif +  if prevs =~? s0 +    let prevs = "" +  endif + +  " indent:   previous line's comment position, otherwise follow next non-comment line if possible +  " keyword:  "--" +  " where:    start of current line +  if curs =~ '^\s*--' +    let pn = curn - 1 +    let ps = getline(pn) +    if curs =~ '^\s*--\s' && ps =~ '--' +      return indent(pn) + stridx(substitute(ps, '^\s*', '', ''), '--') +    else +      " find nextnonblank line that is not a comment +      let nn = nextnonblank(curn + 1) +      let ns = getline(nn) +      while nn > 0 && ns =~ '^\s*--' +        let nn = nextnonblank(nn + 1) +        let ns = getline(nn) +      endwhile +      let n = indent(nn) +      return n != -1 ? n : ind +    endif +  endif + +  " **************************************************************************************** +  " indent:   align generic variables & port names +  " keywords: "procedure" + name, "generic", "map", "port" + "(", provided current line is part of mapping +  " where:    anywhere in previous 2 lines +  " find following previous non-comment line +  let pn = prevnonblank(prevn - 1) +  let ps = getline(pn) +  while pn > 0 && ps =~ '^\s*--' +    let pn = prevnonblank(pn - 1) +    let ps = getline(pn) +  endwhile +  if (curs =~ '^\s*)' || curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*\((.*)\)*\s*\%(=>\s*\S\+\|:[^=]\@=\s*\%(\%(in\|out\|inout\|buffer\|linkage\)\>\|\s\+\)\)') && (prevs =~? s:NC.'\<\%(procedure\s\+\S\+\|generic\|map\|port\)\s*(\%(\s*\w\)\=' || (ps =~? s:NC.'\<\%(procedure\|generic\|map\|port\)'.s:ES && prevs =~ '^\s*(')) +    " align closing ")" with opening "(" +    if curs =~ '^\s*)' +      return ind2 + stridx(prevs_noi, '(') +    endif +    let m = matchend(prevs_noi, '(\s*\ze\w') +    if m != -1 +      return ind2 + m +    else +      if g:vhdl_indent_genportmap +        return ind2 + stridx(prevs_noi, '(') + shiftwidth() +      else +        return ind2 + shiftwidth() +      endif +    endif +  endif + +  " indent:   align conditional/select statement +  " keywords: variable + "<=" without ";" ending +  " where:    start of previous line +  if prevs =~? '^\s*\S\+\s*<=[^;]*'.s:ES +    if g:vhdl_indent_rhsassign +      return ind2 + matchend(prevs_noi, '<=\s*\ze.') +    else +      return ind2 + shiftwidth() +    endif +  endif + +  " indent:   backtrace previous non-comment lines for next smaller or equal size indent +  " keywords: "end" + "record", "units" +  " where:    start of previous line +  " keyword:  ")" +  " where:    start of previous line +  " keyword:  without "<=" + ";" ending +  " where:    anywhere in previous line +  " keyword:  "=>" + ")" ending, provided current line does not begin with ")" +  " where:    anywhere in previous line +  " _note_:   indent allowed to leave this filter +  let m = 0 +  if prevs =~? '^\s*end\s\+\%(record\|units\)\>' +    let m = 3 +  elseif prevs =~ '^\s*)' +    let m = 1 +  elseif prevs =~ s:NC.'\%(<=.*\)\@<!;'.s:ES || (curs !~ '^\s*)' && prevs =~ s:NC.'=>.*'.s:NC.')'.s:ES) +    let m = 2 +  endif + +  if m > 0 +    let pn = prevnonblank(prevn - 1) +    let ps = getline(pn) +    while pn > 0 +      let t = indent(pn) +      if ps !~ '^\s*--' && (t < ind || (t == ind && m == 3)) +        " make sure one of these is true +        " keywords: variable + "<=" without ";" ending +        " where:    start of previous non-comment line +        " keywords: "procedure", "generic", "map", "port" +        " where:    anywhere in previous non-comment line +        " keyword:  "(" +        " where:    start of previous non-comment line +        if m < 3 && ps !~? '^\s*\S\+\s*<=[^;]*'.s:ES +          if ps =~? s:NC.'\<\%(procedure\|generic\|map\|port\)\>' || ps =~ '^\s*(' +            let ind = t +          endif +          break +        endif +        let ind = t +        if m > 1 +          " find following previous non-comment line +          let ppn = prevnonblank(pn - 1) +          let pps = getline(ppn) +          while ppn > 0 && pps =~ '^\s*--' +            let ppn = prevnonblank(ppn - 1) +            let pps = getline(ppn) +          endwhile +          " indent:   follow +          " keyword:  "select" +          " where:    end of following previous non-comment line +          " keyword:  "type" +          " where:    start of following previous non-comment line +          if m == 2 +            let s1 = s:NC.'\<select'.s:ES +            if ps !~? s1 && pps =~? s1 +              let ind = indent(ppn) +            endif +          elseif m == 3 +            let s1 = '^\s*type\>' +            if ps !~? s1 && pps =~? s1 +              let ind = indent(ppn) +            endif +          endif +        endif +        break +      endif +      let pn = prevnonblank(pn - 1) +      let ps = getline(pn) +    endwhile +  endif + +  " indent:   follow indent of previous opening statement, otherwise -sw +  " keyword:  "begin" +  " where:    anywhere in current line +  if curs =~? s:NC.'\<begin\>' +    " find previous opening statement of +    " keywords: "architecture", "block", "entity", "function", "generate", "procedure", "process" +    let s2 = s:NC.s:NE.'\<\%(architecture\|block\|entity\|function\|generate\|procedure\|process\)\>' + +    let pn = prevnonblank(curn - 1) +    let ps = getline(pn) +    while pn > 0 && (ps =~ '^\s*--' || ps !~? s2) +      let pn = prevnonblank(pn - 1) +      let ps = getline(pn) + +      if (ps =~? s:NC.'\<begin\>') +        return indent(pn) - shiftwidth() +      endif +    endwhile + +    if (pn == 0) +      return ind - shiftwidth() +    else +      return indent(pn) +    endif +  endif + +  " indent:   +sw if previous line is previous opening statement +  " keywords: "record", "units" +  " where:    anywhere in current line +  if curs =~? s:NC.s:NE.'\<\%(record\|units\)\>' +    " find previous opening statement of +    " keyword: "type" +    let s3 = s:NC.s:NE.'\<type\>' +    if curs !~? s3.'.*'.s:NC.'\<\%(record\|units\)\>.*'.s:ES && prevs =~? s3 +      let ind = ind + shiftwidth() +    endif +    return ind +  endif + +  " **************************************************************************************** +  " indent:   0 +  " keywords: "architecture", "configuration", "entity", "library", "package" +  " where:    start of current line +  if curs =~? '^\s*\%(architecture\|configuration\|entity\|library\|package\)\>' +    return 0 +  endif + +  " indent:   maintain indent of previous opening statement +  " keyword:  "is" +  " where:    start of current line +  " find previous opening statement of +  " keywords: "architecture", "block", "configuration", "entity", "function", "package", "procedure", "process", "type" +  if curs =~? '^\s*\<is\>' && prevs =~? s:NC.s:NE.'\<\%(architecture\|block\|configuration\|entity\|function\|package\|procedure\|process\|type\)\>' +    return ind2 +  endif + +  " indent:   maintain indent of previous opening statement +  " keyword:  "then" +  " where:    start of current line +  " find previous opening statement of +  " keywords: "elsif", "if" +  if curs =~? '^\s*\<then\>' && prevs =~? s:NC.'\%(\<elsif\>\|'.s:NE.'\<if\>\)' +    return ind2 +  endif + +  " indent:   maintain indent of previous opening statement +  " keyword:  "generate" +  " where:    start of current line +  " find previous opening statement of +  " keywords: "for", "if" +  if curs =~? '^\s*\<generate\>' && prevs =~? s:NC.s:NE.'\%(\%(\<wait\s\+\)\@<!\<for\|\<if\)\>' +    return ind2 +  endif + +  " indent:   +sw +  " keywords: "block", "process" +  " removed:  "begin", "case", "elsif", "if", "loop", "record", "units", "while" +  " where:    anywhere in previous line +  if prevs =~? s:NC.s:NE.'\<\%(block\|process\)\>' +    return ind + shiftwidth() +  endif + +  " indent:   +sw +  " keywords: "architecture", "configuration", "entity", "package" +  " removed:  "component", "for", "when", "with" +  " where:    start of previous line +  if prevs =~? '^\s*\%(architecture\|configuration\|entity\|package\)\>' +    return ind + shiftwidth() +  endif + +  " indent:   +sw +  " keyword:  "select" +  " removed:  "generate", "is", "=>" +  " where:    end of previous line +  if prevs =~? s:NC.'\<select'.s:ES +    return ind + shiftwidth() +  endif + +  " indent:   +sw +  " keyword:  "begin", "loop", "record", "units" +  " where:    anywhere in previous line +  " keyword:  "component", "else", "for" +  " where:    start of previous line +  " keyword:  "generate", "is", "then", "=>" +  " where:    end of previous line +  " _note_:   indent allowed to leave this filter +  if prevs =~? s:NC.'\%(\<begin\>\|'.s:NE.'\<\%(loop\|record\|units\)\>\)' || prevs =~? '^\s*\%(component\|else\|for\)\>' || prevs =~? s:NC.'\%('.s:NE.'\<generate\|\<\%(is\|then\)\|=>\)'.s:ES +    let ind = ind + shiftwidth() +  endif + +  " **************************************************************************************** +  " indent:   -sw +  " keywords: "when", provided previous line does not begin with "when", does not end with "is" +  " where:    start of current line +  let s4 = '^\s*when\>' +  if curs =~? s4 +    if prevs =~? s:NC.'\<is'.s:ES +      return ind +    elseif prevs !~? s4 +      return ind - shiftwidth() +    else +      return ind2 +    endif +  endif + +  " indent:   -sw +  " keywords: "else", "elsif", "end" + "block", "for", "function", "generate", "if", "loop", "procedure", "process", "record", "units" +  " where:    start of current line +  let s5 = 'block\|for\|function\|generate\|if\|loop\|procedure\|process\|record\|units' +  if curs =~? '^\s*\%(else\|elsif\|end\s\+\%('.s5.'\)\)\>' +    if prevs =~? '^\s*\%(elsif\|'.s5.'\)' +      return ind +    else +      return ind - shiftwidth() +    endif +  endif + +  " indent:   backtrace previous non-comment lines +  " keyword:  "end" + "case", "component" +  " where:    start of current line +  let m = 0 +  if curs =~? '^\s*end\s\+case\>' +    let m = 1 +  elseif curs =~? '^\s*end\s\+component\>' +    let m = 2 +  endif + +  if m > 0 +    " find following previous non-comment line +    let pn = prevn +    let ps = getline(pn) +    while pn > 0 +      if ps !~ '^\s*--' +        "indent:   -2sw +        "keywords: "end" + "case" +        "where:    start of previous non-comment line +        "indent:   -sw +        "keywords: "when" +        "where:    start of previous non-comment line +        "indent:   follow +        "keywords: "case" +        "where:    start of previous non-comment line +        if m == 1 +          if ps =~? '^\s*end\s\+case\>' +            return indent(pn) - 2 * shiftwidth() +          elseif ps =~? '^\s*when\>' +            return indent(pn) - shiftwidth() +          elseif ps =~? '^\s*case\>' +            return indent(pn) +          endif +        "indent:   follow +        "keyword:  "component" +        "where:    start of previous non-comment line +        elseif m == 2 +          if ps =~? '^\s*component\>' +            return indent(pn) +          endif +        endif +      endif +      let pn = prevnonblank(pn - 1) +      let ps = getline(pn) +    endwhile +    return ind - shiftwidth() +  endif + +  " indent:   -sw +  " keyword:  ")" +  " where:    start of current line +  if curs =~ '^\s*)' +    return ind - shiftwidth() +  endif + +  " indent:   0 +  " keywords: "end" + "architecture", "configuration", "entity", "package" +  " where:    start of current line +  if curs =~? '^\s*end\s\+\%(architecture\|configuration\|entity\|package\)\>' +    return 0 +  endif + +  " indent:   -sw +  " keywords: "end" + identifier, ";" +  " where:    start of current line +  "if curs =~? '^\s*end\s\+\w\+\>' +  if curs =~? '^\s*end\%(\s\|;'.s:ES.'\)' +    return ind - shiftwidth() +  endif + +  " **************************************************************************************** +  " indent:   maintain indent of previous opening statement +  " keywords: without "procedure", "generic", "map", "port" + ":" but not ":=" + eventually ;$ +  " where:    start of current line +  if curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*:[^=].*;.*$' +    return ind2 +  endif +  " **************************************************************************************** +  " indent:     maintain indent of previous opening statement, corner case which +  "             does not end in ;, but is part of a mapping +  " keywords:   without "procedure", "generic", "map", "port" + ":" but not ":=", never + ;$ and +  "             prevline without "procedure", "generic", "map", "port" + ":" but not ":=" + eventually ;$ +  " where:      start of current line +  if curs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*:[^=].*[^;].*$' +      if prevs =~? '^\s*\%(\<\%(procedure\|generic\|map\|port\)\>.*\)\@<!\w\+\s*\w*\s*:[^=].*;.*$' +         return ind2 +     endif + endif + +  " return leftover filtered indent +  return ind +endfunction + +endif diff --git a/indent/vim.vim b/indent/vim.vim new file mode 100644 index 00000000..e39e4dc5 --- /dev/null +++ b/indent/vim.vim @@ -0,0 +1,106 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Vim script +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2016 Jun 27 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetVimIndent() +setlocal indentkeys+==end,=else,=cat,=fina,=END,0\\ + +let b:undo_indent = "setl indentkeys< indentexpr<" + +" Only define the function once. +if exists("*GetVimIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +function GetVimIndent() +  let ignorecase_save = &ignorecase +  try +    let &ignorecase = 0 +    return GetVimIndentIntern() +  finally +    let &ignorecase = ignorecase_save +  endtry +endfunc + +function GetVimIndentIntern() +  " Find a non-blank line above the current line. +  let lnum = prevnonblank(v:lnum - 1) + +  " If the current line doesn't start with '\' and below a line that starts +  " with '\', use the indent of the line above it. +  let cur_text = getline(v:lnum) +  if cur_text !~ '^\s*\\' +    while lnum > 0 && getline(lnum) =~ '^\s*\\' +      let lnum = lnum - 1 +    endwhile +  endif + +  " At the start of the file use zero indent. +  if lnum == 0 +    return 0 +  endif +  let prev_text = getline(lnum) + +  " Add a 'shiftwidth' after :if, :while, :try, :catch, :finally, :function +  " and :else.  Add it three times for a line that starts with '\' after +  " a line that doesn't (or g:vim_indent_cont if it exists). +  let ind = indent(lnum) +  if cur_text =~ '^\s*\\' && v:lnum > 1 && prev_text !~ '^\s*\\' +    if exists("g:vim_indent_cont") +      let ind = ind + g:vim_indent_cont +    else +      let ind = ind + shiftwidth() * 3 +    endif +  elseif prev_text =~ '^\s*aug\%[roup]\s\+' && prev_text !~ '^\s*aug\%[roup]\s\+[eE][nN][dD]\>' +    let ind = ind + shiftwidth() +  else +    " A line starting with :au does not increment/decrement indent. +    if prev_text !~ '^\s*au\%[tocmd]' +      let i = match(prev_text, '\(^\||\)\s*\(if\|wh\%[ile]\|for\|try\|cat\%[ch]\|fina\%[lly]\|fu\%[nction]\|el\%[seif]\)\>') +      if i >= 0 +	let ind += shiftwidth() +	if strpart(prev_text, i, 1) == '|' && has('syntax_items') +	      \ && synIDattr(synID(lnum, i, 1), "name") =~ '\(Comment\|String\)$' +	  let ind -= shiftwidth() +	endif +      endif +    endif +  endif + +  " If the previous line contains an "end" after a pipe, but not in an ":au" +  " command.  And not when there is a backslash before the pipe. +  " And when syntax HL is enabled avoid a match inside a string. +  let i = match(prev_text, '[^\\]|\s*\(ene\@!\)') +  if i > 0 && prev_text !~ '^\s*au\%[tocmd]' +    if !has('syntax_items') || synIDattr(synID(lnum, i + 2, 1), "name") !~ '\(Comment\|String\)$' +      let ind = ind - shiftwidth() +    endif +  endif + + +  " Subtract a 'shiftwidth' on a :endif, :endwhile, :catch, :finally, :endtry, +  " :endfun, :else and :augroup END. +  if cur_text =~ '^\s*\(ene\@!\|cat\|fina\|el\|aug\%[roup]\s\+[eE][nN][dD]\)' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 + +endif diff --git a/indent/vroom.vim b/indent/vroom.vim new file mode 100644 index 00000000..29188466 --- /dev/null +++ b/indent/vroom.vim @@ -0,0 +1,25 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Vroom (vim testing and executable documentation) +" Maintainer:	David Barnett (https://github.com/google/vim-ft-vroom) +" Last Change:	2014 Jul 23 + +if exists('b:did_indent') +  finish +endif +let b:did_indent = 1 + +let s:cpo_save = &cpo +set cpo-=C + + +let b:undo_indent = 'setlocal autoindent<' + +setlocal autoindent + + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/xf86conf.vim b/indent/xf86conf.vim new file mode 100644 index 00000000..f45a828c --- /dev/null +++ b/indent/xf86conf.vim @@ -0,0 +1,41 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             XFree86 Configuration File +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetXF86ConfIndent() +setlocal indentkeys=!^F,o,O,=End +setlocal nosmartindent + +if exists("*GetXF86ConfIndent") +  finish +endif + +function GetXF86ConfIndent() +  let lnum = prevnonblank(v:lnum - 1) + +  if lnum == 0 +    return 0 +  endif + +  let ind = indent(lnum) + +  if getline(lnum) =~? '^\s*\(Sub\)\=Section\>' +    let ind = ind + shiftwidth() +  endif + +  if getline(v:lnum) =~? '^\s*End\(Sub\)\=Section\>' +    let ind = ind - shiftwidth() +  endif + +  return ind +endfunction + +endif diff --git a/indent/xhtml.vim b/indent/xhtml.vim new file mode 100644 index 00000000..28d4056f --- /dev/null +++ b/indent/xhtml.vim @@ -0,0 +1,16 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	XHTML +" Maintainer:	Bram Moolenaar <Bram@vim.org> (for now) +" Last Change:	2005 Jun 24 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Handled like HTML for now. +runtime! indent/html.vim + +endif diff --git a/indent/xinetd.vim b/indent/xinetd.vim new file mode 100644 index 00000000..e290638e --- /dev/null +++ b/indent/xinetd.vim @@ -0,0 +1,59 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             xinetd.conf(5) configuration file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +if exists("b:did_indent") +  finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetXinetdIndent() +setlocal indentkeys=0{,0},!^F,o,O +setlocal nosmartindent + +if exists("*GetXinetdIndent") +  finish +endif +let s:keepcpo= &cpo +set cpo&vim + +function s:count_braces(lnum, count_open) +  let n_open = 0 +  let n_close = 0 +  let line = getline(a:lnum) +  let pattern = '[{}]' +  let i = match(line, pattern) +  while i != -1 +    if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'ld\%(Comment\|String\)' +      if line[i] == '{' +        let n_open += 1 +      elseif line[i] == '}' +        if n_open > 0 +          let n_open -= 1 +        else +          let n_close += 1 +        endif +      endif +    endif +    let i = match(line, pattern, i + 1) +  endwhile +  return a:count_open ? n_open : n_close +endfunction + +function GetXinetdIndent() +  let pnum = prevnonblank(v:lnum - 1) +  if pnum == 0 +    return 0 +  endif + +  return indent(pnum) + s:count_braces(pnum, 1) * shiftwidth() +        \ - s:count_braces(v:lnum, 0) * shiftwidth() +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +endif diff --git a/indent/xml.vim b/indent/xml.vim new file mode 100644 index 00000000..cdd0ed9d --- /dev/null +++ b/indent/xml.vim @@ -0,0 +1,111 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Language:	xml +" Maintainer:	Johannes Zellner <johannes@zellner.org> +" Last Change:	2017 Jun 13 +" Notes:	1) does not indent pure non-xml code (e.g. embedded scripts) +"		2) will be confused by unbalanced tags in comments +"		or CDATA sections. +"		2009-05-26 patch by Nikolai Weibull +" TODO: 	implement pre-like tags, see xml_indent_open / xml_indent_close + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +    finish +endif +let b:did_indent = 1 +let s:keepcpo= &cpo +set cpo&vim + +" [-- local settings (must come before aborting the script) --] +setlocal indentexpr=XmlIndentGet(v:lnum,1) +setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,} + +if !exists('b:xml_indent_open') +    let b:xml_indent_open = '.\{-}<\a' +    " pre tag, e.g. <address> +    " let b:xml_indent_open = '.\{-}<[/]\@!\(address\)\@!' +endif + +if !exists('b:xml_indent_close') +    let b:xml_indent_close = '.\{-}</' +    " end pre tag, e.g. </address> +    " let b:xml_indent_close = '.\{-}</\(address\)\@!' +endif + +let &cpo = s:keepcpo +unlet s:keepcpo + +" [-- finish, if the function already exists --] +if exists('*XmlIndentGet') +  finish +endif + +let s:keepcpo= &cpo +set cpo&vim + +fun! <SID>XmlIndentWithPattern(line, pat) +    let s = substitute('x'.a:line, a:pat, "\1", 'g') +    return strlen(substitute(s, "[^\1].*$", '', '')) +endfun + +" [-- check if it's xml --] +fun! <SID>XmlIndentSynCheck(lnum) +    if '' != &syntax +	let syn1 = synIDattr(synID(a:lnum, 1, 1), 'name') +	let syn2 = synIDattr(synID(a:lnum, strlen(getline(a:lnum)) - 1, 1), 'name') +	if '' != syn1 && syn1 !~ 'xml' && '' != syn2 && syn2 !~ 'xml' +	    " don't indent pure non-xml code +	    return 0 +	elseif syn1 =~ '^xmlComment' && syn2 =~ '^xmlComment' +	    " indent comments specially +	    return -1 +	endif +    endif +    return 1 +endfun + +" [-- return the sum of indents of a:lnum --] +fun! <SID>XmlIndentSum(lnum, style, add) +    let line = getline(a:lnum) +    if a:style == match(line, '^\s*</') +	return (shiftwidth() * +	\  (<SID>XmlIndentWithPattern(line, b:xml_indent_open) +	\ - <SID>XmlIndentWithPattern(line, b:xml_indent_close) +	\ - <SID>XmlIndentWithPattern(line, '.\{-}/>'))) + a:add +    else +	return a:add +    endif +endfun + +fun! XmlIndentGet(lnum, use_syntax_check) +    " Find a non-empty line above the current line. +    let lnum = prevnonblank(a:lnum - 1) + +    " Hit the start of the file, use zero indent. +    if lnum == 0 +	return 0 +    endif + +    if a:use_syntax_check +	let check_lnum = <SID>XmlIndentSynCheck(lnum) +	let check_alnum = <SID>XmlIndentSynCheck(a:lnum) +	if 0 == check_lnum || 0 == check_alnum +	    return indent(a:lnum) +	elseif -1 == check_lnum || -1 == check_alnum +	    return -1 +	endif +    endif + +    let ind = <SID>XmlIndentSum(lnum, -1, indent(lnum)) +    let ind = <SID>XmlIndentSum(a:lnum, 0, ind) + +    return ind +endfun + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:ts=8 + +endif diff --git a/indent/xsd.vim b/indent/xsd.vim new file mode 100644 index 00000000..e4a41996 --- /dev/null +++ b/indent/xsd.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language: 	.xsd files (XML Schema) +" Maintainer:	Nobody +" Last Change:	2005 Jun 09 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Use XML formatting rules +runtime! indent/xml.vim + + +endif diff --git a/indent/xslt.vim b/indent/xslt.vim new file mode 100644 index 00000000..03f32790 --- /dev/null +++ b/indent/xslt.vim @@ -0,0 +1,17 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:    XSLT .xslt files +" Maintainer:  David Fishburn <fishburn@ianywhere.com> +" Last Change: Wed May 14 2003 8:48:41 PM + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +" Use XML formatting rules +runtime! indent/xml.vim + + +endif diff --git a/indent/yacc.vim b/indent/yacc.vim new file mode 100644 index 00000000..3055f31f --- /dev/null +++ b/indent/yacc.vim @@ -0,0 +1,45 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             YACC input file +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2006-12-20 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +  finish +endif + +let b:did_indent = 1 + +setlocal indentexpr=GetYaccIndent() +setlocal indentkeys=!^F,o,O +setlocal nosmartindent + +" Only define the function once. +if exists("*GetYaccIndent") +  finish +endif + +function GetYaccIndent() +  if v:lnum == 1 +    return 0 +  endif + +  let ind = indent(v:lnum - 1) +  let line = getline(v:lnum - 1) + +  if line == '' +    let ind = 0 +  elseif line =~ '^\w\+\s*:' +    let ind = ind + matchend(line, '^\w\+\s*') +  elseif line =~ '^\s*;' +    let ind = 0 +  else +    let ind = indent(v:lnum) +  endif + +  return ind +endfunction + +endif diff --git a/indent/yaml.vim b/indent/yaml.vim new file mode 100644 index 00000000..d7b8db59 --- /dev/null +++ b/indent/yaml.vim @@ -0,0 +1,159 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:         YAML +" Maintainer:       Nikolai Pavlov <zyx.vim@gmail.com> +" Last Change:	    2017 Jun 13 + +" Only load this indent file when no other was loaded. +if exists('b:did_indent') +  finish +endif + +let s:save_cpo = &cpo +set cpo&vim + +let b:did_indent = 1 + +setlocal indentexpr=GetYAMLIndent(v:lnum) +setlocal indentkeys=!^F,o,O,0#,0},0],<:>,0- +setlocal nosmartindent + +let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<' + +" Only define the function once. +if exists('*GetYAMLIndent') +    finish +endif + +function s:FindPrevLessIndentedLine(lnum, ...) +    let prevlnum = prevnonblank(a:lnum-1) +    let curindent = a:0 ? a:1 : indent(a:lnum) +    while           prevlnum +                \&&  indent(prevlnum) >=  curindent +                \&& getline(prevlnum) =~# '^\s*#' +        let prevlnum = prevnonblank(prevlnum-1) +    endwhile +    return prevlnum +endfunction + +function s:FindPrevLEIndentedLineMatchingRegex(lnum, regex) +    let plilnum = s:FindPrevLessIndentedLine(a:lnum, indent(a:lnum)+1) +    while plilnum && getline(plilnum) !~# a:regex +        let plilnum = s:FindPrevLessIndentedLine(plilnum) +    endwhile +    return plilnum +endfunction + +let s:mapkeyregex='\v^\s*\#@!\S@=%(\''%([^'']|\''\'')*\'''. +                \                 '|\"%([^"\\]|\\.)*\"'. +                \                 '|%(%(\:\ )@!.)*)\:%(\ |$)' +let s:liststartregex='\v^\s*%(\-%(\ |$))' + +let s:c_ns_anchor_char = '\v%([\n\r\uFEFF \t,[\]{}]@!\p)' +let s:c_ns_anchor_name = s:c_ns_anchor_char.'+' +let s:c_ns_anchor_property =  '\v\&'.s:c_ns_anchor_name + +let s:ns_word_char = '\v[[:alnum:]_\-]' +let s:ns_tag_char  = '\v%(%\x\x|'.s:ns_word_char.'|[#/;?:@&=+$.~*''()])' +let s:c_named_tag_handle     = '\v\!'.s:ns_word_char.'+\!' +let s:c_secondary_tag_handle = '\v\!\!' +let s:c_primary_tag_handle   = '\v\!' +let s:c_tag_handle = '\v%('.s:c_named_tag_handle. +            \            '|'.s:c_secondary_tag_handle. +            \            '|'.s:c_primary_tag_handle.')' +let s:c_ns_shorthand_tag = '\v'.s:c_tag_handle . s:ns_tag_char.'+' +let s:c_non_specific_tag = '\v\!' +let s:ns_uri_char  = '\v%(%\x\x|'.s:ns_word_char.'\v|[#/;?:@&=+$,.!~*''()[\]])' +let s:c_verbatim_tag = '\v\!\<'.s:ns_uri_char.'+\>' +let s:c_ns_tag_property = '\v'.s:c_verbatim_tag. +            \               '\v|'.s:c_ns_shorthand_tag. +            \               '\v|'.s:c_non_specific_tag + +let s:block_scalar_header = '\v[|>]%([+-]?[1-9]|[1-9]?[+-])?' + +function GetYAMLIndent(lnum) +    if a:lnum == 1 || !prevnonblank(a:lnum-1) +        return 0 +    endif + +    let prevlnum = prevnonblank(a:lnum-1) +    let previndent = indent(prevlnum) + +    let line = getline(a:lnum) +    if line =~# '^\s*#' && getline(a:lnum-1) =~# '^\s*#' +        " Comment blocks should have identical indent +        return previndent +    elseif line =~# '^\s*[\]}]' +        " Lines containing only closing braces should have previous indent +        return indent(s:FindPrevLessIndentedLine(a:lnum)) +    endif + +    " Ignore comment lines when calculating indent +    while getline(prevlnum) =~# '^\s*#' +        let prevlnum = prevnonblank(prevlnum-1) +        if !prevlnum +            return previndent +        endif +    endwhile + +    let prevline = getline(prevlnum) +    let previndent = indent(prevlnum) + +    " Any examples below assume that shiftwidth=2 +    if prevline =~# '\v[{[:]$|[:-]\ [|>][+\-]?%(\s+\#.*|\s*)$' +        " Mapping key: +        "     nested mapping: ... +        " +        " - { +        "     key: [ +        "         list value +        "     ] +        " } +        " +        " - |- +        "     Block scalar without indentation indicator +        return previndent+shiftwidth() +    elseif prevline =~# '\v[:-]\ [|>]%(\d+[+\-]?|[+\-]?\d+)%(\#.*|\s*)$' +        " - |+2 +        "   block scalar with indentation indicator +        "#^^ indent+2, not indent+shiftwidth +        return previndent + str2nr(matchstr(prevline, +                    \'\v([:-]\ [|>])@<=[+\-]?\d+%([+\-]?%(\s+\#.*|\s*)$)@=')) +    elseif prevline =~# '\v\"%([^"\\]|\\.)*\\$' +        "    "Multiline string \ +        "     with escaped end" +        let qidx = match(prevline, '\v\"%([^"\\]|\\.)*\\') +        return virtcol([prevlnum, qidx+1]) +    elseif line =~# s:liststartregex +        " List line should have indent equal to previous list line unless it was  +        " caught by one of the previous rules +        return indent(s:FindPrevLEIndentedLineMatchingRegex(a:lnum, +                    \                                       s:liststartregex)) +    elseif line =~# s:mapkeyregex +        " Same for line containing mapping key +        let prevmapline = s:FindPrevLEIndentedLineMatchingRegex(a:lnum, +                    \                                           s:mapkeyregex) +        if getline(prevmapline) =~# '^\s*- ' +            return indent(prevmapline) + 2 +        else +            return indent(prevmapline) +        endif +    elseif prevline =~# '^\s*- ' +        " - List with +        "   multiline scalar +        return previndent+2 +    elseif prevline =~# s:mapkeyregex . '\v\s*%(%('.s:c_ns_tag_property. +                \                              '\v|'.s:c_ns_anchor_property. +                \                              '\v|'.s:block_scalar_header. +                \                             '\v)%(\s+|\s*%(\#.*)?$))*' +        " Mapping with: value +        "     that is multiline scalar +        return previndent+shiftwidth() +    endif +    return previndent +endfunction + +let &cpo = s:save_cpo + +endif diff --git a/indent/zimbu.vim b/indent/zimbu.vim new file mode 100644 index 00000000..85883ca7 --- /dev/null +++ b/indent/zimbu.vim @@ -0,0 +1,132 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:	Zimbu +" Maintainer:	Bram Moolenaar <Bram@vim.org> +" Last Change:	2016 Jan 25 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") +   finish +endif +let b:did_indent = 1 + +setlocal ai nolisp nocin +setlocal indentexpr=GetZimbuIndent(v:lnum) +setlocal indentkeys=0{,0},!^F,o,O,0=ELSE,0=ELSEIF,0=CASE,0=DEFAULT,0=FINALLY + +" We impose recommended defaults: no Tabs, 'shiftwidth' = 2 +setlocal sw=2 et + +let b:undo_indent = "setl et< sw< ai< indentkeys< indentexpr=" + +" Only define the function once. +if exists("*GetZimbuIndent") +  finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Come here when loading the script the first time. + +let s:maxoff = 50	" maximum number of lines to look backwards for () + +func GetZimbuIndent(lnum) +  let prevLnum = prevnonblank(a:lnum - 1) +  if prevLnum == 0 +    " This is the first non-empty line, use zero indent. +    return 0 +  endif + +  " Taken from Python indenting: +  " If the previous line is inside parenthesis, use the indent of the starting +  " line. +  " Trick: use the non-existing "dummy" variable to break out of the loop when +  " going too far back. +  call cursor(prevLnum, 1) +  let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW', +	  \ "line('.') < " . (prevLnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|String\\|Char\\)$'") +  if parlnum > 0 +    let plindent = indent(parlnum) +    let plnumstart = parlnum +  else +    let plindent = indent(prevLnum) +    let plnumstart = prevLnum +  endif + + +  " When inside parenthesis: If at the first line below the parenthesis add +  " two 'shiftwidth', otherwise same as previous line. +  " i = (a +  "       + b +  "       + c) +  call cursor(a:lnum, 1) +  let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', +	  \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|String\\|Char\\)$'") +  if p > 0 +    if p == prevLnum +      " When the start is inside parenthesis, only indent one 'shiftwidth'. +      let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', +	  \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" +	  \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" +	  \ . " =~ '\\(Comment\\|String\\|Char\\)$'") +      if pp > 0 +	return indent(prevLnum) + shiftwidth() +      endif +      return indent(prevLnum) + shiftwidth() * 2 +    endif +    if plnumstart == p +      return indent(prevLnum) +    endif +    return plindent +  endif + +  let prevline = getline(prevLnum) +  let thisline = getline(a:lnum) + +  " If this line is not a comment and the previous one is then move the +  " previous line further back. +  if thisline !~ '^\s*#' +    while prevline =~ '^\s*#' +      let prevLnum = prevnonblank(prevLnum - 1) +      if prevLnum == 0 +	" Only comment lines before this, no indent +	return 0 +      endif +      let prevline = getline(prevLnum) +      let plindent = indent(prevLnum) +    endwhile +  endif + +  if prevline =~ '^\s*\(IF\|\|ELSEIF\|ELSE\|GENERATE_IF\|\|GENERATE_ELSEIF\|GENERATE_ELSE\|WHILE\|REPEAT\|TRY\|CATCH\|FINALLY\|FOR\|DO\|SWITCH\|CASE\|DEFAULT\|FUNC\|VIRTUAL\|ABSTRACT\|DEFINE\|REPLACE\|FINAL\|PROC\|MAIN\|NEW\|ENUM\|CLASS\|INTERFACE\|BITS\|MODULE\|SHARED\)\>' +    let plindent += shiftwidth() +  endif +  if thisline =~ '^\s*\(}\|ELSEIF\>\|ELSE\>\|CATCH\|FINALLY\|GENERATE_ELSEIF\>\|GENERATE_ELSE\>\|UNTIL\>\)' +    let plindent -= shiftwidth() +  endif +  if thisline =~ '^\s*\(CASE\>\|DEFAULT\>\)' && prevline !~ '^\s*SWITCH\>' +    let plindent -= shiftwidth() +  endif + +  " line up continued comment that started after some code +  "   String something   # comment comment +  "                      # comment +  if a:lnum == prevLnum + 1 && thisline =~ '^\s*#' && prevline !~ '^\s*#' +    let n = match(prevline, '#') +    if n > 1 +      let plindent = n +    endif +  endif + +  return plindent +endfunc + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/indent/zsh.vim b/indent/zsh.vim new file mode 100644 index 00000000..d8e3347d --- /dev/null +++ b/indent/zsh.vim @@ -0,0 +1,18 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vim') == -1 +   +" Vim indent file +" Language:             Zsh shell script +" Maintainer:           Christian Brabandt <cb@256bit.org> +" Previous Maintainer:  Nikolai Weibull <now@bitwi.se> +" Latest Revision:      2015-05-29 +" License:              Vim (see :h license) +" Repository:           https://github.com/chrisbra/vim-zsh + +if exists("b:did_indent") +  finish +endif + +" Same as sh indenting for now. +runtime! indent/sh.vim + +endif  | 
