使用参数定义新的Vim运算符

时间:2012-01-24 21:16:04

标签: vim

我一直在寻找在Vim中映射一个带有额外参数的新运算符。

例如,我们知道ciw将“切入内部单词”并将您置于插入模式,我正在寻找的是自定义操作来替换c(例如{{} 1}})采取s之类的动作,但需要额外的参数。

一个简单的例子是:

iw

以正常模式执行(给定第一列上的光标)Given a line in a text file siw*围绕第一个单词,如下所示:

*

我知道,这是最优秀的surround.vim插件。但我只是在这里给出一个例子,并寻找一个关于如何获得映射以便上述工作的答案。

我尝试使用*Given* a line in a text file onoremap进行游戏,但似乎无法按照我想要的方式进行游戏。

所以这是运动和运算符挂起映射的组合。

3 个答案:

答案 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)

问题的标题可能会引起误解。你想要做的是定义一个新的运算符,如ydc,既不是动作也不是文本对象,不是吗? :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