在vim中打开某些文件类型之前如何警告?

时间:2019-08-27 11:35:04

标签: bash vim

依靠命令行自动完成功能很容易用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上有一个相关问题,但主要是关于修改自动完成功能,以防止首先意外打开文件。

2 个答案:

答案 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想要什么。