是否有可能取消所述行为?
额外加分任务: 找到一种方法,使Vim在退出插入模式后立即刷新光标位置。
是否有可能取消所述行为?
额外加分任务: 找到一种方法,使Vim在退出插入模式后立即刷新光标位置。
虽然我不建议更改默认的光标机制,但实现所需行为的一种方式是使用以下插入模式映射。
:inoremap <silent> <Esc> <Esc>`^
在插入模式中,Esc键的功能被改写为执行`^
命令,将光标移动到上次离开插入模式时的位置。由于在这种映射中,它会在使用Esc键离开插入模式后立即执行,因此与默认行为相比,光标会向右移动一个字符的位置。
与其他一些解决方法不同,这种方法不需要Vim编译时启用+ex_extra
功能。
a
在当前位置插入,而 i
则将光标移回并插入。无论哪种方式都是合乎逻辑的,这取决于您认为光标在哪里。我想编写vi的人认为光标位于高亮字符之后。 - DrAlautocmd InsertLeave * :normal \
^`。 - Nathan NeffabcDefg
,光标位于 D
上:
如果按下 i,插入模式位置将在c
和D
之间。正常的ESC 将把光标放在c
上;<C-O>:stopinsert<CR>
(或反引号方法)将把光标放在D
上。
如果按下 a,插入模式位置将在 D
和 e
之间。正常的 ESC 将把光标放在D
上;<C-O>:stopinsert<CR>
将把光标放在e
上。
如果你真的想做到这一点,你可以使用以下代码:
let insert_command = "inoremap <ESC> <C-O>:stopinsert<CR>"
let append_command = "iunmap <ESC>"
nnoremap i :exe insert_command<CR>i
nnoremap a :exe append_command<CR>a
但是请记住,这只处理以i
和a
作为输入方法的情况:如果您使用可视块模式、I
或A
等其他方法,则需要想出新的命令来匹配它们(而且这些命令非常多)。因此,我强烈建议您不要这样做。
个人建议您习惯默认行为。您可以轻松地将其逻辑应用于i
或 逻辑应用于a
。如果您将默认设置为适用于i
的逻辑而损失了适用于a
的逻辑,那么当您使用标准的vi/vim安装时,您会感到困惑。
根据Nathan Neff的评论,我发现最好的方法是:
autocmd InsertLeave * :normal! `^
set virtualedit=onemore
autocmd
命令会将光标移回到插入模式结束时的位置(即比默认位置向前一个字符)。
virtualedit
使其在行末表现得更加一致(因此可以在行末最后一个字符的后面向前移动一个字符)。
(编辑:normal!
以避免递归映射)
inoremap <silent> <Esc> <C-O>:stopinsert<CR>
.vimrc
文件中。i
进入插入模式时逻辑上正确,但如果你使用 a
进入插入模式则不合逻辑。 - DrAli
重新映射为设置标志,然后将插入模式下的 <Esc>
重新映射为检查该标志,如果已设置,则使用 <C-O>:stopinsert<CR>
,然后无论如何都清除该标志。 - rampiona
来说完全是不合逻辑的。通常,在每次更改后,当我离开该更改时,我就完成了该更改,并且我想做的下一件事可能涉及进行其他更改。因此,对我来说,在离开插入模式时(无论我如何进入它),我通常希望光标位于下一个字符上,以便我准备进行下一次更改,而不是准备更改我刚刚插入的内容。(大部分内容摘自我的评论:http://unix.stackexchange.com/a/11403/38050) - Kyle Strandau InsertLeave * call cursor([getpos('.')[1], getpos('.')[2]+1])
call
之前插入if (getpos('。')[2]> 1) |
来修复它。(此外,它应该是augroup
的一部分,以防止重新加载包含此autocommand的.vimrc
时产生累积跳转向前。) - Kyle Strandaugroup
吗?谢谢。 - Steven Luttimeoutlen
吗?我个人将 ttimeoutlen
设置为 10
毫秒:ttimeoutlen
是给终端仿真器客户端发出终端转义序列(例如右箭头键的 4 字节序列 \033[[C
)的超时宽限。插入模式实际上直到此超时之后才会真正退出,这个原因应该很明显——Vim 不知道你的终端是否要跟随一个转义序列或者将 Esc 作为退出插入模式命令。请注意并认识到你的 Vim 设置已经在做这件事情了,延迟退出插入模式。 - Steven Luautocmd!InsertLeave * if(getpos('。')[2]> 1)| call cursor([getpos('。')[1],getpos('。')[2] + 1])| endif
因此,自动命令不会在第一列中断。此外,请参见类似的解决方案:https://vim.fandom.com/wiki/Prevent_escape_from_moving_the_cursor_one_character_to_the_left - john c. j.有一种方法来自Vim技巧维基对我很有效,已经使用了好多年:
" Leave insert mode to the *right* of the final location of the insertion
" pointer
" From http://vim.wikia.com/wiki/Prevent_escape_from_moving_the_cursor_one_character_to_the_left
let CursorColumnI = 0 "the cursor column position in INSERT
autocmd InsertEnter * let CursorColumnI = col('.')
autocmd CursorMovedI * let CursorColumnI = col('.')
autocmd InsertLeave * if col('.') != CursorColumnI | call cursor(0, col('.')+1) | endif
这个怎么样:
:imap <Esc> <Esc><Right>
i
进入插入模式,这将是合乎逻辑的,但如果您使用 a
进入插入模式,则不合逻辑。 - DrAl
a
进入还是使用i
进入,因此它假设您是使用a
进入的。实际上,当您重复使用a
和 <kbd>Esc</kbd> 时,光标并不会“滑动”。 - Alois Mahdal<esc>D
删除光标后的内容时会让我感到困扰。我认为基于:autocmd InsertLeave
的一些东西可能会有效吗? - Steven Lu