Skip to content

Commit 1543e37

Browse files
committed
rework indent helpers and fix with indent
1 parent b916c00 commit 1543e37

File tree

4 files changed

+239
-72
lines changed

4 files changed

+239
-72
lines changed

autoload/elixir/indent.vim

Lines changed: 165 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,13 @@ function! elixir#indent#indent(lnum)
2121

2222
let handlers = [
2323
\'top_of_file',
24-
\'starts_with_end',
25-
\'starts_with_mid_or_end_block_keyword',
26-
\'following_trailing_do',
27-
\'following_trailing_rocket',
2824
\'following_trailing_binary_operator',
2925
\'starts_with_pipe',
3026
\'starts_with_close_bracket',
3127
\'starts_with_binary_operator',
32-
\'inside_nested_construct',
28+
\'inside_block',
3329
\'starts_with_comment',
30+
\'starts_with_end',
3431
\'inside_generic_block',
3532
\'follow_prev_nb'
3633
\]
@@ -296,41 +293,132 @@ endfunction
296293
" nested structure. For example, we might be in a function in a map in a
297294
" function, etc... so we need to first figure out what the innermost structure
298295
" is then forward execution to the proper handler
299-
function! elixir#indent#handle_inside_nested_construct(lnum, text, prev_nb_lnum, prev_nb_text)
296+
function! elixir#indent#handle_inside_block(lnum, text, prev_nb_lnum, prev_nb_text)
300297
let start_pattern = '\C\%(\<with\>\|\<if\>\|\<case\>\|\<cond\>\|\<try\>\|\<receive\>\|\<fn\>\|{\|\[\|(\)'
301298
let end_pattern = '\C\%(\<end\>\|\]\|}\|)\)'
302-
let pair_info = searchpairpos(start_pattern, '', end_pattern, 'bnW', "line('.') == " . line('.') . " || elixir#indent#searchpair_back_skip()", max([0, a:lnum - g:elixir_indent_max_lookbehind]))
299+
" hack - handle do: better
300+
let pair_info = searchpairpos(start_pattern, '', end_pattern, 'bnW', "line('.') == " . line('.') . " || elixir#indent#searchpair_back_skip() || getline(line('.')) =~ 'do:'", max([0, a:lnum - g:elixir_indent_max_lookbehind]))
303301
let pair_lnum = pair_info[0]
304302
let pair_col = pair_info[1]
305303
if pair_lnum != 0 || pair_col != 0
306304
let pair_text = getline(pair_lnum)
307305
let pair_char = pair_text[pair_col - 1]
308-
if pair_char == 'f'
309-
call s:debug("testing s:do_handle_inside_fn")
310-
return s:do_handle_inside_fn(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
306+
if pair_char == 'w'
307+
" Handle with
308+
call s:debug("testing s:do_handle_with")
309+
return s:do_handle_with(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
310+
elseif pair_char == 'i'
311+
" Handle if
312+
call s:debug("testing s:do_handle_if")
313+
return s:do_handle_if(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
314+
elseif pair_char == 'c' && pair_text[pair_col] == 'a'
315+
" Handle case
316+
call s:debug("testing s:do_handle_case")
317+
return s:do_handle_case(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
318+
elseif pair_char == 'c' && pair_text[pair_col] == 'o'
319+
" Handle cond
320+
call s:debug("testing s:do_handle_cond")
321+
return s:do_handle_cond(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
322+
elseif pair_char == 't'
323+
" Handle try
324+
call s:debug("testing s:do_handle_try")
325+
return s:do_handle_try(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
326+
elseif pair_char == 'r'
327+
" Handle receive
328+
call s:debug("testing s:do_handle_receive")
329+
return s:do_handle_receive(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
330+
elseif pair_char == 'f'
331+
" Handle fn
332+
call s:debug("testing s:do_handle_fn")
333+
return s:do_handle_fn(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
311334
elseif pair_char == '['
312-
call s:debug("testing s:do_handle_inside_square_brace")
313-
return s:do_handle_inside_square_brace(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
335+
" Handle [
336+
call s:debug("testing s:do_handle_square_brace")
337+
return s:do_handle_square_brace(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
314338
elseif pair_char == '{'
315-
call s:debug("testing s:do_handle_inside_curly_brace")
316-
return s:do_handle_inside_curly_brace(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
339+
" Handle {
340+
call s:debug("testing s:do_handle_curly_brace")
341+
return s:do_handle_curly_brace(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
317342
elseif pair_char == '('
318-
call s:debug("testing s:do_handle_inside_parens")
319-
return s:do_handle_inside_parens(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
320-
elseif pair_char == 'w'
321-
call s:debug("testing s:do_handle_inside_with")
322-
return s:do_handle_inside_with(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
343+
" Handle (
344+
call s:debug("testing s:do_handle_parens")
345+
return s:do_handle_parens(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
323346
else
324-
call s:debug("testing s:do_handle_inside_keyword_block")
325-
return s:do_handle_inside_keyword_block(pair_lnum, pair_col, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
347+
" Should never get hit!
348+
return -1
326349
end
327350
else
328351
return -1
329352
end
330353
endfunction
331354

332-
function! s:do_handle_inside_with(pair_lnum, pair_col, lnum, text, prev_nb_lnum, prev_nb_text)
333-
if a:pair_lnum == a:lnum
355+
function! s:do_handle_try(try_start_lnum, try_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
356+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
357+
call s:debug("current line is end")
358+
return indent(a:try_start_lnum)
359+
elseif s:starts_with(a:text, s:keyword('catch'), a:lnum)
360+
call s:debug("current line is catch")
361+
return indent(a:try_start_lnum)
362+
elseif s:starts_with(a:text, s:keyword('rescue'), a:lnum)
363+
call s:debug("current line is rescue")
364+
return indent(a:try_start_lnum)
365+
elseif s:starts_with(a:text, s:keyword('after'), a:lnum)
366+
call s:debug("current line is after")
367+
return indent(a:try_start_lnum)
368+
else
369+
if search(s:keyword('catch'), 'bnW', a:try_start_lnum) != 0
370+
call s:debug("in catch")
371+
return s:do_handle_pattern_match_block(a:try_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
372+
elseif search(s:keyword('rescue'), 'bnW', a:try_start_lnum) != 0
373+
call s:debug("in rescue")
374+
return s:do_handle_pattern_match_block(a:try_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
375+
else
376+
return indent(a:try_start_lnum) + s:sw()
377+
end
378+
end
379+
endfunction
380+
381+
function! s:do_handle_case(case_start_lnum, case_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
382+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
383+
call s:debug("current line is end")
384+
return indent(a:case_start_lnum)
385+
else
386+
call s:debug("in pattern match")
387+
return s:do_handle_pattern_match_block(a:case_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
388+
end
389+
endfunction
390+
391+
function! s:do_handle_cond(cond_start_lnum, cond_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
392+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
393+
call s:debug("current line is end")
394+
return indent(a:cond_start_lnum)
395+
else
396+
call s:debug("in pattern match")
397+
return s:do_handle_pattern_match_block(a:cond_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
398+
end
399+
endfunction
400+
401+
function! s:do_handle_receive(receive_start_lnum, receive_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
402+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
403+
call s:debug("current line is end")
404+
return indent(a:receive_start_lnum)
405+
elseif s:starts_with(a:text, s:keyword('after'), a:lnum)
406+
call s:debug("current line is after")
407+
return indent(a:receive_start_lnum)
408+
elseif a:receive_start_lnum == a:prev_nb_lnum
409+
call s:debug("prev nb line is receive")
410+
return indent(a:prev_nb_lnum) + s:sw()
411+
elseif s:starts_with(a:prev_nb_text, s:keyword('after'), a:prev_nb_lnum)
412+
call s:debug("prev nb line is after")
413+
return indent(a:prev_nb_lnum) + s:sw()
414+
else
415+
call s:debug("in pattern match")
416+
return s:do_handle_pattern_match_block(a:receive_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
417+
end
418+
endfunction
419+
420+
function! s:do_handle_with(with_start_lnum, with_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
421+
if a:with_start_lnum == a:lnum
334422
" This is the `with` line or an inline `with`/`do`
335423
call s:debug("current line is `with`")
336424
return -1
@@ -347,90 +435,108 @@ function! s:do_handle_inside_with(pair_lnum, pair_col, lnum, text, prev_nb_lnum,
347435

348436
if s:starts_with(a:text, '\Cdo:', a:lnum)
349437
call s:debug("current line is do:")
350-
return pair_col - 1 + s:sw()
438+
return a:with_start_col - 1 + s:sw()
351439
elseif s:starts_with(a:text, '\Celse:', a:lnum)
352440
call s:debug("current line is else:")
353441
return pair_col - 1
442+
elseif s:starts_with(a:text, '\Cend', a:lnum)
443+
call s:debug("current line is end")
444+
return a:with_start_col - 1
354445
elseif s:starts_with(a:text, '\C\(\<do\>\|\<else\>\)', a:lnum)
355446
call s:debug("current line is do/else")
356-
return pair_col - 1
447+
return a:with_start_col - 1
357448
elseif s:starts_with(pair_text, '\C\(do\|else\):', pair_lnum)
358449
call s:debug("inside do:/else:")
359450
return pair_col - 1 + s:sw()
360451
elseif pair_char == 'w'
361452
call s:debug("inside with/do")
362-
return pair_col + 4
453+
return a:with_start_col + 4
363454
elseif pair_char == 'd'
364455
call s:debug("inside do/else|end")
365-
return pair_col - 1 + s:sw()
456+
return a:with_start_col - 1 + s:sw()
366457
else
367458
call s:debug("inside else/end")
368-
return s:do_handle_inside_pattern_match_block(pair_lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
459+
return s:do_handle_pattern_match_block(pair_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
369460
end
370461
end
371462
endfunction
372463

373-
function! s:do_handle_inside_keyword_block(pair_lnum, _pair_col, _lnum, text, prev_nb_lnum, prev_nb_text)
374-
let keyword_pattern = '\C\%(\<case\>\|\<cond\>\|\<try\>\|\<receive\>\|\<after\>\|\<catch\>\|\<rescue\>\|\<else\>\)'
375-
if a:pair_lnum
376-
" last line is a "receive" or something
377-
if s:starts_with(a:prev_nb_text, keyword_pattern, a:prev_nb_lnum)
378-
call s:debug("prev nb line is keyword")
379-
return indent(a:prev_nb_lnum) + s:sw()
380-
else
381-
return s:do_handle_inside_pattern_match_block(a:pair_lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
382-
end
464+
function! s:do_handle_if(if_start_lnum, if_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
465+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
466+
call s:debug("current line is end")
467+
return indent(a:if_start_lnum)
468+
elseif s:starts_with(a:text, s:keyword('else'), a:lnum)
469+
call s:debug("current line is else")
470+
return indent(a:if_start_lnum)
383471
else
384-
return -1
385-
endif
472+
call s:debug("current line is nested inside if")
473+
return indent(a:if_start_lnum) + s:sw()
474+
end
386475
endfunction
387476

388477
" Implements indent for pattern-matching blocks (e.g. case, fn, with/else)
389-
function! s:do_handle_inside_pattern_match_block(block_start_lnum, text, prev_nb_lnum, prev_nb_text)
390-
if a:text =~ '->'
391-
call s:debug("current line contains ->")
478+
function! s:do_handle_pattern_match_block(block_start_lnum, lnum, text, prev_nb_lnum, prev_nb_text)
479+
call s:debug("running s:do_handle_pattern_match_block")
480+
" hack!
481+
if a:text =~ '\(fn.*\)\@<!->'
482+
call s:debug("current line contains ->; assuming match definition")
392483
return indent(a:block_start_lnum) + s:sw()
393-
elseif a:prev_nb_text =~ '->'
394-
call s:debug("prev nb line contains ->")
484+
elseif a:prev_nb_text =~ '\(fn.*\)\@<!->'
485+
call s:debug("prev nb line contains ->; assuming first line of match handler")
395486
return indent(a:prev_nb_lnum) + s:sw()
396487
else
488+
call s:debug("assuming match handler; returning previous indent")
397489
return indent(a:prev_nb_lnum)
398490
end
399491
endfunction
400492

401-
function! s:do_handle_inside_fn(pair_lnum, _pair_col, lnum, text, prev_nb_lnum, prev_nb_text)
402-
if a:pair_lnum && a:pair_lnum != a:lnum
403-
return s:do_handle_inside_pattern_match_block(a:pair_lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
493+
function! s:do_handle_fn(fn_start_lnum, _fn_start_col, lnum, text, prev_nb_lnum, prev_nb_text)
494+
if s:starts_with(a:text, s:keyword('end'), a:lnum)
495+
call s:debug("current line is end")
496+
return indent(a:fn_start_lnum)
497+
elseif s:ends_with(a:prev_nb_text, '->', a:prev_nb_lnum)
498+
if a:prev_nb_lnum == a:fn_start_lnum
499+
call s:debug("prev line is fn that ends with ->")
500+
return indent(a:fn_start_lnum) + s:sw()
501+
else
502+
call s:debug("prev line ends with -> but is not fn declaration")
503+
return indent(a:prev_nb_lnum) + s:sw()
504+
endif
505+
elseif s:starts_with(a:text, s:keyword('end'), a:lnum)
506+
call s:debug("starts with end; returning indent of line " . a:fn_start_lnum)
507+
return indent(a:fn_start_lnum)
508+
elseif a:fn_start_lnum && a:fn_start_lnum != a:lnum
509+
return s:do_handle_pattern_match_block(a:fn_start_lnum, a:lnum, a:text, a:prev_nb_lnum, a:prev_nb_text)
404510
else
405511
return -1
406512
endif
407513
endfunction
408514

409-
function! s:do_handle_inside_square_brace(pair_lnum, pair_col, _lnum, _text, _prev_nb_lnum, _prev_nb_text)
515+
function! s:do_handle_square_brace(brace_start_lnum, brace_start_col, _lnum, _text, _prev_nb_lnum, _prev_nb_text)
410516
" If in list...
411-
if a:pair_lnum != 0 || a:pair_col != 0
412-
let pair_text = getline(a:pair_lnum)
413-
let substr = strpart(pair_text, a:pair_col, len(pair_text)-1)
517+
if a:brace_start_lnum != 0 || a:brace_start_col != 0
518+
let brace_start_text = getline(a:brace_start_lnum)
519+
let substr = strpart(brace_start_text, a:brace_start_col, len(brace_start_text)-1)
414520
let indent_pos = match(substr, '\S')
415521
if indent_pos != -1
416-
return indent_pos + a:pair_col
522+
return indent_pos + a:brace_start_col
417523
else
418-
return indent(a:pair_lnum) + s:sw()
524+
return indent(a:brace_start_lnum) + s:sw()
419525
endif
420526
else
421527
return -1
422528
end
423529
endfunction
424530

425-
function! s:do_handle_inside_curly_brace(pair_lnum, _pair_col, _lnum, _text, _prev_nb_lnum, _prev_nb_text)
426-
return indent(a:pair_lnum) + s:sw()
531+
function! s:do_handle_curly_brace(brace_start_lnum, _brace_start_col, _lnum, _text, _prev_nb_lnum, _prev_nb_text)
532+
return indent(a:brace_start_lnum) + s:sw()
427533
endfunction
428534

429-
function! s:do_handle_inside_parens(pair_lnum, pair_col, _lnum, _text, prev_nb_lnum, prev_nb_text)
430-
if a:pair_lnum
535+
function! s:do_handle_parens(paren_start_lnum, paren_start_col, _lnum, _text, prev_nb_lnum, prev_nb_text)
536+
if a:paren_start_lnum
431537
if s:ends_with(a:prev_nb_text, '(', a:prev_nb_lnum)
432538
return indent(a:prev_nb_lnum) + s:sw()
433-
elseif a:pair_lnum == a:prev_nb_lnum
539+
elseif a:paren_start_lnum == a:prev_nb_lnum
434540
" Align indent (e.g. "def add(a,")
435541
let pos = s:find_last_pos(a:prev_nb_lnum, a:prev_nb_text, '[^(]\+,')
436542
if pos == -1

spec/indent/basic_spec.rb

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -538,26 +538,24 @@ def hi do
538538
EOF
539539

540540
i <<~EOF
541-
fun1 = fn
542-
(:foo) ->
543-
:bar
544-
:end
541+
fun2 = fn :foo ->
542+
:bar
543+
'end'
545544
end
545+
546546
EOF
547547

548548
i <<~EOF
549-
fun2 = fn
550-
(:foo) ->
551-
:bar
552-
'end'
549+
fun2 = fn :foo ->
550+
:bar
551+
'end'
553552
end
554553
EOF
555554

556555
i <<~EOF
557-
fun3 = fn
558-
(:foo) ->
559-
:bar
560-
:send
556+
fun3 = fn :foo ->
557+
:bar
558+
:send
561559
end
562560
EOF
563561
end

spec/indent/blocks_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def hello do
123123
EOF
124124

125125
i <<~EOF
126-
def handle_info(:tick, state = %{policy_iteration: []) do
126+
def handle_info(:tick, state = %{policy_iteration: []}) do
127127
state = put_in(state[:policy_iteration], state.policy)
128128
{:noreply, state}
129129
end

0 commit comments

Comments
 (0)