我一直在寻找在Vim中映射一个带有额外参数的新运算符。
例如,我们知道ciw
将“切入内部单词”并将您置于插入模式,我正在寻找的是自定义操作来替换c
(例如{{} 1}})采取s
之类的动作,但需要额外的参数。
一个简单的例子是:
iw
以正常模式执行(给定第一列上的光标)Given a line in a text file
将siw*
围绕第一个单词,如下所示:
*
我知道,这是最优秀的surround.vim插件。但我只是在这里给出一个例子,并寻找一个关于如何获得映射以便上述工作的答案。
我尝试使用*Given* a line in a text file
和onoremap
进行游戏,但似乎无法按照我想要的方式进行游戏。
所以这是运动和运算符挂起映射的组合。
答案 0 :(得分:12)
这是问题中描述的命令的示例实现, 用于说明目的。
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
为了获得用户输入,使用函数InputChar()
,假设是
必需参数是单个字符。
function! InputChar()
let c = getchar()
return type(c) == type(0) ? nr2char(c) : c
endfunction
如果需要接受字符串参数,请调用input()
而不是
InputChar()
。
答案 1 :(得分:7)
问题的标题可能会引起误解。你想要做的是定义一个新的运算符,如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)
如果您确实要定义自己的文字对象,请考虑vim-textobj-user。
答案 2 :(得分:1)
考虑一个用于编写自定义文本对象的插件。例如: https://github.com/kana/vim-textobj-user