From 2e49f022449be3cbd397dad3f2c5533eb8b09093 Mon Sep 17 00:00:00 2001 From: Wang Shidong Date: Sun, 16 Oct 2022 13:45:34 +0800 Subject: [PATCH] feat(iedit): rewrite iedit in lua (#4724) --- .stylua.toml | 6 + .../neosnippet-snippets/neosnippets/lua.snip | 3 +- .../_posts/2019-01-19-use-vim-as-a-lua-ide.md | 8 +- lua/spacevim/api/data/string.lua | 23 +- lua/spacevim/api/vim/highlight.lua | 13 +- lua/spacevim/plugin/iedit.lua | 685 ++++++++++++++++++ test/lua/data/string.vader | 3 +- 7 files changed, 735 insertions(+), 6 deletions(-) create mode 100644 .stylua.toml create mode 100644 lua/spacevim/plugin/iedit.lua diff --git a/.stylua.toml b/.stylua.toml new file mode 100644 index 000000000..a79b15d9b --- /dev/null +++ b/.stylua.toml @@ -0,0 +1,6 @@ +column_width = 80 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferSingle" +call_parentheses = "Always" diff --git a/bundle/neosnippet-snippets/neosnippets/lua.snip b/bundle/neosnippet-snippets/neosnippets/lua.snip index e8fc02b3e..31d500235 100644 --- a/bundle/neosnippet-snippets/neosnippets/lua.snip +++ b/bundle/neosnippet-snippets/neosnippets/lua.snip @@ -2,9 +2,10 @@ snippet func abbr function name(args)...end options word - function ${1:#:function_name}(${2:#:argument}) + function ${1:#:function_name}(${2:#:argument}) -- {{{ ${0:TARGET} end + -- }}} snippet if options head diff --git a/docs/_posts/2019-01-19-use-vim-as-a-lua-ide.md b/docs/_posts/2019-01-19-use-vim-as-a-lua-ide.md index aead06399..61efac8a1 100644 --- a/docs/_posts/2019-01-19-use-vim-as-a-lua-ide.md +++ b/docs/_posts/2019-01-19-use-vim-as-a-lua-ide.md @@ -76,12 +76,18 @@ It is running asynchronously, and will not block your vim. ### Code formatting The format layer is also enabled by default, with this layer you can use key binding `SPC b f` to format current buffer. -Before using this feature, please install luaformatter. +Before using this feature, please install [luaformatter](https://github.com/Koihik/LuaFormatter) or [stylua](https://github.com/JohnnyMorganz/StyLua). ```sh luarocks install formatter ``` +Install stylua in windows: + +``` +scoop install stylua +``` + ### REPL support Start a `lua -i` inferior REPL process with `SPC l s i`. After the REPL process being started, you can diff --git a/lua/spacevim/api/data/string.lua b/lua/spacevim/api/data/string.lua index 244e2c226..8b3c4e313 100644 --- a/lua/spacevim/api/data/string.lua +++ b/lua/spacevim/api/data/string.lua @@ -78,11 +78,30 @@ function M.string2chars(str) end function M.matchstrpos(str, need, ...) - + local matchedstr = vim.fn.matchstr(str, need, ...) + local matchbegin = vim.fn.match(str, need, ...) + local matchend = vim.fn.matchend(str, need, ...) + return {matchedstr, matchbegin, matchend} + -- return vim.fn.matchstrpos(str, need, ...) end function M.strAllIndex(str, need, use_expr) - + local rst = {} + if use_expr then + local idx = M.matchstrpos(str, need) + while idx[2] ~= -1 do + table.insert(rst, {idx[2], idx[3]}) + idx = M.matchstrpos(str, need, idx[3]) + end + else + local pattern = [[\<\V]] .. need .. [[\ze\W\|\<\V]] .. need .. [[\ze\$]] + local idx = vim.fn.match(str, pattern) + while idx ~= -1 do + table.insert(rst, {idx, idx + vim.fn.len(need)}) + idx = vim.fn.match(str, pattern, idx + 1 + vim.fn.len(need)) + end + end + return rst end function M.strQ2B(str) diff --git a/lua/spacevim/api/vim/highlight.lua b/lua/spacevim/api/vim/highlight.lua index b4816d199..88d2457ab 100644 --- a/lua/spacevim/api/vim/highlight.lua +++ b/lua/spacevim/api/vim/highlight.lua @@ -30,7 +30,18 @@ M.group2dict = function (name) end M.hide_in_normal = function (name) - + local group = M.group2dict(name) + if vim.fn.empty(group) == 1 then + return + end + local normal = M.group2dict('Normal') + local guibg = normal.guibg or '' + local ctermbg = normal.ctermbg or '' + group.guifg = guibg + group.guibg = guibg + group.ctermfg = ctermbg + group.ctermbg = ctermbg + M.hi(group) end diff --git a/lua/spacevim/plugin/iedit.lua b/lua/spacevim/plugin/iedit.lua new file mode 100644 index 000000000..34c6bfe82 --- /dev/null +++ b/lua/spacevim/plugin/iedit.lua @@ -0,0 +1,685 @@ +--============================================================================= +-- iedit.lua --- multiple cursor for spacevim in lua +-- Copyright (c) 2016-2022 Wang Shidong & Contributors +-- Author: Wang Shidong < wsdjeg@outlook.com > +-- URL: https://spacevim.org +-- License: GPLv3 +--============================================================================= + +local M = {} +local modname = 'spacevim.plugin.iedit' +_G[modname] = M +package.loaded[modname] = M --return modname +setmetatable(M, { __index = _G }) + +-- Local spacevim APIs {{{ +local hi = require('spacevim.api').import('vim.highlight') +local str = require('spacevim.api').import('data.string') +local cmp = require('spacevim.api').import('vim.compatible') +local v = require('spacevim.api').import('vim') +local k = require('spacevim.api').import('vim.keys') +-- }}} + +-- Local Variable {{{ + +local logger = require('spacevim.logger').derive('iedit') + +local index = -1 +local cursor_col = -1 +local mode = '' +local hi_id = '' +local Operator = '' +local iedit_cursor_hi_info = {} +local cursor_stack = {} + +local iedit_hi_info = { + { + name = 'IeditPurpleBold', + guibg = '#3c3836', + guifg = '#d3869b', + ctermbg = '', + ctermfg = 175, + bold = 1, + }, + { + name = 'IeditBlueBold', + guibg = '#3c3836', + guifg = '#83a598', + ctermbg = '', + ctermfg = 109, + bold = 1, + }, + { + name = 'IeditInactive', + guibg = '#3c3836', + guifg = '#abb2bf', + ctermbg = '', + ctermfg = 145, + bold = 1, + }, +} + +-- }}} + +--- basic functions{{{ +local function empty(expr) -- {{{ + return vim.fn.empty(expr) == 1 +end +-- }}} + +local matchstr = vim.fn.matchstr +local substitute = vim.fn.substitute +local range = vim.fn.range +local getline = vim.fn.getline + +local function echo(msg) -- {{{ + vim.api.nvim_echo({ { msg } }, false, {}) +end +-- }}} + +---}}} + +local function fixstack(idxs) -- {{{ + local change = 0 + for i = 1, #idxs, 1 do + cursor_stack[idxs[i][1]].col = cursor_stack[idxs[i][1]].col + change + change = change + idxs[i][2] - cursor_stack[idxs[i][1]].len + cursor_stack[idxs[i][1]].len = idxs[i][2] + end +end +-- }}} + +local function replace_symbol() -- {{{ + local line = 0 + local begin = '' + local pre = '' + local _end = '' + local idxs = {} + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].lnum ~= line then + if not empty(idxs) then + logger.debug('i is:' .. i) + logger.debug( + 'cursor_stack[i -1] is' .. vim.inspect(cursor_stack[i - 1]) + ) + _end = string.sub( + vim.fn.getline(line), + cursor_stack[i - 1].col + cursor_stack[i - 1].len - 1, + -1 + ) + pre = pre .. _end + end + fixstack(idxs) + vim.fn.setline(line, pre) + idxs = {} + line = cursor_stack[i].lnum + if cursor_stack[i].col ~= 1 then + begin = string.sub(vim.fn.getline(line), 1, cursor_stack[i].col - 2) + else + begin = '' + end + pre = begin + .. cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + else + line = cursor_stack[i].lnum + if i == 1 then + if cursor_stack[i].col == 1 then + pre = '' + else + pre = string.sub(vim.fn.getline(line), 1, cursor_stack[i].col - 2) + .. cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + end + else + local a = cursor_stack[i - 1].col + cursor_stack[i - 1].len - 1 + local b = cursor_stack[i].col - 2 + local next = '' + if a > b then + next = '' + else + next = string.sub(vim.fn.getline(line), a, b) + end + pre = pre + .. next + .. cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + end + end + table.insert(idxs, { + i, + vim.fn.len( + cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + ), + }) + end + if not empty(idxs) then + end + fixstack(idxs) + vim.fn.setline(line, pre) +end +-- }}} + +local function reset_Operator(...) -- {{{ + Operator = '' +end +-- }}} + +local function timeout() -- {{{ + timer_start(1000, reset_Operator) +end +-- }}} + +local function highlight_cursor() -- {{{ + hi.hi(iedit_cursor_hi_info) + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + if i == index then + vim.fn.matchaddpos('IeditPurpleBold', { + { + cursor_stack[i].lnum, + cursor_stack[i].col, + cursor_stack[i].len, + }, + }) + else + vim.fn.matchaddpos('IeditBlueBold', { + { + cursor_stack[i].lnum, + cursor_stack[i].col, + cursor_stack[i].len, + }, + }) + end + vim.fn.matchadd( + 'SpaceVimGuideCursor', + [[\%]] + .. cursor_stack[i].lnum + .. [[l\%]] + .. (cursor_stack[i].col + vim.fn.len(cursor_stack[i].cursor_begin)) + .. 'c', + 99999 + ) + else + vim.fn.matchaddpos('IeditInactive', { + { + cursor_stack[i].lnum, + cursor_stack[i].col, + cursor_stack[i].len, + }, + }) + end + end +end +-- }}} + +local function remove_cursor_highlight() -- {{{ + vim.fn.clearmatches() +end +-- }}} + +local function handle_normal(char) -- handle normal key bindings {{{ + remove_cursor_highlight() + if char == 'i' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + vim.cmd('redrawstatus!') + -- }}} + elseif char == 'I' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + local old_cursor_char = cursor_stack[i].cursor_char + cursor_stack[i].cursor_char = vim.fn.matchstr( + cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end, + '^.' + ) + cursor_stack[i].cursor_end = vim.fn.substitute( + cursor_stack[i].cursor_begin + .. old_cursor_char + .. cursor_stack[i].cursor_end, + '^.', + '', + 'g' + ) + cursor_stack[i].cursor_begin = '' + end + end + vim.cmd('redrawstatus!') + -- }}} + elseif char == '' then -- {{{ + cursor_stack[index].active = not cursor_stack[index].active + --}}} + elseif char == 'a' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + vim.cmd('redrawstatus!') + -- }}} + elseif char == 'A' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + cursor_stack[i].cursor_char = '' + cursor_stack[i].cursor_end = '' + end + end + vim.cmd('redrawstatus!') + -- }}} + elseif char == 'C' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_char = '' + cursor_stack[i].cursor_end = '' + end + end + replace_symbol() + -- }}} + elseif char == '~' then -- toggle the case of cursor char {{{ + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_char = + str.toggle_case(cursor_stack[i].cursor_char) + end + end + replace_symbol() + --}}} + elseif char == 'f' then -- string find mode {{{ + Operator = 'f' + timeout() + -- }}} + elseif char == 's' then -- {{{ + mode = 'i' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'ii' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + replace_symbol() + -- }}} + elseif char == 'x' then -- {{{ + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + replace_symbol() + -- }}} + elseif char == 'X' then -- {{{ + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = + vim.fn.substitute(cursor_stack[i].cursor_begin, '.$', '', 'g') + end + end + replace_symbol() + -- }}} + elseif char == '' or char == 'h' then -- {{{ + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_end = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_end + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_begin, '.$') + cursor_stack[i].cursor_begin = + vim.fn.substitute(cursor_stack[i].cursor_begin, '.$', '', 'g') + end + end + -- }}} + elseif char == '' or char == 'l' then + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + elseif char == 'e' then + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + local word = vim.fn.matchstr(cursor_stack[i].cursor_end, [[^\s*\S*]]) + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. word + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_begin, '.$') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, [[^\s*\S*]], '', 'g') + end + end + elseif char == 'b' then + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + local word = vim.fn.matchstr(cursor_stack[i].cursor_begin, [[\S*\s*$]]) + cursor_stack[i].cursor_end = word + .. cursor_stack[i].cursor_char + .. cursor_stack[i].cursor_end + cursor_stack[i].cursor_begin = + vim.fn.substitute(cursor_stack[i].cursor_begin, [[\S*\s*$]], '', 'g') + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + elseif char == 'w' then + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + if cursor_stack[i].active then + local word = vim.fn.matchstr(cursor_stack[i].cursor_end, [[\S*\s*$]]) + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. word + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, [[^\S*\s*]], '', 'g') + cursor_stack[i].cursor_char = + vim.fn.matchstr(cursor_stack[i].cursor_end, '^.') + cursor_stack[i].cursor_end = + vim.fn.substitute(cursor_stack[i].cursor_end, '^.', '', 'g') + end + end + elseif char == '0' or char == '' then + elseif char == '$' or char == '' then + elseif char == 'D' then + elseif char == 'p' then + elseif char == 'S' then + elseif char == 'G' then + elseif char == 'g' then + elseif char == '' then + elseif char == '' then + elseif char == '' then + elseif char == 'n' then + elseif char == 'N' then + end + highlight_cursor() + return cursor_stack[1].cursor_begin + .. cursor_stack[1].cursor_char + .. cursor_stack[1].cursor_end +end +-- }}} + +local function handle_insert(char) -- {{{ + remove_cursor_highlight() + local is_movement = false + if char == k.t('') or char == k.t('') then + mode = 'n' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'in' + highlight_cursor() + vim.cmd('redraw!') + vim.cmd('redrawstatus!') + return cursor_stack[1].cursor_begin + .. cursor_stack[1].cursor_char + .. cursor_stack[1].cursor_end + elseif char == k.t('') then + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = + substitute(cursor_stack[i].cursor_begin, [[\S*\s*$]], '', 'g') + end + end + elseif char == k.t('') then + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = '' + end + end + elseif char == k.t('') then + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].active then + cursor_stack[i].cursor_char = '' + cursor_stack[i].cursor_end = '' + end + end + elseif char == k.t('') or char == k.t('') then + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = + substitute(cursor_stack[i].cursor_begin, '.$', '', 'g') + end + end + else + for i = 1, #cursor_stack, 1 do + if cursor_stack[i].active then + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin .. char + end + end + end + if not is_movement then + replace_symbol() + end + highlight_cursor() + return cursor_stack[1].cursor_begin + .. cursor_stack[1].cursor_char + .. cursor_stack[1].cursor_end +end +--- }}} + +local function parse_symbol(_begin, _end, symbol, use_expr, selectall) -- {{{ + local len = #symbol + local cursor = { vim.fn.line('.'), vim.fn.col('.') } + for _, l in ipairs(vim.fn.range(_begin, _end)) do + local line = vim.fn.getline(l) + local idx = str.strAllIndex(line, symbol, use_expr) + for _, v in ipairs(idx) do + local pos_a = v[1] + local pos_b = v[2] + table.insert(cursor_stack, { + cursor_begin = string.sub(line, pos_a, pos_b - 2), + cursor_char = string.sub(line, pos_b - 1, pos_b - 1), + cursor_end = '', + active = selectall, + lnum = l, + col = pos_a + 1, + len = pos_b - pos_a, + }) + if l == cursor[1] and pos_a + 1 <= cursor[2] and pos_b >= cursor[2] then + index = #cursor_stack + end + end + end + if index == -1 and vim.fn.empty(cursor_stack) == 0 then + index = 1 + vim.fn.cursor(cursor_stack[1].lnum, cursor_stack[1].col) + end + if vim.fn.empty(cursor_stack) == 0 then + cursor_stack[index].active = true + end +end +-- }}} + +local function handle_f_char(char) -- {{{ + remove_cursor_highlight() + if char >= 32 and char <= 126 then + Operator = '' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + local matchedstr = vim.fn.matchstr( + cursor_stack[i].cursor_end, + vim.fn.printf('[^%s]', vim.fn.nr2char(char)) + ) + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin + .. cursor_stack[i].cursor_char + .. matchedstr + cursor_stack[i].cursor_end = vim.fn.matchstr( + cursor_stack[i].cursor_end, + vim.fn.printf([[[%s]\zs.*]], vim.fn.nr2char(char)) + ) + cursor_stack[i].cursor_char = vim.fn.nr2char(char) + end + end + highlight_cursor() + return cursor_stack[1].cursor_begin + .. cursor_stack[1].cursor_char + .. cursor_stack[1].cursor_end +end +-- }}} + +local function handle_register(char) -- {{{ + local char = vim.fn.nr2char(char) + -- same as char =~# '[a-zA-Z0-9"+:/]' in vim script + if char:match('[a-zA-Z0-9"%+:/]') then + remove_cursor_highlight() + Operator = '' + local reg = '@' .. char + local paste = vim.fn.split(vim.fn.eval(reg), '\n')[1] or '' + for _, i in ipairs(vim.fn.range(1, #cursor_stack)) do + cursor_stack[i].cursor_begin = cursor_stack[i].cursor_begin .. paste + end + replace_symbol() + highlight_cursor() + end + return cursor_stack[1].cursor_begin + .. cursor_stack[1].cursor_char + .. cursor_stack[1].cursor_end +end +-- }}} + +local function handle(mode, char) -- {{{ + if mode == 'n' and Operator == 'f' then + handle_f_char(char) + elseif mode == 'n' then + handle_normal(char) + elseif mode == 'r' and Operator == 'r' then + handle_register(char) + elseif mode == 'i' then + handle_insert(char) + end +end +-- }}} + +function M.start(...) -- {{{ + local args = { ... } + argv = args[1] or '' + local selectall = true + local use_expr = false + if + empty(argv) + and ( + matchstr(getline('.'), '\\%' .. vim.fn.col('.') .. 'c.') == '' + or matchstr(getline('.'), '\\%' .. vim.fn.col('.') .. 'c.') == ' ' + ) + then + echo('no pattern found under cursor') + end + local save_tve = vim.o.t_ve + local save_cl = vim.wo.cursorline + vim.wo.cursorline = false + vim.o.t_ve = '' + hi.hi(iedit_hi_info[1]) + hi.hi(iedit_hi_info[2]) + hi.hi(iedit_hi_info[3]) + local cursor_hi = hi.group2dict('Cursor') + iedit_cursor_hi_info = vim.fn.deepcopy(cursor_hi) + iedit_cursor_hi_info.name = 'SpaceVimGuideCursor' + lcursor_hi = hi.group2dict('lCursor') + local guicursor = vim.o.guicursor + hi.hide_in_normal('Cursor') + hi.hide_in_normal('lCursor') + if vim.api ~= nil then + vim.cmd('set guicursor+=a:Cursor/lCursor') + end + mode = 'n' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'in' + if #cursor_stack == 0 then + local curpos = vim.fn.getpos('.') + local save_reg_k = vim.api.nvim_eval('@"') + if not empty(argv) and vim.fn.type(argv) == 4 then + selectall = argv.selectall or selectall + if argv.expr ~= nil then + use_expr = true + symbol = argv.expr + elseif argv.word then + symbol = argv.word + elseif argv.stack then + else + vim.cmd('normal! gv"ky') + symbol = vim.fn.split(vim.api.nvim_eval('@K'), '\n')[1] + end + else + vim.cmd('normal! viw"ky') + symbol = vim.fn.split(vim.api.nvim_eval('@K'), '\n')[1] + end + end + vim.fn.setpos('.', curpos) + local _begin = args[2] or 1 + local _end = args[3] or vim.fn.line('$') + logger.debug('iedit symbol:>' .. symbol .. '<') + logger.debug('iedit use_expr:' .. vim.fn.string(use_expr)) + logger.debug('iedit begin:' .. _begin) + logger.debug('iedit end:' .. _end) + parse_symbol(_begin, _end, symbol, 1, selectall) + highlight_cursor() + vim.cmd('redrawstatus!') + while mode ~= '' and #cursor_stack > 0 do + vim.cmd('redraw!') + local char = v.getchar() + if mode == 'n' and char == k.t('') then + mode = '' + else + local symbol = handle(mode, char) + end + end + if #cursor_stack == 0 then + vim.cmd('normal! :') + echo('Pattern not found:' .. symbol) + end + cursor_stack = {} + index = -1 + mode = '' + vim.w.spacevim_iedit_mode = mode + vim.w.spacevim_statusline_mode = 'in' + vim.o.t_ve = save_tve + hi.hi(cursor_hi) + hi.hi(lcursor_hi) + vim.o.guicursor = guicursor + vim.cmd('normal! :') + remove_cursor_highlight() + pcall(vim.fn.matchdelete, hi_id) + hi_id = '' + vim.wo.cursorline = save_cl + return symbol +end +-- }}} + +return M + +-- vim:set et sw=2 cc=80 foldmethod=marker foldmarker={{{,}}}: diff --git a/test/lua/data/string.vader b/test/lua/data/string.vader index 33f64c21e..1ba43f202 100644 --- a/test/lua/data/string.vader +++ b/test/lua/data/string.vader @@ -1,9 +1,10 @@ Execute ( SpaceVim lua api: data#string ): - if !has('lua') && !has('nvim-0.5.0') + if !has('nvim-0.5.0') finish endif let cmp = SpaceVim#api#import('vim#compatible') Log 'test trim()' lua sp_str = require('spacevim.api').import('data.string') AssertEqual cmp.luaeval("sp_str.trim(' s b ')"), 's b' + AssertEqual cmp.luaeval("sp_str.strAllIndex('hello spacevim hello', 'hello', 0)"), [[0, 5], [15, 20]]