Vim,在不编辑的情况下退出时,创建未保存的缓冲区
Vim, when exiting without editing, creates unsaved buffer
当谈到 VIM 时,我有一些奇怪的行为。
我期望的行为:
编辑文件时,如果处于插入模式并且在退出插入模式时没有对文件进行任何修改,则缓冲区应被视为“已保存”。
我实际得到的行为:
编辑文件时,当我退出插入模式而不进行任何修改时,缓冲区显示文件已被编辑。尽管
我通过打开 vim 的干净版本测试了此行为在 vim 中是否正常,似乎我期望的行为是默认行为。
这是我的配置片段,我的完整配置在这里:(https://github.com/TheBabu/Config/blob/master/.vimrc)
我假设是什么导致了这种行为,否则它可能是一个插件
"Setup
set shell=bash
set nowrap
set number
set nocompatible
set noshowmode
set directory^=$HOME/.vim/.swapfiles
set undofile
set mouse=a
syntax on
colorscheme neodark
hi Normal ctermbg=none
sign define transparent_sign
augroup SignColFixAu
au!
au BufReadPost *.c,*.cc,*.h,*.cpp,*.hh,*.hpp,*.py,*.js,*.php,*.rs exe "sign place 1111 name=transparent_sign line=1 file=".@%
augroup end
inoremap <cr> <space><bs><cr>
inoremap <esc> ~<bs><esc>
inoremap <expr> <up> pumvisible() ? "\<c-p>" : "~\<bs>\<up>"
inoremap <expr> <down> pumvisible() ? "\<c-p>" : "~\<bs>\<down>"
inoremap <Esc>x <Esc>x
"Tabs
set listchars=tab:➡\
set list
set autoindent
set noexpandtab
set tabstop=4
set shiftwidth=4
..SNIP...
"Plugins
Plugin 'VundleVim/Vundle.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'Valloric/YouCompleteMe'
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
Plugin 'easymotion/vim-easymotion'
Plugin 'w0rp/ale'
Plugin 'godlygeek/tabular'
Plugin 'LukeLike/auto-pairs'
Plugin 'ananagame/vimsence'
Plugin 'preservim/nerdcommenter'
call vundle#end()
filetype plugin indent on
...SNIP...
感谢您的帮助!
调试这个的一个很好的起点可能是在 vim 说它被编辑后比较原始版本和修改版本。
要查看更改,如果文件受 VCS 控制,请使用 git diff
,否则请使用 vim -d original_copy edited_copy
。
差异字符应该让您了解可能导致此问题的代码的副作用。如果您无法理解,请在此处粘贴差异。
问题是由您的 <Esc>
映射引起的:
inoremap <esc> ~<bs><esc>
此映射是插入一个 ~
字符然后在其上退格,这实际上不会更改内容,但仍将缓冲区标记为已修改。 (Vim 并没有真正跟踪缓冲区的确切内容,而是跟踪是否引入了任何更改,并且都插入了 ~
并在字符数上退格。)
您在评论中提到您使用此映射(连同 <CR>
映射)来更改 Vim 缩进的行为方式。 Vim 的通常行为是在移动到新行时删除自动缩进(在其他空行上使用 <CR>
)或离开插入模式(使用 <Esc>
。)
在 Vim 中似乎没有办法改变这种行为。但是默认的 Vim 行为实际上非常有用,因为它可以防止以到处都是尾随空格的行结束。 (许多人使用 Vim autocmd 来 trim 保存时的尾随空格,而其他人使用 git 挂钩或代码审查机器人来阻止具有尾随空格的源代码文件。)
我想您保留尾随空格的动机是这样您可以离开插入模式,然后在同一行上再次进入插入模式,同时保留缩进。但事实证明你真的 不需要 这样做,因为 Vim 有很多方法可以通过正确的缩进再次启动插入模式。
例如,如果您在当前行上方(O
)或下方插入一行(o
),Vim 将在新行上插入适当的缩进.如果你在一个空行上并想在那里开始插入,那么不要使用 i
来启动插入模式,而是使用 S
来替换当前行的内容。由于该行是空的,因此不会有任何要替换的内容,但是 S
命令将以当前缩进开始替换,因此应该也可以解决这个问题。
如果您已经处于插入模式(不一定在行首),您还可以使用 Ctrl+F 让 Vim 对当前行应用正确的缩进,所以这也是一个选项。对于某些语言(特别是 Python),Vim 不能总是找到正确的缩进(因为您缩进是结束一个块),所以 Vim 可能无法猜对。在这些情况下,您还可以使用 Ctrl+T 来增加缩进和 Ctrl+D 减少它。两者都是插入模式命令,可以在行中的任何位置执行。
希望通过使用这些命令,您将能够放弃用于跟踪缩进的尾随空格并删除这些映射。
当谈到 VIM 时,我有一些奇怪的行为。
我期望的行为: 编辑文件时,如果处于插入模式并且在退出插入模式时没有对文件进行任何修改,则缓冲区应被视为“已保存”。
我实际得到的行为: 编辑文件时,当我退出插入模式而不进行任何修改时,缓冲区显示文件已被编辑。尽管
我通过打开 vim 的干净版本测试了此行为在 vim 中是否正常,似乎我期望的行为是默认行为。
这是我的配置片段,我的完整配置在这里:(https://github.com/TheBabu/Config/blob/master/.vimrc) 我假设是什么导致了这种行为,否则它可能是一个插件
"Setup
set shell=bash
set nowrap
set number
set nocompatible
set noshowmode
set directory^=$HOME/.vim/.swapfiles
set undofile
set mouse=a
syntax on
colorscheme neodark
hi Normal ctermbg=none
sign define transparent_sign
augroup SignColFixAu
au!
au BufReadPost *.c,*.cc,*.h,*.cpp,*.hh,*.hpp,*.py,*.js,*.php,*.rs exe "sign place 1111 name=transparent_sign line=1 file=".@%
augroup end
inoremap <cr> <space><bs><cr>
inoremap <esc> ~<bs><esc>
inoremap <expr> <up> pumvisible() ? "\<c-p>" : "~\<bs>\<up>"
inoremap <expr> <down> pumvisible() ? "\<c-p>" : "~\<bs>\<down>"
inoremap <Esc>x <Esc>x
"Tabs
set listchars=tab:➡\
set list
set autoindent
set noexpandtab
set tabstop=4
set shiftwidth=4
..SNIP...
"Plugins
Plugin 'VundleVim/Vundle.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'Valloric/YouCompleteMe'
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
Plugin 'easymotion/vim-easymotion'
Plugin 'w0rp/ale'
Plugin 'godlygeek/tabular'
Plugin 'LukeLike/auto-pairs'
Plugin 'ananagame/vimsence'
Plugin 'preservim/nerdcommenter'
call vundle#end()
filetype plugin indent on
...SNIP...
感谢您的帮助!
调试这个的一个很好的起点可能是在 vim 说它被编辑后比较原始版本和修改版本。
要查看更改,如果文件受 VCS 控制,请使用 git diff
,否则请使用 vim -d original_copy edited_copy
。
差异字符应该让您了解可能导致此问题的代码的副作用。如果您无法理解,请在此处粘贴差异。
问题是由您的 <Esc>
映射引起的:
inoremap <esc> ~<bs><esc>
此映射是插入一个 ~
字符然后在其上退格,这实际上不会更改内容,但仍将缓冲区标记为已修改。 (Vim 并没有真正跟踪缓冲区的确切内容,而是跟踪是否引入了任何更改,并且都插入了 ~
并在字符数上退格。)
您在评论中提到您使用此映射(连同 <CR>
映射)来更改 Vim 缩进的行为方式。 Vim 的通常行为是在移动到新行时删除自动缩进(在其他空行上使用 <CR>
)或离开插入模式(使用 <Esc>
。)
在 Vim 中似乎没有办法改变这种行为。但是默认的 Vim 行为实际上非常有用,因为它可以防止以到处都是尾随空格的行结束。 (许多人使用 Vim autocmd 来 trim 保存时的尾随空格,而其他人使用 git 挂钩或代码审查机器人来阻止具有尾随空格的源代码文件。)
我想您保留尾随空格的动机是这样您可以离开插入模式,然后在同一行上再次进入插入模式,同时保留缩进。但事实证明你真的 不需要 这样做,因为 Vim 有很多方法可以通过正确的缩进再次启动插入模式。
例如,如果您在当前行上方(O
)或下方插入一行(o
),Vim 将在新行上插入适当的缩进.如果你在一个空行上并想在那里开始插入,那么不要使用 i
来启动插入模式,而是使用 S
来替换当前行的内容。由于该行是空的,因此不会有任何要替换的内容,但是 S
命令将以当前缩进开始替换,因此应该也可以解决这个问题。
如果您已经处于插入模式(不一定在行首),您还可以使用 Ctrl+F 让 Vim 对当前行应用正确的缩进,所以这也是一个选项。对于某些语言(特别是 Python),Vim 不能总是找到正确的缩进(因为您缩进是结束一个块),所以 Vim 可能无法猜对。在这些情况下,您还可以使用 Ctrl+T 来增加缩进和 Ctrl+D 减少它。两者都是插入模式命令,可以在行中的任何位置执行。
希望通过使用这些命令,您将能够放弃用于跟踪缩进的尾随空格并删除这些映射。