function! sj#elixir#SplitDoBlock() let [function_name, function_start, function_end, function_type] = \ sj#argparser#elixir#LocateFunction() if function_start < 0 return 0 endif let is_if = function_name == 'if' || function_name == 'unless' let parser = sj#argparser#elixir#Construct(function_start, function_end, getline('.')) call parser.Process() let do_body = '' let else_body = '' let args = [] for arg in parser.args if arg =~ '^do:' && do_body == '' let do_body = substitute(arg, '^do:\s*', '', '') elseif arg =~ '^else:' && is_if && else_body == '' let else_body = substitute(arg, '^else:\s*', '', '') else call add(args, arg) endif endfor if do_body == '' return 0 endif let line = getline('.') if is_if && function_type == 'with_round_braces' " skip the round brackets before the if-clause let new_line = strpart(line, 0, function_start - 2) . ' ' . join(args, ', ') else let new_line = strpart(line, 0, function_start - 1) . join(args, ', ') endif if function_end > 0 if is_if && function_type == 'with_round_braces' " skip the round brackets after the if-clause let new_line .= strpart(line, function_end + 1) else let new_line .= strpart(line, function_end) end else " we didn't detect an end, so it goes on to the end of the line endif if else_body != '' let do_block = " do\n" . do_body . "\nelse\n" . else_body . "\nend" else let do_block = " do\n" . do_body . "\nend" endif call sj#ReplaceLines(line('.'), line('.'), new_line . do_block) return 1 endfunction function! sj#elixir#JoinDoBlock() let do_pattern = '\s*do\s*\%(#.*\)\=$' let def_lineno = line('.') let def_line = getline(def_lineno) if def_line !~ do_pattern return 0 endif let [function_name, function_start, function_end, function_type] = \ sj#argparser#elixir#LocateFunction() if function_start < 0 return 0 endif let is_if = function_name == 'if' || function_name == 'unless' let body_lineno = line('.') + 1 let body_line = getline(body_lineno) if is_if && getline(line('.') + 2) =~ '^\s*else\>' let else_lineno = line('.') + 2 let else_line = getline(else_lineno) let else_body_lineno = line('.') + 3 let else_body_line = getline(else_body_lineno) let end_lineno = line('.') + 4 let end_line = getline(end_lineno) else let else_line = '' let end_lineno = line('.') + 2 let end_line = getline(end_lineno) endif if end_line !~ '^\s*end$' return 0 endif exe 'keeppatterns s/'.do_pattern.'//' if function_end < 0 let function_end = col('$') - 1 endif let args = sj#GetCols(function_start, function_end) let joined_args = ', do: '.sj#Trim(body_line) if else_line != '' let joined_args .= ', else: '.sj#Trim(else_body_line) endif call sj#ReplaceCols(function_start, function_end, args . joined_args) exe body_lineno.','.end_lineno.'delete _' return 1 endfunction function! sj#elixir#JoinCommaDelimitedItems() if getline('.') !~ ',\s*$' return 0 endif let start_lineno = line('.') let end_lineno = start_lineno let lineno = nextnonblank(start_lineno + 1) let line = getline(lineno) while lineno <= line('$') && line =~ ',\s*$' let end_lineno = lineno let lineno = nextnonblank(lineno + 1) let line = getline(lineno) endwhile let end_lineno = lineno call cursor(start_lineno, 0) exe "normal! V".(end_lineno - start_lineno)."jJ" return 1 endfunction function! sj#elixir#SplitArray() let [from, to] = sj#LocateBracesAroundCursor('[', ']', [ \ 'elixirInterpolationDelimiter', \ 'elixirString', \ 'elixirStringDelimiter', \ 'elixirSigilDelimiter', \ ]) if from < 0 return 0 endif let items = sj#ParseJsonObjectBody(from + 1, to - 1) if len(items) == 0 || to - from < 2 return 1 endif " substitute [1, 2, | tail] let items[-1] = substitute(items[-1], "\\(|[^>].*\\)", "\n\\1", "") let body = "[\n" . join(items, ",\n") . "\n]" call sj#ReplaceMotion('Va[', body) return 1 endfunction function! sj#elixir#JoinArray() normal! $ if getline('.')[col('.') - 1] != '[' return 0 endif let body = sj#Trim(sj#GetMotion('Vi[')) " remove trailing comma let body = substitute(body, ',\ze\_s*$', '', '') let items = split(body, ",\s*\n") if len(items) == 0 return 0 endif " join isolated | tail on the last line let items[-1] = substitute(items[-1], "[[:space:]]*\\(|[^>].*\\)", " \\1", "") let body = join(sj#TrimList(items), ', ') call sj#ReplaceMotion('Va[', '['.body.']') return 1 endfunction let s:pipe_pattern = '^\s*|>\s\+' let s:atom_pattern = ':\k\+' let s:module_pattern = '\k\%(\k\|\.\)*' let s:function_pattern = '\k\+[?!]\=' let s:atom_or_module_pattern = '\%(' . s:atom_pattern . '\.\|' . s:module_pattern . '\.\)\=' function! sj#elixir#SplitPipe() let line = getline('.') call sj#PushCursor() normal! 0f( let [function_name, function_start, function_end, function_type] = \ sj#argparser#elixir#LocateFunction() call sj#PopCursor() " We only support function calls that start at the beginning of the line " (accounting for whitespace) let prefix = strpart(line, 0, function_start - 1) let prefix_pattern = '^\s*' . s:atom_or_module_pattern . function_name . '\((\|\s\+\)$' if function_start < 0 || prefix !~ prefix_pattern return 0 endif let comment_pattern = '\s*\(#.*\)\=$' if function_end < 0 let comment_start = match(line, comment_pattern) if comment_start < 0 let rest = 'none' else let rest = strpart(line, comment_start) let function_end = comment_start endif else let rest = strpart(line, function_end + 1) if rest !~ '^' . comment_pattern return 0 endif end let parser = sj#argparser#elixir#Construct(function_start, function_end, line) call parser.Process() let args = parser.args let function_call = sj#Trim(strpart(line, 0, function_start - 2)) let result = args[0] . "\n|> " . function_call . '(' . join(args[1:], ', ') . ')' . rest call sj#ReplaceLines(line('.'), line('.'), result) return 1 endfunction function! sj#elixir#JoinPipe() call sj#PushCursor() let line = getline('.') if line !~ s:pipe_pattern normal! j let line = getline('.') endif let line_num = line('.') let prev_line = sj#Trim(getline(line_num - 1)) if line !~ s:pipe_pattern || prev_line =~ s:pipe_pattern call sj#PopCursor() return 0 endif let empty_args_pattern = s:pipe_pattern . '\(' . s:atom_or_module_pattern . s:function_pattern . '\)()' if line =~ empty_args_pattern let function_name = substitute(line, empty_args_pattern, '\1', '') let result = function_name . '(' . prev_line . ')' call sj#PopCursor() else normal! f(l let [function_name, function_start, function_end, function_type] = \ sj#argparser#elixir#LocateFunction() call sj#PopCursor() if function_start < 0 return 0 endif let parser = sj#argparser#elixir#Construct(function_start, function_end, line) call parser.Process() let args = parser.args let function_call = substitute(strpart(line, 0, function_start - 2), '|>\s\+', '', '') let result = function_call . '(' . prev_line . ', ' . join(args, ', ') . ')' endif call sj#ReplaceLines(line_num - 1, line_num, result) return 1 endfunction