2

我正在尝试在 VIM 中映射 Ctrl-y 以删除它在从光标下开始匹配的括号之间找到的任何内容。它有效,但它也删除了括号。这是我目前正在使用的:

imap <c-y> <Esc><Right>d%<Insert>

这很好用,除了我说它也删除了光标下的内容(即匹配的括号)。我确实找到了这个:

diX

X成为您正在寻找的支架;[, (,'

i命令的问题是我不想为我定期执行此操作的每个括号映射一个新键,我喜欢%它匹配光标下的任何内容,s甚至是一个字母。

有什么办法可以保留括号吗?

编辑:对不起,一个例子。我有以下文本示例,(* 代表光标):

(*text to be erased between brackets)
"*text to be erased between brackets"
'*text to be erased between brackets'
[*text to be erased between brackets]
{*text to be erased between brackets}

基本上在每个示例中,我希望我的光标位于相关括号的顶部,然后当我点击Ctrl-y它时,它会从插入模式移动到普通模式,删除所有文本或光标下括号之间的任何内容(在那个点下因为我移动到正常模式然后<Right>)到同一个括号的下一个。

所以上面所有的都会变成:

()
""
''
[]
{}

无需卸下周围的支架。随着d%括号被删除。

4

3 回答 3

5

不,%仅匹配一对的另一半,并且字母字符(例如s不要成对出现):您只能使用(){}[]''""<>.

此外,编辑是在正常模式下完成的,而不是插入模式。

在正常模式下,一种可能的顺序是v%holc

" []: normal mode cursor, |: insert mode cursor

[(]foo bar baz)
[(foo bar baz)]
[(foo bar baz])
([foo bar baz])
(|)

因此,以下映射应满足您的需求:

nnoremap <C-y> v%holc

扩展此映射以使其适用于任何字符将不那么简单。

我应该补充一点ci(,朋友并不像你想象的那样繁重。

编辑

以下功能(以及相关的正常模式映射)不是很聪明,但完全符合您的要求;随意修改它。它是这样工作的:

  • 如果您点击<C-y>a ({[<,当前字符与其兄弟 ( >]})) 之间的文本将被删除,您将进入插入模式。

  • 如果您点击<C-y>任何其他字符,则当前字符与其在该行中的下一个出现之间的文本将被删除,您将进入插入模式。

功能:

function! InPair()

  let l:this_char = getline('.')[col('.')-1]

  if this_char == '{' || this_char == '(' || this_char == '[' || this_char == '<'
    execute "normal! di" . this_char
  else
    execute "normal! ldt" . this_char
  endif

  startinsert

endfunction

映射:

nnoremap <C-y> :call InPair()<CR>

它绝不是完美的,但它应该提供一个很好的起点。

于 2013-03-29T06:48:34.987 回答
1

请参阅:help visual-operators。即,v_iB选择括号 {} 之间的所有文本。所以viBd会删除 2 {} 之间的所有文本。

于 2017-06-11T19:23:08.093 回答
0

让我们举个例子,我没有很清楚地告诉你...... :(

你有这个(* 是光标),你当前的映射将改变:

(foo*bar)

into         

*ar)

但你希望它是:

(*ar) (back to INSERT mode)

那么你可以这样做:

imap <c-y> <Esc>lv%ls

它将首先视觉选择到左括号,然后向右移动,这样括号以后不会被删除,然后s将删除视觉选择并返回插入模式。

,我又看了你的问题,看来你想要:

*bar) ( INSERT mode)

那么就更容易了:(仍然基于您当前的映射)

 imap <c-y> <Esc>c%

顺便说一句,如果你想拥有(*bar) (INSERT mode):(你真的应该在你的问题中举一个例子...... ^_^)

imap <c-y> <Esc>v%lc
于 2013-03-28T22:42:30.030 回答