Skip to content

Commit 5ef8ae1

Browse files
authored
Merge branch 'master' into add-temple-extensions
2 parents 725f878 + 821cfea commit 5ef8ae1

File tree

10 files changed

+394
-7
lines changed

10 files changed

+394
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Features:
1010

1111
* Syntax highlighting for Elixir and EEx files
12-
* Filetype detection for `.ex`, `.exs`, `.eex`, `.leex`, and `.sface` files
12+
* Filetype detection for `.ex`, `.exs`, `.eex`, `.heex`, `.leex`, and `.sface` files
1313
* Automatic indentation
1414
* Integration between Ecto projects and [vim-dadbod][] for running SQL queries
1515
on defined Ecto repositories

autoload/elixir/indent.vim

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function! elixir#indent#indent(lnum)
2020
call cursor(lnum, 0)
2121

2222
let handlers = [
23+
\'inside_embedded_view',
2324
\'top_of_file',
2425
\'starts_with_string_continuation',
2526
\'following_trailing_binary_operator',
@@ -65,6 +66,17 @@ function! s:prev_starts_with(context, expr)
6566
return s:_starts_with(a:context.prev_nb_text, a:expr, a:context.prev_nb_lnum)
6667
endfunction
6768

69+
function! s:in_embedded_view()
70+
let groups = map(synstack(line('.'), col('.')), "synIDattr(v:val, 'name')")
71+
for group in ['elixirPhoenixESigil', 'elixirLiveViewSigil', 'elixirSurfaceSigil']
72+
if index(groups, group) >= 0
73+
return 1
74+
endif
75+
endfor
76+
77+
return 0
78+
endfunction
79+
6880
" Returns 0 or 1 based on whether or not the text starts with the given
6981
" expression and is not a string or comment
7082
function! s:_starts_with(text, expr, lnum)
@@ -156,6 +168,104 @@ function! s:find_last_pos(lnum, text, match)
156168
return -1
157169
endfunction
158170

171+
function! elixir#indent#handle_inside_embedded_view(context)
172+
if !s:in_embedded_view()
173+
return -1
174+
endif
175+
176+
" Multi-line Surface data delimiters
177+
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]))
178+
if pair_lnum
179+
if a:context.text =~ '}}$'
180+
return indent(pair_lnum)
181+
elseif a:context.text =~ '}}*>$'
182+
return -1
183+
elseif s:prev_ends_with(a:context, '[\|%{')
184+
return indent(a:context.prev_nb_lnum) + s:sw()
185+
elseif a:context.prev_nb_text =~ ',$'
186+
return indent(a:context.prev_nb_lnum)
187+
else
188+
return indent(pair_lnum) + s:sw()
189+
endif
190+
endif
191+
192+
" Multi-line opening tag -- >, />, or %> are on a different line that their opening <
193+
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]))
194+
if pair_lnum
195+
if a:context.text =~ '^\s\+\%\(>\|\/>\|%>\|}}>\)$'
196+
call s:debug("current line is a lone >, />, or %>")
197+
return indent(pair_lnum)
198+
elseif a:context.text =~ '\%\(>\|\/>\|%>\|}}>\)$'
199+
call s:debug("current line ends in >, />, or %>")
200+
if s:prev_ends_with(a:context, ',')
201+
return indent(a:context.prev_nb_lnum)
202+
else
203+
return -1
204+
endif
205+
else
206+
call s:debug("in the body of a multi-line opening tag")
207+
return indent(pair_lnum) + s:sw()
208+
endif
209+
endif
210+
211+
" Special cases
212+
if s:prev_ends_with(a:context, '^[^<]*do\s%>')
213+
call s:debug("prev line closes a multi-line do block")
214+
return indent(a:context.prev_nb_lnum)
215+
elseif a:context.prev_nb_text =~ 'do\s*%>$'
216+
call s:debug("prev line opens a do block")
217+
return indent(a:context.prev_nb_lnum) + s:sw()
218+
elseif a:context.text =~ '^\s\+<\/[a-zA-Z0-9\.\-_]\+>\|<% end %>'
219+
call s:debug("a single closing tag")
220+
if a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>.*<\/[a-zA-Z0-9\.\-_]\+>$'
221+
call s:debug("opening and closing tags are on the same line")
222+
return indent(a:context.prev_nb_lnum) - s:sw()
223+
elseif a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>\|\s\+>'
224+
call s:debug("prev line is opening html tag or single >")
225+
return indent(a:context.prev_nb_lnum)
226+
elseif s:prev_ends_with(a:context, '^[^<]*\%\(do\s\)\@<!%>')
227+
call s:debug("prev line closes a multi-line eex tag")
228+
return indent(a:context.prev_nb_lnum) - 2 * s:sw()
229+
else
230+
return indent(a:context.prev_nb_lnum) - s:sw()
231+
endif
232+
elseif a:context.text =~ '^\s*<%\s*\%(end\|else\|catch\|rescue\)\>.*%>'
233+
call s:debug("eex middle or closing eex tag")
234+
return indent(a:context.prev_nb_lnum) - s:sw()
235+
elseif a:context.prev_nb_text =~ '\s*<\/\|<% end %>$'
236+
call s:debug("prev is closing tag")
237+
return indent(a:context.prev_nb_lnum)
238+
elseif a:context.prev_nb_text =~ '^\s\+<[^%\/]*[^/]>.*<\/[a-zA-Z0-9\.\-_]\+>$'
239+
call s:debug("opening and closing tags are on the same line")
240+
return indent(a:context.prev_nb_lnum)
241+
elseif s:prev_ends_with(a:context, '\s\+\/>')
242+
call s:debug("prev ends with a single \>")
243+
return indent(a:context.prev_nb_lnum)
244+
elseif s:prev_ends_with(a:context, '^[^<]*\/>')
245+
call s:debug("prev line is closing a multi-line self-closing tag")
246+
return indent(a:context.prev_nb_lnum) - s:sw()
247+
elseif s:prev_ends_with(a:context, '^\s\+<.*\/>')
248+
call s:debug("prev line is closing self-closing tag")
249+
return indent(a:context.prev_nb_lnum)
250+
elseif a:context.prev_nb_text =~ '^\s\+%\?>$'
251+
call s:debug("prev line is a single > or %>")
252+
return indent(a:context.prev_nb_lnum) + s:sw()
253+
endif
254+
255+
" Simple HTML (ie, opening tag is not split across lines)
256+
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]))
257+
if pair_lnum
258+
call s:debug("simple HTML")
259+
if a:context.text =~ '^\s\+<\/\w\+>$'
260+
return indent(pair_lnum)
261+
else
262+
return indent(pair_lnum) + s:sw()
263+
endif
264+
endif
265+
266+
return -1
267+
endfunction
268+
159269
function! elixir#indent#handle_top_of_file(context)
160270
if a:context.prev_nb_lnum == 0
161271
return 0

doc/elixir.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ INTRODUCTION *elixir-introduction*
1919
*elixir* provides Vim configuration files for Elixir http://elixir-lang.org/
2020

2121
* Syntax highlighting for Elixir and EEx files
22-
* Filetype detection for `.ex`, `.exs`, `.eex`, `.leex`, and `.sface` files
22+
* Filetype detection for `.ex`, `.exs`, `.eex`, `.heex`, `.leex`, and `.sface` files
2323
* Automatic indentation
2424
* Integration between Ecto projects and |vim-dadbod| for running SQL queries
2525
on defined Ecto repositories

ftdetect/elixir.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
au BufRead,BufNewFile *.ex,*.exs set filetype=elixir
2-
au BufRead,BufNewFile *.eex,*.leex,*.sface,*.lexs set filetype=eelixir
2+
au BufRead,BufNewFile *.eex,*.heex,*.leex,*.sface,.lexs set filetype=eelixir
33
au BufRead,BufNewFile mix.lock set filetype=elixir
44
au BufRead,BufNewFile * call s:DetectElixir()
55

ftplugin/eelixir.vim

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ if !exists("b:eelixir_subtype")
1919
if b:eelixir_subtype == ''
2020
let b:eelixir_subtype = matchstr(&filetype,'^eex\.\zs\w\+')
2121
endif
22+
if b:eelixir_subtype == ''
23+
let b:eelixir_subtype = matchstr(&filetype,'^heex\.\zs\w\+')
24+
endif
2225
if b:eelixir_subtype == ''
2326
let b:eelixir_subtype = matchstr(&filetype,'^leex\.\zs\w\+')
2427
endif
2528
if b:eelixir_subtype == ''
2629
let b:eelixir_subtype = matchstr(&filetype,'^sface\.\zs\w\+')
2730
endif
2831
if b:eelixir_subtype == ''
29-
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.sface\|\.leex\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
32+
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.heex\|\.leex\|\.sface\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
3033
endif
3134
if b:eelixir_subtype == 'ex'
3235
let b:eelixir_subtype = 'elixir'

ftplugin/elixir.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ let &l:path =
2929
\ &g:path
3030
\ ], ',')
3131
setlocal includeexpr=elixir#util#get_filename(v:fname)
32-
setlocal suffixesadd=.ex,.exs,.eex,.leex,.sface,.erl,.xrl,.yrl,.hrl
32+
setlocal suffixesadd=.ex,.exs,.eex,.heex,.leex,.sface,.erl,.xrl,.yrl,.hrl
3333

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

indent/elixir.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ let b:did_indent = 1
66
setlocal indentexpr=elixir#indent(v:lnum)
77

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

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

0 commit comments

Comments
 (0)