依靠命令行自动完成功能很容易用vim意外地打开大型二进制文件或数据文件。
在vim中打开某些文件类型时是否可以添加交互式警告?
例如,我想在打开不带扩展名的文件时添加一条警告:
> vim someBinary
Edit someBinary? [y/N]
或者也许:
> vim someBinary
# vim buffer opens and displays warning about filetype,
# giving user a chance to quit before loading the file
这可以应用于一系列扩展名,例如.pdf
,.so
,.o
,.a
,无扩展名等。
preventing vim from opening binary files上有一个相关问题,但主要是关于修改自动完成功能,以防止首先意外打开文件。
答案 0 :(得分:2)
下面是我想出的解决方案,它在BufReadCmd
事件中使用了vim自动命令。它有很多vimscript,但是非常强大。如果正在打开的文件是非ascii文件或具有黑名单扩展名(在此示例中为.csv
和.tsv
),它将发出警告:
augroup bigfiles
" Clear the bigfiles group in case defined elsewhere
autocmd!
" Set autocommand to run before reading buffer
autocmd BufReadCmd * silent call PromptFileEdit()
augroup end
" Prompt user input if editing an existing file before reading
function! PromptFileEdit()
" Current file
let file = expand("%")
" Whether or not we should continue to open the file
let continue = 1
" Skip if file has an extension or is not readable
if filereadable(file) && (IsNonAsciiFile(file) || IsBlacklistedFile())
" Get response from user
let response = input('Are you sure you want to open "' . file . '"? [y/n]')
" Bail if response is a 'n' or contains a 'q'
if response ==? "n" || response =~ "q"
let continue = 0
if (winnr("$") == 1)
" Quit if it was the only buffer open
quit
else
" Close buffer if other buffers open
bdelete
endif
endif
endif
if continue == 1
" Edit the file
execute "e" file
" Run the remaining autocommands for the file
execute "doautocmd BufReadPost" file
endif
endfunction
" Return 1 if file is a non-ascii file, otherwise 0
function! IsNonAsciiFile(file)
let ret = 1
let fileResult = system('file ' . a:file)
" Check if file contains ascii or is empty
if fileResult =~ "ASCII" || fileResult =~ "empty" || fileResult =~ "UTF"
let ret = 0
endif
return ret
endfunction
" Return 1 if file is blacklisted, otherwise 0
function! IsBlacklistedFile()
let ret = 0
let extension = expand('%:e')
" List contains ASCII files that we don't want to open by accident
let blacklistExtensions = ['csv', 'tsv']
" Check if we even have an extension
if strlen(extension) == 0
let ret = 0
" Check if our extension is in the blacklisted extensions
elseif index(blacklistExtensions, extension) >= 0
let ret = 1
endif
return ret
endfunction
要在启用语法突出显示的情况下阅读,请参见此gist。
也许不是超级优雅,但是我喜欢在学习过程中学习一些vimscript。
我对vimscript不太了解,因此我确定还有改进的余地-欢迎提出建议和替代解决方案。
注意:由于调用file
,因此这在WSL或Cygwin之外的Windows系统上不起作用。
答案 1 :(得分:1)
您可以使用类似这样的功能
promptvim() {
grep -Fq "." <<< "$1" || read -p "Edit $1? [y/N]" && [[ $REPLY == "y" ]] || return
/usr/bin/vim "$1"
}
您可以选择其他功能名称。当您使用vim
时,其他脚本可能会失败。
编辑: 当您喜欢这种结构(包装器,而不是vim设置)时,可以通过更多测试使功能更好:
promptvim() {
if [ $# -eq 0 ]; then
echo "arguments are missing"
return
fi
local maybe_dot=$(grep -Fq "." <<< "$1")
for file in $*; do
# skip tests when creating a new file
if [ -f "${file}" ]; then
maybe_dot=$(grep -F "." <<< "${file}")
if (( ${#maybe_dot} == 0 )); then
read -p "Edit ${file}? [y/N]"
# check default response variable REPLY
# Convert to lowercase and check other ways of confirming too
if [[ ! "${REPLY,,}" =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
continue
fi
fi
fi
echo /usr/bin/vim "${file}"
done
}
这仍然不能涵盖所有特殊情况。您可能想在命令行上添加对vim
参数的支持,检查交互式会话,并考虑使用here documents
想要什么。