" Vim indent file " Language: Teal " Adapted from https://github.com/tbastos/vim-lua and the default lua file " {{{ setup if exists("b:did_indent") finish endif let b:did_indent = 1 let s:cpo_save = &cpo set cpo&vim setlocal autoindent setlocal nosmartindent setlocal indentexpr=GetTealIndent(v:lnum) setlocal indentkeys+=0=end,0=until if exists("*GetTealIndent") finish endif " }}} " {{{ Patterns " [\t ] seems to be faster than \s let s:begin_block_open_patt = '\C^[\t ]*\%(if\|for\|while\|repeat\|else\|elseif\|do\|then\)\>' let s:end_block_open_patt = '\C\%((\|{\|then\|do\)[\t ]*$' let s:block_close_patt = '\C^[\t ]*\%(\%(end\|else\|elseif\|until\)\>\|}\|)\)' let s:middle_patt = '\C\<\%(function\|record\|enum\)\>' let s:ignore_patt = 'String$\|Comment$\|Type$' let s:starts_with_bin_op = '\C^[\t ]*\([<>=~^&|*/%+-.:]\|\%(or\|and\|is\|as\)\>\)' " }}} " {{{ Helpers function s:IsIgnorable(line_num, column) return synIDattr(synID(a:line_num, a:column, 1), 'name') =~# s:ignore_patt \ && !(getline(a:line_num) =~# '^[\t ]*\%(--\)\?\[=*\[') endfunction function s:PrevLineOfCode(line_num) let line_num = prevnonblank(a:line_num) while s:IsIgnorable(line_num, 1) let line_num = prevnonblank(line_num - 1) endwhile return line_num endfunction " strip comments function s:GetLineContent(line_num) " remove trailing -- ... let content = getline(a:line_num) return substitute(content, '--.*$', '', '') endfunction function s:MatchPatt(line_num, line_content, patt, prev_match) if a:prev_match != -1 return a:prev_match endif let match_index = match(a:line_content, a:patt) if match_index != -1 && \ synIDattr(synID(a:line_num, match_index+1, 1), "name") =~# s:ignore_patt let match_index = -1 endif return match_index endfunction " }}} " {{{ The Indent function function GetTealIndent(lnum) if s:IsIgnorable(a:lnum, 1) return indent(a:lnum - 1) endif let prev_line_num = s:PrevLineOfCode(a:lnum - 1) if prev_line_num == 0 return 0 endif let prev_line = s:GetLineContent(prev_line_num) let i = 0 let match_index = s:MatchPatt(prev_line_num, prev_line, s:begin_block_open_patt, -1) let match_index = s:MatchPatt(prev_line_num, prev_line, s:end_block_open_patt, match_index) let match_index = s:MatchPatt(prev_line_num, prev_line, s:middle_patt, match_index) " If the previous line opens a block (and doesnt close it), >> if match_index != -1 && prev_line !~# '\C\<\%(end\|until\)\>' let i += 1 endif " If the current line closes a block, << let curr_line = s:GetLineContent(a:lnum) let match_index = s:MatchPatt(a:lnum, curr_line, s:block_close_patt, -1) if match_index != -1 let i -= 1 endif " if line starts with bin op and previous line doesnt, >> let current_starts_with_bin_op = 0 let prev_starts_with_bin_op = 0 let match_index = s:MatchPatt(a:lnum, curr_line, s:starts_with_bin_op, -1) if match_index != -1 let current_starts_with_bin_op = 1 endif let match_index = s:MatchPatt(prev_line_num, prev_line, s:starts_with_bin_op, -1) if match_index != -1 let prev_starts_with_bin_op = 1 endif if current_starts_with_bin_op && !prev_starts_with_bin_op let i += 1 elseif !current_starts_with_bin_op && prev_starts_with_bin_op let i -= 1 endif if i > 1 let i = 1 " elseif i < -1 " let i = -1 endif return indent(prev_line_num) + (shiftwidth() * i) endfunction " }}} let &cpo = s:cpo_save unlet s:cpo_save