forked from aniani/vim
		
	
		
			
	
	
		
			120 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
		
		
			
		
	
	
			120 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
|   | vim9script | ||
|  | 
 | ||
|  | # Vim indent plugin file | ||
|  | # Language: Odin | ||
|  | # Maintainer: Maxim Kim <habamax@gmail.com> | ||
|  | # Website: https://github.com/habamax/vim-odin | ||
|  | # Last Change: 2024-01-15 | ||
|  | 
 | ||
|  | if exists("b:did_indent") | ||
|  |     finish | ||
|  | endif | ||
|  | b:did_indent = 1 | ||
|  | 
 | ||
|  | b:undo_indent = 'setlocal cindent< cinoptions< cinkeys< indentexpr<' | ||
|  | 
 | ||
|  | setlocal cindent | ||
|  | setlocal cinoptions=L0,m1,(s,j1,J1,l1,+0,:0,#1 | ||
|  | setlocal cinkeys=0{,0},0),0],!^F,:,o,O | ||
|  | 
 | ||
|  | setlocal indentexpr=GetOdinIndent(v:lnum) | ||
|  | 
 | ||
|  | def PrevLine(lnum: number): number | ||
|  |     var plnum = lnum - 1 | ||
|  |     var pline: string | ||
|  |     while plnum > 1 | ||
|  |         plnum = prevnonblank(plnum) | ||
|  |         pline = getline(plnum) | ||
|  |         # XXX: take into account nested multiline /* /* */ */ comments | ||
|  |         if pline =~ '\*/\s*$' | ||
|  |             while getline(plnum) !~ '/\*' && plnum > 1 | ||
|  |                 plnum -= 1 | ||
|  |             endwhile | ||
|  |             if getline(plnum) =~ '^\s*/\*' | ||
|  |                 plnum -= 1 | ||
|  |             else | ||
|  |                 break | ||
|  |             endif | ||
|  |         elseif pline =~ '^\s*//' | ||
|  |             plnum -= 1 | ||
|  |         else | ||
|  |             break | ||
|  |         endif | ||
|  |     endwhile | ||
|  |     return plnum | ||
|  | enddef | ||
|  | 
 | ||
|  | def GetOdinIndent(lnum: number): number | ||
|  |     var plnum = PrevLine(lnum) | ||
|  |     var pline = getline(plnum) | ||
|  |     var pindent = indent(plnum) | ||
|  |     # workaround of cindent "hang" | ||
|  |     # if the previous line looks like: | ||
|  |     # : #{} | ||
|  |     # : #whatever{whateverelse} | ||
|  |     # and variations where : # { } are in the string | ||
|  |     # cindent(lnum) hangs | ||
|  |     if pline =~ ':\s\+#.*{.*}' | ||
|  |         return pindent | ||
|  |     endif | ||
|  | 
 | ||
|  |     var indent = cindent(lnum) | ||
|  |     var line = getline(lnum) | ||
|  | 
 | ||
|  |     if line =~ '^\s*#\k\+' | ||
|  |         if pline =~ '[{:]\s*$' | ||
|  |             indent = pindent + shiftwidth() | ||
|  |         else | ||
|  |             indent = pindent | ||
|  |         endif | ||
|  |     elseif pline =~ 'switch\s.*{\s*$' | ||
|  |         indent = pindent | ||
|  |     elseif pline =~ 'case\s*.*,\s*\(//.*\)\?$' # https://github.com/habamax/vim-odin/issues/8 | ||
|  |         indent = pindent + matchstr(pline, 'case\s*')->strcharlen() | ||
|  |     elseif line =~ '^\s*case\s\+.*,\s*$' | ||
|  |         indent = pindent - shiftwidth() | ||
|  |     elseif pline =~ 'case\s*.*:\s*\(//.*\)\?$' | ||
|  |         if line !~ '^\s*}\s*$' && line !~ '^\s*case[[:space:]:]' | ||
|  |             indent = pindent + shiftwidth() | ||
|  |         endif | ||
|  |     elseif pline =~ '^\s*@.*' && line !~ '^\s*}' | ||
|  |         indent = pindent | ||
|  |     elseif pline =~ ':[:=].*}\s*$' | ||
|  |         indent = pindent | ||
|  |     elseif pline =~ '^\s*}\s*$' | ||
|  |         if line !~ '^\s*}' && line !~ 'case\s*.*:\s*$' | ||
|  |             indent = pindent | ||
|  |         else | ||
|  |             indent = pindent - shiftwidth() | ||
|  |         endif | ||
|  |     elseif pline =~ '\S:\s*$' | ||
|  |         # looking up for a case something, | ||
|  |         #                       whatever, | ||
|  |         #                       anything: | ||
|  |         # ... 20 lines before | ||
|  |         for idx in range(plnum - 1, plnum - 21, -1) | ||
|  |             if plnum < 1 | ||
|  |                 break | ||
|  |             endif | ||
|  |             if getline(idx) =~ '^\s*case\s.*,\s*$' | ||
|  |                 indent = indent(idx) + shiftwidth() | ||
|  |                 break | ||
|  |             endif | ||
|  |         endfor | ||
|  |     elseif pline =~ '{[^{]*}\s*$' && line !~ '^\s*[})]\s*$' # https://github.com/habamax/vim-odin/issues/2 | ||
|  |         indent = pindent | ||
|  |     elseif pline =~ '^\s*}\s*$' # https://github.com/habamax/vim-odin/issues/3 | ||
|  |         # Find line with opening { and check if there is a label: | ||
|  |         # If there is, return indent of the closing } | ||
|  |         cursor(plnum, 1) | ||
|  |         silent normal! % | ||
|  |         var brlnum = line('.') | ||
|  |         var brline = getline('.') | ||
|  |         if plnum != brlnum && (brline =~ '^\s*\k\+:\s\+for' || brline =~ '^\s*\k\+\s*:=') | ||
|  |             indent = pindent | ||
|  |         endif | ||
|  |     endif | ||
|  | 
 | ||
|  |     return indent | ||
|  | enddef |