mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 05:40:05 +08:00
234 lines
5.5 KiB
VimL
234 lines
5.5 KiB
VimL
scriptencoding utf-8
|
|
let s:save_cpo = &cpo
|
|
set cpo&vim
|
|
|
|
|
|
" Workaround issues #12
|
|
function! s:escape_substitute_sub(str)
|
|
return substitute(a:str, '&', '\\&', "g")
|
|
endfunction
|
|
|
|
|
|
function! s:extend_list(list)
|
|
return empty(a:list) ? {}
|
|
\ : len(a:list) == 1 ? a:list[0]
|
|
\ : extend(deepcopy(a:list[0]), s:extend_list(a:list[1:]))
|
|
endfunction
|
|
|
|
|
|
|
|
function! jplus#getchar()
|
|
let c = nr2char(getchar())
|
|
return c =~ '[[:print:]]' ? c : ""
|
|
endfunction
|
|
|
|
|
|
function! s:join_list(list, c, ignore, left_match, right_match)
|
|
let list = filter(a:list, 'len(v:val) && !(a:ignore != "" && (v:val =~ a:ignore))')
|
|
|
|
if empty(list)
|
|
return []
|
|
endif
|
|
|
|
let result = list[0]
|
|
for i in list[1:]
|
|
let result = matchstr(result, a:left_match) . a:c . matchstr(i, a:right_match)
|
|
endfor
|
|
return result
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:add_comment_leader_pattern(current_pattern)
|
|
if &formatoptions !~ 'j'
|
|
return a:current_pattern
|
|
endif
|
|
|
|
let flags = '\(^:\|m\)'
|
|
let to_consider = filter(split(&comments, ','), 'v:val =~ flags')
|
|
call map(to_consider, 'split(v:val, ":")[-1]')
|
|
|
|
if len(to_consider) == 0
|
|
return a:current_pattern
|
|
endif
|
|
|
|
" Escape special characters
|
|
let to_escape = '\([*.]\)'
|
|
let replace_with = '\\\1'
|
|
call map(to_consider, 'substitute(v:val, to_escape, replace_with, "g")')
|
|
|
|
" Construct patterns
|
|
let before = '^\s*'
|
|
let after = '\s*\zs.*'
|
|
call map(to_consider, 'before . v:val . after')
|
|
|
|
" Note: a:current_pattern MUST come at the end since it might contain '.*'
|
|
" in the pattern, which will match even to comment leaders
|
|
return '\%(' . join(to_consider, '\|') . '\|' . a:current_pattern . '\)'
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:join(config)
|
|
let ignore = a:config.ignore_pattern
|
|
let left_matchstr = a:config.left_matchstr_pattern
|
|
let right_matchstr = s:add_comment_leader_pattern(a:config.right_matchstr_pattern)
|
|
let delimiter = s:escape_substitute_sub(a:config.delimiter)
|
|
let c = substitute(a:config.delimiter_format, '%d', delimiter, "g")
|
|
let start = a:config.firstline
|
|
let lastline = a:config.firstline + a:config.line_num
|
|
let end = lastline + (start == lastline)
|
|
|
|
if end > line("$")
|
|
return
|
|
endif
|
|
|
|
let line = s:join_list(getline(start, end), c, ignore, left_matchstr, right_matchstr)
|
|
|
|
let view = winsaveview()
|
|
let new_col = len(line) - len(matchstr(getline(end), right_matchstr))
|
|
let view['col'] = new_col - 1
|
|
call setline(start, line)
|
|
|
|
if start+1 <= end
|
|
silent execute start+1 . ',' . end 'delete _'
|
|
endif
|
|
|
|
if end <= line("$")
|
|
normal! -1
|
|
endif
|
|
call winrestview(view)
|
|
endfunction
|
|
|
|
|
|
|
|
let g:jplus#default_config = {
|
|
\ "_" : {
|
|
\ "left_matchstr_pattern" : '.\{-}\ze\s*$',
|
|
\ "right_matchstr_pattern" : '\s*\zs.*',
|
|
\ "ignore_pattern" : '',
|
|
\ "delimiter" : " ",
|
|
\ "delimiter_format" : "%d",
|
|
\ },
|
|
\ "bash" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\ "c" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\ "cpp" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\ "ruby" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\ "python" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\ "vim" : {
|
|
\ "right_matchstr_pattern" : '^\s*\\\s*\zs.*\|\s*\zs.*',
|
|
\ },
|
|
\ "zsh" : {
|
|
\ "left_matchstr_pattern" : '^.\{-}\%(\ze\s*\\$\|$\)',
|
|
\ },
|
|
\}
|
|
|
|
|
|
let g:jplus#config = get(g:, "jplus#config", {})
|
|
|
|
function! jplus#get_config(filetype, ...)
|
|
return s:extend_list([
|
|
\ get(g:jplus#default_config, "_", {}),
|
|
\ get(g:jplus#config, "_", {}),
|
|
\ get(g:jplus#default_config, a:filetype, {}),
|
|
\ get(g:jplus#config, a:filetype, {}),
|
|
\ get(a:, 1, {})
|
|
\ ])
|
|
endfunction
|
|
|
|
|
|
let g:jplus#input_config = get(g:, "jplus#input_config", {})
|
|
|
|
function! jplus#get_input_config(input, filetype, ...)
|
|
let empty_keyword = a:input ==# "" ? "__EMPTY__" : a:input
|
|
return s:extend_list([
|
|
\ get(g:jplus#default_config, "_", {}),
|
|
\ get(g:jplus#config, "_", {}),
|
|
\ get(g:jplus#input_config, "__DEFAULT__", {}),
|
|
\ get(g:jplus#default_config, a:filetype, {}),
|
|
\ get(g:jplus#config, a:filetype, {}),
|
|
\ { "delimiter" : a:input },
|
|
\ get(g:jplus#input_config, empty_keyword, {}),
|
|
\ get(a:, 1, {})
|
|
\ ])
|
|
endfunction
|
|
|
|
|
|
function! jplus#join(config) range
|
|
if &modifiable == 0
|
|
return
|
|
endif
|
|
let config = extend({
|
|
\ "firstline" : a:firstline,
|
|
\ "line_num" : a:lastline - a:firstline,
|
|
\ }, a:config)
|
|
let s:latest_config = a:config
|
|
let s:latest_config.line_num = config.line_num
|
|
let &operatorfunc = "jplus#operatorfunc_latest_repeat"
|
|
call feedkeys("g@g@", "n")
|
|
" execute "normal!" (mode() =~# "[vV\<C-v>]") ? "g@" : "g@g@"
|
|
endfunction
|
|
|
|
|
|
function! jplus#join_latest_repeat()
|
|
if exists("s:latest_config")
|
|
let config = extend({
|
|
\ "firstline" : a:firstline,
|
|
\ "line_num" : a:lastline - a:firstline,
|
|
\ }, s:latest_config)
|
|
call s:join(config)
|
|
endif
|
|
endfunction
|
|
|
|
|
|
function! jplus#mapexpr_join(...)
|
|
let g:jplus_tmp_config = get(a:, 1, {})
|
|
return ":call jplus#join(g:jplus_tmp_c, g:jplus_tmp_config)\<CR>"
|
|
endfunction
|
|
|
|
|
|
function! s:operatorfunc(wise, ...)
|
|
let base = get(a:, 1, {})
|
|
let first = getpos("'[")[1]
|
|
let last = getpos("']")[1]
|
|
let config = base
|
|
call jplus#join(extend({
|
|
\ "firstline" : first,
|
|
\ "lastline" : last,
|
|
\ }, config))
|
|
endfunction
|
|
|
|
|
|
function! jplus#operatorfunc(wise)
|
|
return s:operatorfunc(a:wise, jplus#get_config(&filetype))
|
|
endfunction
|
|
|
|
|
|
function! jplus#operatorfunc_input(wise)
|
|
return s:operatorfunc(a:wise, jplus#get_input_config(input("Input joint delimiter : "), &filetype))
|
|
endfunction
|
|
|
|
|
|
function! jplus#operatorfunc_getchar(wise)
|
|
return s:operatorfunc(a:wise, jplus#get_input_config(jplus#getchar(), &filetype))
|
|
endfunction
|
|
|
|
|
|
function! jplus#operatorfunc_latest_repeat(...)
|
|
return jplus#join_latest_repeat()
|
|
endfunction
|
|
|
|
|
|
let &cpo = s:save_cpo
|
|
unlet s:save_cpo
|