function! sj#go#SplitImports() let pattern = '^import\s\+\(\%(\k\+\s\+\)\=\%(".*"\)\)$' if getline('.') =~ pattern call sj#Keeppatterns('s/' . pattern . '/import (\r\1\r)/') normal! k== return 1 else return 0 endif endfunction function! sj#go#JoinImports() if getline('.') =~ '^import\s*($' && \ getline(line('.') + 1) =~ '^\s*\%(\k\+\s\+\)\=".*"$' && \ getline(line('.') + 2) =~ '^)$' call sj#Keeppatterns('s/^import (\_s\+\(\%(\k\+\s\+\)\=\(".*"\)\)\_s\+)$/import \1/') return 1 else return 0 endif endfunction function! sj#go#SplitVars() abort let pattern = '^\s*\(var\|type\|const\)\s\+[[:keyword:], ]\+=\=' if sj#SearchUnderCursor(pattern) <= 0 return 0 endif call search(pattern, 'Wce', line('.')) let line = getline('.') if line[col('.') - 1] == '=' " before and after = let lhs = sj#Trim(strpart(line, 0, col('.') - 1)) let rhs = sj#Ltrim(strpart(line, col('.'))) let values_parser = sj#argparser#go_vars#Construct(rhs) call values_parser.Process() let values = values_parser.args let comment = values_parser.comment else let [comment, comment_start, _] = matchstrpos(line, '\s*\%(\/\/.*\)\=$') if comment == "" let lhs = sj#Trim(line) else let lhs = sj#Trim(strpart(line, 0, comment_start)) endif let values = [] endif if len(values) > 0 && values[-1] =~ '[{([]\s*$' " the value is incomplete, so let's not attempt to split it return 0 endif let [prefix, _, prefix_end] = matchstrpos(lhs, '^\s*\(var\|type\|const\)\s\+') let lhs = strpart(lhs, prefix_end) let variables = [] let last_type = '' for variable in reverse(split(lhs, ',\s*')) let variable = sj#Trim(variable) let type = matchstr(variable, '^\k\+\s\+\zs\S.*$') if empty(type) && !empty(last_type) " No type, take the last one that we saw going backwards call add(variables, variable . ' ' . last_type) else let last_type = type call add(variables, variable) endif endfor call reverse(variables) let declarations = [] for i in range(0, len(variables) - 1) if i < len(values) call add(declarations, variables[i] . ' = ' . values[i]) else call add(declarations, variables[i]) endif endfor let replacement = prefix . "(\n" let replacement .= join(declarations, "\n") let replacement .= "\n)" if comment != '' let replacement .= ' ' . sj#Ltrim(comment) endif call sj#ReplaceMotion('_vg_', replacement) return 0 endfunction function! sj#go#JoinVars() abort let pattern = '^\s*\(var\|type\|const\)\s\+(' if sj#SearchUnderCursor(pattern) <= 0 return 0 endif call search(pattern, 'Wce', line('.')) let declarations = sj#TrimList(split(sj#GetMotion('vi('), "\n")) if len(declarations) == 1 " Only one line, so just join it as-is call sj#ReplaceMotion('va(', declarations[0]) return 1 endif let variables = [] let values = [] let types = [] for line in declarations let [lhs, _, match_end] = matchstrpos(line, '.\{-}\s*=\s*') if match_end > -1 let variable_description = matchstr(lhs, '.\{-}\ze\s*=\s*') let line = substitute(line, ',$', '', '') call add(values, strpart(line, match_end)) else let line = substitute(line, ',$', '', '') let variable_description = line endif let [variable, _, match_end] = matchstrpos(variable_description, '^\k\+\s*') let type = strpart(variable_description, match_end) call add(variables, { 'variable': sj#Rtrim(variable), 'type': type }) call add(types, type) endfor if len(variables) == 0 return 0 endif if len(uniq(types)) > 1 " We have assignment to values, but we also have different types, so it " can't be on one line return 0 endif " Handle var one, two string -> one should also get "string" let declarations = [] let index = 0 for entry in variables if empty(entry.type) || (len(variables) > index + 1 && entry.type ==# variables[index + 1].type) " This variable's type is the same as the next one's, so skip it call add(declarations, entry.variable) elseif empty(entry.type) call add(declarations, entry.variable) else call add(declarations, entry.variable . ' ' . entry.type) endif let index += 1 endfor let combined_declaration = join(declarations, ', ') if len(values) > 0 let combined_declaration .= ' = ' . join(values, ', ') endif call sj#ReplaceMotion('va(', combined_declaration) return 1 endfunction function! sj#go#SplitStruct() let [start, end] = sj#LocateBracesAroundCursor('{', '}', ['goString', 'goComment']) if start < 0 && end < 0 return 0 endif let args = sj#ParseJsonObjectBody(start + 1, end - 1) if len(args) == 0 return 0 endif for arg in args if arg !~ '^\k\+\s*:' " this is not really a struct instantiation return 0 end endfor call sj#ReplaceCols(start + 1, end - 1, "\n".join(args, ",\n").",\n") return 1 endfunction function! sj#go#JoinStructDeclaration() let start_lineno = line('.') let pattern = '^\s*type\s\+.*\s*\zsstruct\s*{$' if search(pattern, 'Wc', line('.')) <= 0 && \ search(pattern, 'Wcb', line('.')) <= 0 return 0 endif call sj#PushCursor() normal! f{% let end_lineno = line('.') if start_lineno == end_lineno " we haven't moved, brackets not found call sj#PopCursor() return 0 endif let arguments = [] for line in getbufline('%', start_lineno + 1, end_lineno - 1) let argument = substitute(line, ',$', '', '') let argument = sj#Trim(argument) if argument != '' call add(arguments, argument) endif endfor if len(arguments) == 0 let replacement = 'struct{}' else let replacement = 'struct{ ' . join(arguments, ', ') . ' }' endif call sj#PopCursor() call sj#ReplaceMotion('vf{%', replacement) return 1 endfunction function! sj#go#JoinStruct() let start_lineno = line('.') let pattern = '\k\+\s*{$' if search(pattern, 'Wc', line('.')) <= 0 && \ search(pattern, 'Wcb', line('.')) <= 0 return 0 endif call search(pattern, 'Wce', line('.')) normal! % let end_lineno = line('.') if start_lineno == end_lineno " we haven't moved, brackets not found return 0 endif let arguments = [] for line in getbufline('%', start_lineno + 1, end_lineno - 1) let argument = substitute(line, ',$', '', '') let argument = sj#Trim(argument) if argument !~ '^\k\+\s*:' " this is not really a struct instantiation return 0 end if sj#settings#Read('normalize_whitespace') let argument = substitute(argument, '^\k\+\zs:\s\+', ': ', 'g') endif call add(arguments, argument) endfor let replacement = '{' . join(arguments, ', ') . '}' call sj#ReplaceMotion('va{', replacement) return 1 endfunction function! sj#go#SplitSingleLineCurlyBracketBlock() let [start, end] = sj#LocateBracesAroundCursor('{', '}', ['goString', 'goComment']) if start < 0 && end < 0 return 0 endif let body = sj#GetMotion('vi{') if getline('.')[0:start - 1] =~# '\ 2 " more than one line between them, can't join return 0 endif normal! va{J return 1 endfunction function! sj#go#SplitFunc() let pattern = '^func\%(\s*(.\{-})\s*\)\=\s\+\k\+\zs(' if search(pattern, 'Wcn', line('.')) <= 0 && \ search(pattern, 'Wbcn', line('.')) <= 0 return 0 endif let split_type = '' let [start, end] = sj#LocateBracesAroundCursor('(', ')', ['goString', 'goComment']) if start > 0 let split_type = 'definition_list' else let [start, end] = sj#LocateBracesAroundCursor('{', '}', ['goString', 'goComment']) if start > 0 let split_type = 'function_body' endif endif if split_type == 'function_body' let contents = sj#Trim(sj#GetCols(start + 1, end - 1)) call sj#ReplaceCols(start + 1, end - 1, "\n".contents."\n") return 1 elseif split_type == 'definition_list' let parsed = sj#ParseJsonObjectBody(start + 1, end - 1) " Keep `a, b int` variable groups on the same line let arg_groups = [] let typed_arg_group = '' for elem in parsed if match(elem, '\s\+') != -1 let typed_arg_group .= elem call add(arg_groups, typed_arg_group) let typed_arg_group = '' else " not typed here, group it with later vars let typed_arg_group .= elem . ', ' endif endfor call sj#ReplaceCols(start + 1, end - 1, "\n".join(arg_groups, ",\n").",\n") return 1 else return 0 endif endfunction function! sj#go#SplitFuncCall() let [start, end] = sj#LocateBracesAroundCursor('(', ')', ['goString', 'goComment']) if start < 0 && end < 0 return 0 endif let args = sj#ParseJsonObjectBody(start + 1, end - 1) call sj#ReplaceCols(start + 1, end - 1, "\n".join(args, ",\n").",\n") return 1 endfunction function! sj#go#JoinFuncCallOrDefinition() let start_lineno = line('.') if search('($', 'Wc', line('.')) <= 0 return 0 endif if strpart(getline('.'), 0, col('.')) =~ '\(var\|type\|const\|import\)\s\+($' " This isn't a function call, it's a multiline var/const/type declaration return 0 endif normal! % let end_lineno = line('.') if start_lineno == end_lineno " we haven't moved, brackets not found return 0 endif let arguments = [] for line in getbufline('%', start_lineno + 1, end_lineno - 1) let argument = substitute(line, ',$', '', '') let argument = sj#Trim(argument) call add(arguments, argument) endfor let replacement = '(' . join(arguments, ', ') . ')' call sj#ReplaceMotion('va(', replacement) return 1 endfunction