1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 02:10:05 +08:00
SpaceVim/bundle/vim-teal/indent/teal.vim
2022-04-23 17:28:53 +08:00

132 lines
3.3 KiB
VimL

" 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