我一直在寻找在Vim中映射一个带有额外参数的新运算符.
例如,我们知道ciw将"切入内部单词"并将使您进入插入模式,我正在寻找的是一个自定义动作来替换c(例如s)iw需要额外参数的动作.
一个简单的例子是:
Given a line in a text file
Run Code Online (Sandbox Code Playgroud)
并执行正常模式(给定光标在第一列)siw*,这将围绕第一个单词,*如下所示:
*Given* a line in a text file
Run Code Online (Sandbox Code Playgroud)
我知道,这是最优秀的surround.vim插件.但我只是在这里给出一个例子,并寻找一个关于如何获得映射以便上述工作的答案.
我试着用打onoremap和opfunc,但似乎无法让他们打我想要的方式.
所以这是运动和运算符挂起映射的组合.
ib.*_*ib. 13
这里是用于说明目的的问题中描述的命令的示例实现.
nnoremap <silent> s :set opfunc=Surround<cr>g@
vnoremap <silent> s :<c-u>call Surround(visualmode(), 1)<cr>
function! Surround(vt, ...)
let s = InputChar()
if s =~ "\<esc>" || s =~ "\<c-c>"
return
endif
let [sl, sc] = getpos(a:0 ? "'<" : "'[")[1:2]
let [el, ec] = getpos(a:0 ? "'>" : "']")[1:2]
if a:vt == 'line' || a:vt == 'V'
call append(el, s)
call append(sl-1, s)
elseif a:vt == 'block' || a:vt == "\<c-v>"
exe sl.','.el 's/\%'.sc.'c\|\%'.ec.'c.\zs/\=s/g|norm!``'
else
exe el 's/\%'.ec.'c.\zs/\=s/|norm!``'
exe sl 's/\%'.sc.'c/\=s/|norm!``'
endif
endfunction
Run Code Online (Sandbox Code Playgroud)
为了获得用户输入,使用该函数InputChar(),假设所需参数是单个字符.
function! InputChar()
let c = getchar()
return type(c) == type(0) ? nr2char(c) : c
endfunction
Run Code Online (Sandbox Code Playgroud)
如果有必要接受字符串参数,请调用input()而不是
InputChar().
问题的标题可能会引起误解.你想要做的是定义一个新的运营商一样y,d和c,既不运动也不文本对象,不是吗?
:help :map-operator描述了如何定义新的运算符.要获取类似环绕声插件的参数,请使用getchar()您的'operatorfunc'.
虽然:help :map-operator描述了基础知识,但处理传递给它的参数有点麻烦'operatorfunc'.您可以使用vim-operator-user来简化参数的处理.使用此插件,类似环绕声的运算符可以编写如下:
function! OperatorSurround(motion_wise)
let _c = getchar()
let c = type(_c) == type(0) ? nr2char(_c) : _c
if c ==# "\<Esc>" || c == "\<C-c>"
return
endif
let bp = getpos("'[")
let ep = getpos("']")
if a:motion_wise ==# 'char'
call setpos('.', ep)
execute "normal! \"=c\<Return>p"
call setpos('.', bp)
execute "normal! \"=c\<Return>P"
elseif a:motion_wise ==# 'line'
let indent = matchstr(getline('.'), '^\s*')
call append(ep[1], indent . c)
call append(bp[1] - 1, indent . c)
elseif a:motion_wise ==# 'block'
execute bp[1].','.ep[1].'substitute/\%'.ep[2].'c.\zs/\=c/'
execute bp[1].','.ep[1].'substitute/\%'.bp[2].'c\zs/\=c/'
call setpos('.', bp)
else
endif
endfunction
call operator#user#define('surround', 'OperatorSurround')
map s <Plug>(operator-surround)
Run Code Online (Sandbox Code Playgroud)
如果您确实想要定义自己的文本对象,请考虑使用vim-textobj-user.