vim从vmap内部调用一个函数

时间:2011-12-02 12:49:07

标签: vim

我创建了一个vmap文本对象,用于选择单个LaTeX \ item的文本:

vmap im ?\\item<CR>o/\\item\\|\\end{itemize}<CR>b$

但这有一个恼人的功能,我失去了我目前的搜索词。我已经读过,当在函数调用中发生搜索时会恢复搜索项,所以我想将地图转换为只调用一个可以进行搜索的函数:

function! ItemizeTextObject()
  ?\\item
  normal o
  /\\item|\\end{itemize}
  normal b$
endfunction

vmap in :call ItemizeTextObject()<CR>

不幸的是,这不起作用:我收到错误(“找不到模式:\ item | \ end {itemize}”),根本没有选择任何文本,并且在我的光标所在的行下方插入了一个新行上。我尝试了几种变体,并没有成功。

我认为基本问题是我必须在调用函数时保留可视模式(我的命令中的o应切换到选择的另一端,但是它会插入一个新行,)但我不知道怎么做。

更新

我尝试获得以下行为:在这样的文本中:

\begin{itemize}
  \item lorem ipsum...
  \item piece of text I want to select,
   the *CURSOR* is here, and there is more text
   that follows
  \item lorem ipsum...
\end{itemize}

我想点击vin,然后选择中间的文本块:

  \item piece of text I want to select,
   the *CURSOR* is here, and there is more text
   that follows

表示上一个\item开头的文字,直到但不包括下一个\item\end{itemize}

1 个答案:

答案 0 :(得分:2)

我已经使用operatorfunc上的文档来提出以下内容,它应该(接近)你想要的内容 1

function! ItemizeTextObject(type, ...)
    let sel_save = &selection
    let &selection = "inclusive"
    let reg_save = @@

    if a:0  " Invoked from Visual mode, use '< and '> marks.
        silent! 1,+1?\\item
        norm v | " use V for linewise visual mode
        "" use V for linewise visual mode:
        "norm V
        silent! /\\item\|\\end{itemize}
    "elseif a:type == 'line'
    "elseif a:type == 'block'
    else
       silent! 1,+1?\\item
       norm v
       silent! /\\item
    endif

    norm b$

    let &selection = sel_save
    let @@ = reg_save
endfunction

silent! unmap in

xnoremap <silent> in :<C-U>call ItemizeTextObject(visualmode(), 1)<CR>

如果您希望 visual 选择模式中的映射,则应使用vnoremap

需要解决的事项的说明:

  • 您现在可以从其他模式实现动作(填写函数中的分支)
  • 如果启用wrapscan,则不应搜索任何搜索(可能暂时设置nowrapscan?)
  • 你可能希望让操作符重复,这样你就可以通过说vininin扩展选择(参见https://stackoverflow.com/a/7292271/85371的例子)
  • 看起来你想要'linewise'行为(由于b$?)
    • 考虑使用norm V(请参阅评论)

编辑我将此行为与此简单映射进行了比较:

xnoremap <silent>in ?\\item<CR>o/\\item\\|\\end{itemize}<CR>b$

<子> 1 免责声明:我不知道LateX