Skip to content

Commit

Permalink
Merge branch 'master' into add-temple-extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
jbodah authored Sep 4, 2021
2 parents 725f878 + 821cfea commit 5ef8ae1
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Features:

* Syntax highlighting for Elixir and EEx files
* Filetype detection for `.ex`, `.exs`, `.eex`, `.leex`, and `.sface` files
* Filetype detection for `.ex`, `.exs`, `.eex`, `.heex`, `.leex`, and `.sface` files
* Automatic indentation
* Integration between Ecto projects and [vim-dadbod][] for running SQL queries
on defined Ecto repositories
Expand Down
110 changes: 110 additions & 0 deletions autoload/elixir/indent.vim
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,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',
Expand Down Expand Up @@ -65,6 +66,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)
Expand Down Expand Up @@ -156,6 +168,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
Expand Down
2 changes: 1 addition & 1 deletion doc/elixir.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ INTRODUCTION *elixir-introduction*
*elixir* provides Vim configuration files for Elixir http://elixir-lang.org/

* Syntax highlighting for Elixir and EEx files
* Filetype detection for `.ex`, `.exs`, `.eex`, `.leex`, and `.sface` files
* Filetype detection for `.ex`, `.exs`, `.eex`, `.heex`, `.leex`, and `.sface` files
* Automatic indentation
* Integration between Ecto projects and |vim-dadbod| for running SQL queries
on defined Ecto repositories
Expand Down
2 changes: 1 addition & 1 deletion ftdetect/elixir.vim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
au BufRead,BufNewFile *.ex,*.exs set filetype=elixir
au BufRead,BufNewFile *.eex,*.leex,*.sface,*.lexs set filetype=eelixir
au BufRead,BufNewFile *.eex,*.heex,*.leex,*.sface,.lexs set filetype=eelixir
au BufRead,BufNewFile mix.lock set filetype=elixir
au BufRead,BufNewFile * call s:DetectElixir()

Expand Down
5 changes: 4 additions & 1 deletion ftplugin/eelixir.vim
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ if !exists("b:eelixir_subtype")
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^eex\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^heex\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^leex\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^sface\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.sface\|\.leex\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.heex\|\.leex\|\.sface\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
endif
if b:eelixir_subtype == 'ex'
let b:eelixir_subtype = 'elixir'
Expand Down
2 changes: 1 addition & 1 deletion ftplugin/elixir.vim
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let &l:path =
\ &g:path
\ ], ',')
setlocal includeexpr=elixir#util#get_filename(v:fname)
setlocal suffixesadd=.ex,.exs,.eex,.leex,.sface,.erl,.xrl,.yrl,.hrl
setlocal suffixesadd=.ex,.exs,.eex,.heex,.leex,.sface,.erl,.xrl,.yrl,.hrl

let &l:define = 'def\(macro\|guard\|delegate\)\=p\='

Expand Down
2 changes: 1 addition & 1 deletion indent/elixir.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let b:did_indent = 1
setlocal indentexpr=elixir#indent(v:lnum)

setlocal indentkeys+==after,=catch,=do,=else,=end,=rescue,
setlocal indentkeys+=*<Return>,=->,=\|>,=<>,0},0],0)
setlocal indentkeys+=*<Return>,=->,=\|>,=<>,0},0],0),>

" TODO: @jbodah 2017-02-27: all operators should cause reindent when typed

Expand Down
Loading

0 comments on commit 5ef8ae1

Please sign in to comment.