1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-02 22:20:06 +08:00
SpaceVim/bundle/splitjoin.vim/autoload/sj/go.vim
2024-06-27 18:10:36 +08:00

406 lines
10 KiB
VimL

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] =~# '\<struct\s*{$'
" struct { is enforced by gofmt
let padding = ' '
else
let padding = ''
endif
call sj#ReplaceMotion('va{', padding."{\n".sj#Trim(body)."\n}")
return 1
endfunction
function! sj#go#JoinSingleLineFunctionBody()
let start_lineno = line('.')
if search('{$', 'Wc', line('.')) <= 0
return 0
endif
normal! %
let end_lineno = line('.')
if start_lineno == end_lineno
" we haven't moved, brackets not found
return 0
endif
if end_lineno - start_lineno > 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