mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 12:50:04 +08:00
feat(iedit): rewrite iedit in lua (#4724)
This commit is contained in:
parent
0b91495ff2
commit
2e49f02244
6
.stylua.toml
Normal file
6
.stylua.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
column_width = 80
|
||||||
|
line_endings = "Unix"
|
||||||
|
indent_type = "Spaces"
|
||||||
|
indent_width = 2
|
||||||
|
quote_style = "AutoPreferSingle"
|
||||||
|
call_parentheses = "Always"
|
@ -2,9 +2,10 @@
|
|||||||
snippet func
|
snippet func
|
||||||
abbr function name(args)...end
|
abbr function name(args)...end
|
||||||
options word
|
options word
|
||||||
function ${1:#:function_name}(${2:#:argument})
|
function ${1:#:function_name}(${2:#:argument}) -- {{{
|
||||||
${0:TARGET}
|
${0:TARGET}
|
||||||
end
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
snippet if
|
snippet if
|
||||||
options head
|
options head
|
||||||
|
@ -76,12 +76,18 @@ It is running asynchronously, and will not block your vim.
|
|||||||
### Code formatting
|
### 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.
|
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
|
```sh
|
||||||
luarocks install formatter
|
luarocks install formatter
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install stylua in windows:
|
||||||
|
|
||||||
|
```
|
||||||
|
scoop install stylua
|
||||||
|
```
|
||||||
|
|
||||||
### REPL support
|
### REPL support
|
||||||
|
|
||||||
Start a `lua -i` inferior REPL process with `SPC l s i`. After the REPL process being started, you can
|
Start a `lua -i` inferior REPL process with `SPC l s i`. After the REPL process being started, you can
|
||||||
|
@ -78,11 +78,30 @@ function M.string2chars(str)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function M.matchstrpos(str, need, ...)
|
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
|
end
|
||||||
|
|
||||||
function M.strAllIndex(str, need, use_expr)
|
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
|
end
|
||||||
|
|
||||||
function M.strQ2B(str)
|
function M.strQ2B(str)
|
||||||
|
@ -30,7 +30,18 @@ M.group2dict = function (name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
M.hide_in_normal = function (name)
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
685
lua/spacevim/plugin/iedit.lua
Normal file
685
lua/spacevim/plugin/iedit.lua
Normal file
@ -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 == '<tab>' 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 == '<left>' 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 == '<right>' 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 == '<home>' then
|
||||||
|
elseif char == '$' or char == '<end>' then
|
||||||
|
elseif char == 'D' then
|
||||||
|
elseif char == 'p' then
|
||||||
|
elseif char == 'S' then
|
||||||
|
elseif char == 'G' then
|
||||||
|
elseif char == 'g' then
|
||||||
|
elseif char == '<c-n>' then
|
||||||
|
elseif char == '<C-x>' then
|
||||||
|
elseif char == '<C-p>' 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('<Esc>') or char == k.t('<C-g>') 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('<C-w>') 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('<C-u>') 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('<C-k>') 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('<bs>') or char == k.t('<C-h>') 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('<Esc>') 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={{{,}}}:
|
@ -1,9 +1,10 @@
|
|||||||
Execute ( SpaceVim lua api: data#string ):
|
Execute ( SpaceVim lua api: data#string ):
|
||||||
if !has('lua') && !has('nvim-0.5.0')
|
if !has('nvim-0.5.0')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let cmp = SpaceVim#api#import('vim#compatible')
|
let cmp = SpaceVim#api#import('vim#compatible')
|
||||||
Log 'test trim()'
|
Log 'test trim()'
|
||||||
lua sp_str = require('spacevim.api').import('data.string')
|
lua sp_str = require('spacevim.api').import('data.string')
|
||||||
AssertEqual cmp.luaeval("sp_str.trim(' s b ')"), 's b'
|
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]]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user