summaryrefslogtreecommitdiffstats
path: root/autoload/elixir/indent.vim
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2021-09-09 12:05:33 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2021-09-09 12:05:33 +0200
commit7f98e949d4922ba2109304bd4cabe9578a8062fb (patch)
treee1b08f862397c14ab799e8f277c6fc39ec48b3b6 /autoload/elixir/indent.vim
parentce31cd1d2f4e8eee9fd91325e4599f15cb9566fd (diff)
downloadvim-polyglot-7f98e949d4922ba2109304bd4cabe9578a8062fb.tar.gz
vim-polyglot-7f98e949d4922ba2109304bd4cabe9578a8062fb.zip
Update
Diffstat (limited to 'autoload/elixir/indent.vim')
-rw-r--r--autoload/elixir/indent.vim110
1 files changed, 110 insertions, 0 deletions
diff --git a/autoload/elixir/indent.vim b/autoload/elixir/indent.vim
index c9adcd0a..ccf388b7 100644
--- a/autoload/elixir/indent.vim
+++ b/autoload/elixir/indent.vim
@@ -24,6 +24,7 @@ function! elixir#indent#indent(lnum)
call cursor(lnum, 0)
let handlers = [
+ \'inside_embedded_view',
\'top_of_file',
\'starts_with_string_continuation',
\'following_trailing_binary_operator',
@@ -69,6 +70,17 @@ function! s:prev_starts_with(context, expr)
return s:_starts_with(a:context.prev_nb_text, a:expr, a:context.prev_nb_lnum)
endfunction
+function! s:in_embedded_view()
+ let groups = map(synstack(line('.'), col('.')), "synIDattr(v:val, 'name')")
+ for group in ['elixirPhoenixESigil', 'elixirLiveViewSigil', 'elixirSurfaceSigil']
+ if index(groups, group) >= 0
+ return 1
+ endif
+ endfor
+
+ return 0
+endfunction
+
" Returns 0 or 1 based on whether or not the text starts with the given
" expression and is not a string or comment
function! s:_starts_with(text, expr, lnum)
@@ -160,6 +172,104 @@ function! s:find_last_pos(lnum, text, match)
return -1
endfunction
+function! elixir#indent#handle_inside_embedded_view(context)
+ if !s:in_embedded_view()
+ return -1
+ endif
+
+ " Multi-line Surface data delimiters
+ let pair_lnum = searchpair('{{', '', '}}', 'bW', "line('.') == ".a:context.lnum." || s:is_string_or_comment(line('.'), col('.'))", max([0, a:context.lnum - g:elixir_indent_max_lookbehind]))
+ if pair_lnum
+ if a:context.text =~ '}}$'
+ return indent(pair_lnum)
+ elseif a:context.text =~ '}}*>$'
+ return -1
+ elseif s:prev_ends_with(a:context, '[\|%{')
+ return indent(a:context.prev_nb_lnum) + s:sw()
+ elseif a:context.prev_nb_text =~ ',$'
+ return indent(a:context.prev_nb_lnum)
+ else
+ return indent(pair_lnum) + s:sw()
+ endif
+ endif
+
+ " Multi-line opening tag -- >, />, or %> are on a different line that their opening <
+ let pair_lnum = searchpair('^\s\+<.*[^>]$', '', '^[^<]*[/%}]\?>$', 'bW', "line('.') == ".a:context.lnum." || s:is_string_or_comment(line('.'), col('.'))", max([0, a:context.lnum - g:elixir_indent_max_lookbehind]))
+ if pair_lnum
+ if a:context.text =~ '^\s\+\%\(>\|\/>\|%>\|}}>\)$'
+ call s:debug("current line is a lone >, />, or %>")
+ return indent(pair_lnum)
+ elseif a:context.text =~ '\%\(>\|\/>\|%>\|}}>\)$'
+ call s:debug("current line ends in >, />, or %>")
+ if s:prev_ends_with(a:context, ',')
+ return indent(a:context.prev_nb_lnum)
+ else
+ return -1
+ endif
+ else
+ call s:debug("in the body of a multi-line opening tag")
+ return indent(pair_lnum) + s:sw()
+ endif
+ endif
+
+ " Special cases
+ if s:prev_ends_with(a:context, '^[^<]*do\s%>')
+ call s:debug("prev line closes a multi-line do block")
+ return indent(a:context.prev_nb_lnum)
+ elseif a:context.prev_nb_text =~ 'do\s*%>$'
+ call s:debug("prev line opens a do block")
+ return indent(a:context.prev_nb_lnum) + s:sw()
+ elseif a:context.text =~ '^\s\+<\/[a-zA-Z0-9\.\-_]\+>\|<% end %>'
+ call s:debug("a single closing tag")
+ if a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>.*<\/[a-zA-Z0-9\.\-_]\+>$'
+ call s:debug("opening and closing tags are on the same line")
+ return indent(a:context.prev_nb_lnum) - s:sw()
+ elseif a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>\|\s\+>'
+ call s:debug("prev line is opening html tag or single >")
+ return indent(a:context.prev_nb_lnum)
+ elseif s:prev_ends_with(a:context, '^[^<]*\%\(do\s\)\@<!%>')
+ call s:debug("prev line closes a multi-line eex tag")
+ return indent(a:context.prev_nb_lnum) - 2 * s:sw()
+ else
+ return indent(a:context.prev_nb_lnum) - s:sw()
+ endif
+ elseif a:context.text =~ '^\s*<%\s*\%(end\|else\|catch\|rescue\)\>.*%>'
+ call s:debug("eex middle or closing eex tag")
+ return indent(a:context.prev_nb_lnum) - s:sw()
+ elseif a:context.prev_nb_text =~ '\s*<\/\|<% end %>$'
+ call s:debug("prev is closing tag")
+ return indent(a:context.prev_nb_lnum)
+ elseif a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>.*<\/[a-zA-Z0-9\.\-_]\+>$'
+ call s:debug("opening and closing tags are on the same line")
+ return indent(a:context.prev_nb_lnum)
+ elseif s:prev_ends_with(a:context, '\s\+\/>')
+ call s:debug("prev ends with a single \>")
+ return indent(a:context.prev_nb_lnum)
+ elseif s:prev_ends_with(a:context, '^[^<]*\/>')
+ call s:debug("prev line is closing a multi-line self-closing tag")
+ return indent(a:context.prev_nb_lnum) - s:sw()
+ elseif s:prev_ends_with(a:context, '^\s\+<.*\/>')
+ call s:debug("prev line is closing self-closing tag")
+ return indent(a:context.prev_nb_lnum)
+ elseif a:context.prev_nb_text =~ '^\s\+%\?>$'
+ call s:debug("prev line is a single > or %>")
+ return indent(a:context.prev_nb_lnum) + s:sw()
+ endif
+
+ " Simple HTML (ie, opening tag is not split across lines)
+ let pair_lnum = searchpair('^\s\+<[^%\/].*[^\/>]>$', '', '^\s\+<\/\w\+>$', 'bW', "line('.') == ".a:context.lnum." || s:is_string_or_comment(line('.'), col('.'))", max([0, a:context.lnum - g:elixir_indent_max_lookbehind]))
+ if pair_lnum
+ call s:debug("simple HTML")
+ if a:context.text =~ '^\s\+<\/\w\+>$'
+ return indent(pair_lnum)
+ else
+ return indent(pair_lnum) + s:sw()
+ endif
+ endif
+
+ return -1
+endfunction
+
function! elixir#indent#handle_top_of_file(context)
if a:context.prev_nb_lnum == 0
return 0