From 2e8843eb3d0068c0e526e09040331dbb922b03ed Mon Sep 17 00:00:00 2001 From: Wang Shidong Date: Sun, 4 Feb 2018 22:01:16 +0800 Subject: [PATCH] Replace mode for flygrep (#1340) --- .travis.yml | 1 - autoload/SpaceVim/api/data/string.vim | 24 +- autoload/SpaceVim/api/file.vim | 25 ++ autoload/SpaceVim/api/vim/highlight.vim | 2 +- autoload/SpaceVim/layers/core/statusline.vim | 2 +- autoload/SpaceVim/layers/git.vim | 2 +- autoload/SpaceVim/mapping/guide/theme/one.vim | 2 + autoload/SpaceVim/plugins/flygrep.vim | 27 +- autoload/SpaceVim/plugins/iedit.vim | 301 ++++++++++++------ test/api/data/string.vader | 12 + 10 files changed, 279 insertions(+), 119 deletions(-) create mode 100644 test/api/data/string.vader diff --git a/.travis.yml b/.travis.yml index 1a3469e60..bdefa5f47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: python - dist: trusty sudo: false diff --git a/autoload/SpaceVim/api/data/string.vim b/autoload/SpaceVim/api/data/string.vim index 86137312e..424061cc2 100644 --- a/autoload/SpaceVim/api/data/string.vim +++ b/autoload/SpaceVim/api/data/string.vim @@ -72,14 +72,24 @@ function! s:string2chars(str) abort endfunction let s:file['string2chars'] = function('s:string2chars') -function! s:strAllIndex(str, need) abort - let rst = [] +function! s:strAllIndex(str, need, use_expr) abort + if a:use_expr + let rst = [] + let idx = matchstrpos(a:str, a:need) + while idx[1] != -1 + call add(rst, [idx[1], idx[2]]) + let idx = matchstrpos(a:str, a:need, idx[2]) + endwhile + return rst + else + let rst = [] let idx = match(a:str, "\\<" . a:need . "\\>") - while idx != -1 - call add(rst, idx) - let idx = match(a:str, "\\<" . a:need . "\\>", idx + 1 + len(a:need)) - endwhile - return rst + while idx != -1 + call add(rst, [idx, idx+len(a:need)]) + let idx = match(a:str, "\\<" . a:need . "\\>", idx + 1 + len(a:need)) + endwhile + return rst + endif endfunction let s:file['strAllIndex'] = function('s:strAllIndex') diff --git a/autoload/SpaceVim/api/file.vim b/autoload/SpaceVim/api/file.vim index 410086c8c..11fb0f1fd 100644 --- a/autoload/SpaceVim/api/file.vim +++ b/autoload/SpaceVim/api/file.vim @@ -189,6 +189,31 @@ endfunction let s:file['ls'] = function('s:ls') +" +" { +" 'filename' : { +" line1 : content, +" line2 : content, +" } +" } +function! s:updatefiles(files) abort + let failed = [] + for fname in keys(a:files) + let buffer = readfile(fname) + for line in keys(a:files[fname]) + let buffer[line - 1] = a:files[fname][line] + endfor + try + call writefile(buffer, fname, 'b') + catch + call add(failed, fname) + endtry + endfor + return failed +endfunction + +let s:file['updateFiles'] = function('s:updatefiles') + function! SpaceVim#api#file#get() abort return deepcopy(s:file) endfunction diff --git a/autoload/SpaceVim/api/vim/highlight.vim b/autoload/SpaceVim/api/vim/highlight.vim index af094a960..90f2be9fe 100644 --- a/autoload/SpaceVim/api/vim/highlight.vim +++ b/autoload/SpaceVim/api/vim/highlight.vim @@ -58,7 +58,7 @@ function! s:self.hi(info) abort let cmd .= ' guifg=' . a:info.guifg endif let style = [] - for sty in ['hold', 'italic', 'underline'] + for sty in ['bold', 'italic', 'underline'] if get(a:info, sty, '') ==# '1' call add(style, sty) endif diff --git a/autoload/SpaceVim/layers/core/statusline.vim b/autoload/SpaceVim/layers/core/statusline.vim index f9bd0e87f..60b43e3c8 100644 --- a/autoload/SpaceVim/layers/core/statusline.vim +++ b/autoload/SpaceVim/layers/core/statusline.vim @@ -359,7 +359,7 @@ function! SpaceVim#layers#core#statusline#get(...) abort \ . '%#SpaceVim_statusline_b_SpaceVim_statusline_c#' . s:lsep . ' ' \ . '%#SpaceVim_statusline_c# %{unite#get_status_string()} ' elseif &filetype ==# 'SpaceVimFlyGrep' - return '%#SpaceVim_statusline_a_bold# FlyGrep %#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep + return '%#SpaceVim_statusline_a_bold# FlyGrep%{SpaceVim#plugins#flygrep#mode()} %#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep \ . '%#SpaceVim_statusline_b# %{getcwd()} %#SpaceVim_statusline_b_SpaceVim_statusline_c#' . s:lsep \ . '%#SpaceVim_statusline_c# %{SpaceVim#plugins#flygrep#lineNr()}' elseif &filetype ==# 'TransientState' diff --git a/autoload/SpaceVim/layers/git.vim b/autoload/SpaceVim/layers/git.vim index 9b059b42d..577b12bde 100644 --- a/autoload/SpaceVim/layers/git.vim +++ b/autoload/SpaceVim/layers/git.vim @@ -16,7 +16,7 @@ endfunction function! SpaceVim#layers#git#config() abort let g:_spacevim_mappings_space.g = get(g:_spacevim_mappings_space, 'g', {'name' : '+VersionControl/git'}) if has('patch-8.0.0027') || has('nvim') - call SpaceVim#mapping#space#def('nnoremap', ['g', 's'], 'Gina status', 'git status', 1) + call SpaceVim#mapping#space#def('nnoremap', ['g', 's'], 'Gina status --opener=10split', 'git status', 1) call SpaceVim#mapping#space#def('nnoremap', ['g', 'S'], 'Gina add %', 'stage current file', 1) call SpaceVim#mapping#space#def('nnoremap', ['g', 'U'], 'Gina reset -q %', 'unstage current file', 1) call SpaceVim#mapping#space#def('nnoremap', ['g', 'c'], 'Gina commit', 'edit git commit', 1) diff --git a/autoload/SpaceVim/mapping/guide/theme/one.vim b/autoload/SpaceVim/mapping/guide/theme/one.vim index 0fc1851f1..17b9dd2bc 100644 --- a/autoload/SpaceVim/mapping/guide/theme/one.vim +++ b/autoload/SpaceVim/mapping/guide/theme/one.vim @@ -7,5 +7,7 @@ function! SpaceVim#mapping#guide#theme#one#palette() abort \ ['#2c323c', '#afd7d7', 114, 152], \ ['#2c323c', '#ff8787', 114, 210], \ ['#2c323c', '#d75f5f', 114, 167], + \ ['#2c323c', '#689d6a', 114, 72], + \ ['#2c323c', '#8f3f71', 114, 132], \ ] endfunction diff --git a/autoload/SpaceVim/plugins/flygrep.vim b/autoload/SpaceVim/plugins/flygrep.vim index 40640488b..31a190c97 100644 --- a/autoload/SpaceVim/plugins/flygrep.vim +++ b/autoload/SpaceVim/plugins/flygrep.vim @@ -16,7 +16,8 @@ let s:grepid = 0 " grep local funcs:{{{ " @vimlint(EVL103, 1, a:timer) function! s:grep_timer(timer) abort - let cmd = s:get_search_cmd(join(split(s:grep_expr), '.*')) + let s:current_grep_pattern = join(split(s:grep_expr), '.*') + let cmd = s:get_search_cmd(s:current_grep_pattern) call SpaceVim#logger#info('grep cmd: ' . string(cmd)) let s:grepid = s:JOB.start(cmd, { \ 'on_stdout' : function('s:grep_stdout'), @@ -63,6 +64,8 @@ let s:MPT._handle_fly = function('s:flygrep') " @vimlint(EVL103, 0, a:timer) let s:filter_file = '' function! s:start_filter() abort + let s:mode = 'f' + redrawstatus let s:MPT._handle_fly = function('s:filter') let s:MPT._prompt = { \ 'mpt' : s:MPT._prompt.mpt, @@ -112,6 +115,20 @@ function! s:get_filter_cmd(expr) abort endfunction " }}} +let s:mode = '' +" replace local funcs {{{ +function! s:start_replace() abort + let s:mode = 'r' + try + call matchdelete(s:hi_id) + catch + endtr + redrawstatus + let replace_text = s:current_grep_pattern + call SpaceVim#plugins#iedit#start({'expr' : replace_text}) +endfunction +" }}} + " API: MPT._prompt {{{ let s:MPT._prompt.mpt = '➭ ' " }}} @@ -260,6 +277,7 @@ let s:MPT._function_key = { \ "\" : function('s:move_cursor'), \ "\<2-LeftMouse>" : function('s:double_click'), \ "\" : function('s:start_filter'), + \ "\" : function('s:start_replace'), \ } if has('nvim') @@ -284,7 +302,7 @@ endif " files: files for grep, @buffers means listed buffer. " dir: specific a directory for grep function! SpaceVim#plugins#flygrep#open(agrv) abort - noautocmd rightbelow split __flygrep__ + rightbelow split __flygrep__ setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber let save_tve = &t_ve setlocal t_ve= @@ -322,4 +340,9 @@ function! SpaceVim#plugins#flygrep#lineNr() abort return line('.') . '/' . line('$') endif endfunction + +function! SpaceVim#plugins#flygrep#mode() + return empty(s:mode) ? '' : '(' . s:mode . ')' +endfunction + " }}} diff --git a/autoload/SpaceVim/plugins/iedit.vim b/autoload/SpaceVim/plugins/iedit.vim index 988242890..d9a77c5d8 100644 --- a/autoload/SpaceVim/plugins/iedit.vim +++ b/autoload/SpaceVim/plugins/iedit.vim @@ -13,17 +13,29 @@ let s:mode = '' let s:hi_id = '' let s:Operator = '' -" prompt - -let s:symbol_begin = '' -let s:symbol_cursor = '' -let s:symbol_end = '' - let s:VIMH = SpaceVim#api#import('vim#highlight') let s:STRING = SpaceVim#api#import('data#string') let s:cursor_stack = [] +let s:iedit_hi_info = [ + \ { + \ 'name' : 'IeditPurpleBold', + \ 'guibg' : '', + \ 'guifg' : '#d3869b', + \ 'ctermbg' : '', + \ 'ctermfg' : 175, + \ 'bold' : 1, + \ }, + \ { + \ 'name' : 'IeditBlueBold', + \ 'guibg' : '', + \ 'guifg' : '#83a598', + \ 'ctermbg' : '', + \ 'ctermfg' : 109, + \ 'bold' : 1, + \ } + \ ] function! s:highlight_cursor() abort let info = { @@ -35,9 +47,13 @@ function! s:highlight_cursor() abort \ } hi def link SpaceVimGuideCursor Cursor call s:VIMH.hi(info) - for pos in s:stack - call matchaddpos('Underlined', [pos]) - call matchadd('SpaceVimGuideCursor', '\%' . pos[0] . 'l\%' . (pos[1] + len(s:symbol_begin)) . 'c', 99999) + for i in range(len(s:stack)) + if i == s:index + call matchaddpos('IeditPurpleBold', [s:stack[i]]) + else + call matchaddpos('IeditBlueBold', [s:stack[i]]) + endif + call matchadd('SpaceVimGuideCursor', '\%' . s:stack[i][0] . 'l\%' . (s:stack[i][1] + len(s:cursor_stack[i].begin)) . 'c', 99999) endfor endfunction @@ -50,24 +66,38 @@ function! SpaceVim#plugins#iedit#start(...) let save_cl = &l:cursorline setlocal nocursorline setlocal t_ve= + call s:VIMH.hi(s:iedit_hi_info[0]) + call s:VIMH.hi(s:iedit_hi_info[1]) let s:mode = 'n' let w:spacevim_iedit_mode = s:mode let w:spacevim_statusline_mode = 'in' let curpos = getcurpos() + let argv = get(a:000, 0, '') let save_reg_k = @k - if get(a:000, 0, 0) == 1 + let use_expr = 0 + if !empty(argv) && type(argv) == 4 + if has_key(argv, 'expr') + let use_expr = 1 + let symbol = argv.expr + elseif has_key(argv, 'word') + let symbol = argv.word + endif + elseif type(argv) == 0 && argv == 1 normal! gv"ky + let symbol = split(@k, "\n")[0] else normal! viw"ky + let symbol = split(@k, "\n")[0] endif - call setpos('.', curpos) - let symbol = split(@k, "\n")[0] let @k = save_reg_k - echomsg string(a:000) - echom symbol + call setpos('.', curpos) let begin = get(a:000, 1, 1) let end = get(a:000, 2, line('$')) - call s:parse_symbol(begin, end, symbol) + if use_expr + call s:parse_symbol(begin, end, symbol, 1) + else + call s:parse_symbol(begin, end, symbol) + endif call s:highlight_cursor() redrawstatus! while s:mode != '' @@ -116,55 +146,75 @@ function! s:handle_normal(char) abort redrawstatus! elseif a:char == 9 " if index(keys(s:toggle_stack), s:index . '') == -1 - call extend(s:toggle_stack, {s:index : s:stack[s:index]}) + call extend(s:toggle_stack, {s:index : [s:stack[s:index], s:cursor_stack[s:index]]}) call remove(s:stack, s:index) + call remove(s:cursor_stack, s:index) else - call insert(s:stack, s:toggle_stack[s:index] , s:index) + call insert(s:stack, s:toggle_stack[s:index][0] , s:index) + call insert(s:cursor_stack, s:toggle_stack[s:index][1] , s:index) call remove(s:toggle_stack, s:index) endif elseif a:char == 97 " a let s:mode = 'i' let w:spacevim_iedit_mode = s:mode let w:spacevim_statusline_mode = 'ii' - let s:symbol_begin = s:symbol_begin . s:symbol_cursor - let s:symbol_cursor = matchstr(s:symbol_end, '^.') - let s:symbol_end = substitute(s:symbol_end, '^.', '', 'g') + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = s:cursor_stack[i].begin . s:cursor_stack[i].cursor + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].end, '^.') + let s:cursor_stack[i].end = substitute(s:cursor_stack[i].end, '^.', '', 'g') + endfor redrawstatus! elseif a:char == "\" - let s:symbol_end = s:symbol_cursor . s:symbol_end - let s:symbol_cursor = matchstr(s:symbol_begin, '.$') - let s:symbol_begin = substitute(s:symbol_begin, '.$', '', 'g') + for i in range(len(s:cursor_stack)) + if !empty(s:cursor_stack[i].begin) + let s:cursor_stack[i].end = s:cursor_stack[i].cursor . s:cursor_stack[i].end + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].begin, '.$') + let s:cursor_stack[i].begin = substitute(s:cursor_stack[i].begin, '.$', '', 'g') + endif + endfor elseif a:char == "\" - let s:symbol_begin = s:symbol_begin . s:symbol_cursor - let s:symbol_cursor = matchstr(s:symbol_end, '^.') - let s:symbol_end = substitute(s:symbol_end, '^.', '', 'g') + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = s:cursor_stack[i].begin . s:cursor_stack[i].cursor + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].end, '^.') + let s:cursor_stack[i].end = substitute(s:cursor_stack[i].end, '^.', '', 'g') + endfor elseif a:char == 48 " 0 - let s:symbol_end = substitute(s:symbol_begin . s:symbol_cursor . s:symbol_end, '^.', '', 'g') - let s:symbol_cursor = matchstr(s:symbol_begin, '^.') - let s:symbol_begin = '' + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].end = substitute(s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end , '^.', '', 'g') + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].begin, '^.') + let s:cursor_stack[i].begin = '' + endfor elseif a:char == 36 " $ - let s:symbol_begin = substitute(s:symbol_begin . s:symbol_cursor . s:symbol_end, '.$', '', 'g') - let s:symbol_cursor = matchstr(s:symbol_end, '.$') - let s:symbol_end = '' + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = substitute(s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end , '.$', '', 'g') + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].end, '.$') + let s:cursor_stack[i].end = '' + endfor elseif a:char == 68 " D - let s:symbol_begin = '' - let s:symbol_cursor = '' - let s:symbol_end = '' - call s:replace_symbol(s:symbol_begin . s:symbol_cursor . s:symbol_end) + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = '' + let s:cursor_stack[i].cursor = '' + let s:cursor_stack[i].end = '' + endfor + call s:replace_symbol() elseif a:char == 112 " p - let s:symbol_begin = @" - let s:symbol_cursor = '' - let s:symbol_end = '' - call s:replace_symbol(s:symbol_begin . s:symbol_cursor . s:symbol_end) + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = @" + let s:cursor_stack[i].cursor = '' + let s:cursor_stack[i].end = '' + endfor + call s:replace_symbol() elseif a:char == 83 " S - let s:symbol_begin = '' - let s:symbol_cursor = '' - let s:symbol_end = '' + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = '' + let s:cursor_stack[i].cursor = '' + let s:cursor_stack[i].end = '' + endfor let s:mode = 'i' let w:spacevim_iedit_mode = s:mode let w:spacevim_statusline_mode = 'ii' redrawstatus! - call s:replace_symbol(s:symbol_begin . s:symbol_cursor . s:symbol_end) + call s:replace_symbol() elseif a:char == 71 " G exe s:stack[-1][0] elseif a:char == 103 "g @@ -181,14 +231,14 @@ function! s:handle_normal(char) abort else let s:index += 1 endif - call cursor(s:stack[s:index][0], s:stack[s:index][1] + len(s:symbol_begin)) + call cursor(s:stack[s:index][0], s:stack[s:index][1] + len(s:cursor_stack[s:index].begin)) elseif a:char == 78 " N if s:index == 0 let s:index = len(s:stack) - 1 else let s:index -= 1 endif - call cursor(s:stack[s:index][0], s:stack[s:index][1] + len(s:symbol_begin)) + call cursor(s:stack[s:index][0], s:stack[s:index][1] + len(s:cursor_stack[s:index].begin)) endif silent! call s:highlight_cursor() endfunction @@ -217,87 +267,126 @@ function! s:handle_insert(char) abort redraw! redrawstatus! return - elseif a:char == 23 - let s:symbol_begin = '' - elseif a:char == 11 - let s:symbol_cursor = '' - let s:symbol_end = '' + elseif a:char == 23 " + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = '' + endfor + elseif a:char == 11 " + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].cursor = '' + let s:cursor_stack[i].end = '' + endfor elseif a:char == "\" - let s:symbol_begin = substitute(s:symbol_begin, '.$', '', 'g') + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = substitute(s:cursor_stack[i].begin, '.$', '', 'g') + endfor elseif a:char == "\" - let s:symbol_end = s:symbol_cursor . s:symbol_end - let s:symbol_cursor = matchstr(s:symbol_begin, '.$') - let s:symbol_begin = substitute(s:symbol_begin, '.$', '', 'g') + for i in range(len(s:cursor_stack)) + if !empty(s:cursor_stack[i].begin) + let s:cursor_stack[i].end = s:cursor_stack[i].cursor . s:cursor_stack[i].end + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].begin, '.$') + let s:cursor_stack[i].begin = substitute(s:cursor_stack[i].begin, '.$', '', 'g') + endif + endfor elseif a:char == "\" - let s:symbol_begin = s:symbol_begin . s:symbol_cursor - let s:symbol_cursor = matchstr(s:symbol_end, '^.') - let s:symbol_end = substitute(s:symbol_end, '^.', '', 'g') + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin = s:cursor_stack[i].begin . s:cursor_stack[i].cursor + let s:cursor_stack[i].cursor = matchstr(s:cursor_stack[i].end, '^.') + let s:cursor_stack[i].end = substitute(s:cursor_stack[i].end, '^.', '', 'g') + endfor else - let s:symbol_begin .= nr2char(a:char) + for i in range(len(s:cursor_stack)) + let s:cursor_stack[i].begin .= nr2char(a:char) + endfor endif - call s:replace_symbol(s:symbol_begin . s:symbol_cursor . s:symbol_end) + call s:replace_symbol() silent! call s:highlight_cursor() endfunction - -function! s:parse_symbol(begin, end, symbol) abort +function! s:parse_symbol(begin, end, symbol, ...) abort + let use_expr = get(a:000, 0, 0) let len = len(a:symbol) let cursor = [line('.'), col('.')] for l in range(a:begin, a:end) let line = getline(l) - let idx = s:STRING.strAllIndex(line, a:symbol) - for pos_c in idx - call add(s:stack, [l, pos_c + 1, len]) - if l == cursor[0] && pos_c + 1 <= cursor[1] && pos_c + 1 + len >= cursor[1] + let idx = s:STRING.strAllIndex(line, a:symbol, use_expr) + for [pos_a, pos_b] in idx + call add(s:stack, [l, pos_a + 1, pos_b - pos_a]) + if len(idx) > 1 && l == cursor[0] && pos_a + 1 <= cursor[1] && pos_a + 1 + len >= cursor[1] let s:index = len(s:stack) - 1 - if pos_c + 1 < cursor[1] - let s:symbol_begin = line[pos_c : cursor[1] - 2] - else - let s:symbol_begin = '' - endif - let s:symbol_cursor = line[ cursor[1] - 1 : cursor[1] - 1] - if pos_c + 1 + len > cursor[1] - let s:symbol_end = line[ cursor[1] : pos_c + len - 1] - else - let s:symbol_end = '' - endif endif + call add(s:cursor_stack, + \ { + \ 'begin' : line[pos_a : pos_b - 2], + \ 'cursor' : line[pos_b - 1 : pos_b - 1], + \ 'end' : '', + \ } + \ ) endfor endfor + if s:index == -1 && !empty(s:stack) + let s:index = 0 + call cursor(s:stack[0][0], s:stack[0][1]) + endif + let g:wsd = [s:stack, s:cursor_stack] endfunction " TODO current only support one line symbol -function! s:replace_symbol(symbol) abort - let lines = split(a:symbol, "\n") - if len(lines) > 1 - let len = len(s:stack) - for idx in range(len) - let pos = s:stack[len-1-idx] - let line = getline(pos[0]) - if pos[1] == 1 - let begin = '' - else - let begin = line[:pos[1] - 2] +function! s:replace_symbol() abort + let line = 0 + let pre = '' + let idxs = [] + for i in range(len(s:stack)) + if s:stack[i][0] != line + if !empty(idxs) + let end = getline(line)[s:stack[i-1][1] + s:stack[i-1][2] - 1: ] + let pre .= end endif - let end = line[pos[1] + pos[2]:] - let line = begin . lines[0] . end - call setline(pos[0], line) - let s:stack[len-1-idx][2] = len(lines[0]) - endfor - else - let len = len(s:stack) - for idx in range(len) - let pos = s:stack[len-1-idx] - let line = getline(pos[0]) - if pos[1] == 1 - let begin = '' + call s:fixstack(idxs) + call setline(line, pre) + let idxs = [] + let line = s:stack[i][0] + let begin = s:stack[i][1] == 1 ? '' : getline(line)[:s:stack[i][1] - 2] + let pre = begin . s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end + else + let line = s:stack[i][0] + if i == 0 + let pre = (s:stack[i][1] == 1 ? '' : getline(line)[:s:stack[i][1] - 2]) . s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end else - let begin = line[:pos[1] - 2] + let a = s:stack[i-1][1] + s:stack[i-1][2] - 1 + let b = s:stack[i][1] - 2 + if a > b + let next = '' + else + let next = getline(line)[ a : b ] + endif + let pre .= next . s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end endif - let end = line[pos[1] + pos[2] - 1:] - let line = begin . a:symbol . end - call setline(pos[0], line) - let s:stack[len-1-idx][2] = len(a:symbol) - endfor + endif + call add(idxs, [i, len(s:cursor_stack[i].begin . s:cursor_stack[i].cursor . s:cursor_stack[i].end)]) + endfor + if !empty(idxs) + let end = getline(line)[s:stack[i][1] + s:stack[i][2] - 1: ] + let pre .= end endif + call s:fixstack(idxs) + call setline(line, pre) endfunction + +" [idx, newlen] +" same line +" [[1,6], [2,6], [3,6]] +function! s:fixstack(idxs) abort + " for [idx, len] in idxs + " let s:stack[idx] + " let s:stack[idx][2] = len + " endfor + let change = 0 + for i in range(len(a:idxs)) + let s:stack[a:idxs[i][0]][1] += change + let change += a:idxs[i][1] - s:stack[a:idxs[i][0]][2] + let s:stack[a:idxs[i][0]][2] = a:idxs[i][1] + endfor +endfunction + +" vim:set et sw=2 cc=80 nowrap: diff --git a/test/api/data/string.vader b/test/api/data/string.vader new file mode 100644 index 000000000..dfe11bbb0 --- /dev/null +++ b/test/api/data/string.vader @@ -0,0 +1,12 @@ +Execute ( SpaceVim api: data#string ): + let str = SpaceVim#api#import('data#string') + AssertEqual str.trim(' s b '), 's b' + AssertEqual str.trim_start(' s b '), 's b ' + AssertEqual str.trim_end(' s b '), ' s b' + AssertEqual str.fill('s b', 10), 's b ' + AssertEqual str.fill_middle('s b', 10), ' s b ' + AssertEqual str.string2chars(' a b '), [' ', 'a', ' ', 'b', ' '] + AssertEqual str.strAllIndex('hello spacevim hello', 'hello', 0), [[0, 5], [15, 20]] + AssertEqual str.strAllIndex('hello spacevim hello', 'he.*', 1), [[0, 20]] + AssertEqual str.strAllIndex('hello spacevim hello', 'he[^ ]*', 1), [[0, 5], [15, 20]] + AssertEqual str.strAllIndex('let s:cursor_stack[i].end = s:cursor_stack[i].cursor . s:cursor_stack[i].end', 's.cursor[^_]*', 1), [[0, 5], [15, 20]]