| 
									
										
										
										
											2012-12-05 19:01:43 +01:00
										 |  |  | " Vim indent file | 
					
						
							|  |  |  | " Language:         YAML | 
					
						
							|  |  |  | " Maintainer:       Nikolai Pavlov <zyx.vim@gmail.com> | 
					
						
							| 
									
										
										
										
											2015-11-10 21:15:48 +01:00
										 |  |  | " Last Change:	    2015 Nov 01 | 
					
						
							| 
									
										
										
										
											2012-12-05 19:01:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | " 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) | 
					
						
							| 
									
										
										
										
											2015-11-10 21:15:48 +01:00
										 |  |  | setlocal indentkeys=!^F,o,O,0#,0},0],<:>,0- | 
					
						
							| 
									
										
										
										
											2012-12-05 19:01:43 +01:00
										 |  |  | setlocal nosmartindent | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | " Only define the function once. | 
					
						
							|  |  |  | if exists('*GetYAMLIndent') | 
					
						
							|  |  |  |     finish | 
					
						
							|  |  |  | endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if exists('*shiftwidth') | 
					
						
							|  |  |  |     let s:shiftwidth = function('shiftwidth') | 
					
						
							|  |  |  | else | 
					
						
							|  |  |  |     function s:shiftwidth() | 
					
						
							|  |  |  |         return &shiftwidth | 
					
						
							|  |  |  |     endfunction | 
					
						
							|  |  |  | 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*%(\''%([^'']|'''')*\'''. | 
					
						
							|  |  |  |                 \        '|\"%([^"\\]|\\.)*\"'. | 
					
						
							|  |  |  |                 \        '|%(%(\:\ )@!.)*)\:%(\ |$)' | 
					
						
							|  |  |  | let s:liststartregex='\v^\s*%(\-%(\ |$))' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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+s: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 | 
					
						
							| 
									
										
										
										
											2015-09-25 20:34:21 +02:00
										 |  |  |         let prevmapline = s:FindPrevLEIndentedLineMatchingRegex(a:lnum, | 
					
						
							|  |  |  |                     \                                           s:mapkeyregex) | 
					
						
							|  |  |  |         if getline(prevmapline) =~# '^\s*- ' | 
					
						
							|  |  |  |             return indent(prevmapline) + 2 | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return indent(prevmapline) | 
					
						
							|  |  |  |         endif | 
					
						
							| 
									
										
										
										
											2012-12-05 19:01:43 +01:00
										 |  |  |     elseif prevline =~# '^\s*- ' | 
					
						
							|  |  |  |         " - List with | 
					
						
							|  |  |  |         "   multiline scalar | 
					
						
							|  |  |  |         return previndent+2 | 
					
						
							|  |  |  |     elseif prevline =~# s:mapkeyregex | 
					
						
							|  |  |  |         " Mapping with: value | 
					
						
							|  |  |  |         "     that is multiline scalar | 
					
						
							|  |  |  |         return previndent+s:shiftwidth() | 
					
						
							|  |  |  |     endif | 
					
						
							|  |  |  |     return previndent | 
					
						
							|  |  |  | endfunction | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let &cpo = s:save_cpo |