It is easy to accidentally open a large binary or data file with vim when relying on command line autocomplete.
Is it possible to add an interactive warning when opening certain file types in vim?
For example, I'd like to add a warning when opening files without an extension:
> vim someBinary
Edit someBinary? [y/N]
Or maybe:
> vim someBinary
# vim buffer opens and displays warning about filetype,
# giving user a chance to quit before loading the file
This could be applied to a range of extensions, such as .pdf, .so, .o, .a, no extension, etc.
There is a related question on preventing vim from opening binary files, but it is primarily about modifying autocomplete to prevent accidentally opening the files in the first place.
Below is the solution I came up with, using vim autocommands with the BufReadCmd event. It's a lot of vimscript, but it's pretty robust. It issues a warning if the file being opened is a non-ascii file or has a blacklisted extension (.csv and .tsv for this example):
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
To read with syntax highlighting enabled, see this gist.
Maybe not super elegant, but I enjoyed learning some vimscript along the way.
I am not too experienced with vimscript so I'm sure there is room for improvements -- suggestions and alternative solutions welcome.
Note: This is not expected to work on Windows systems outside of WSL or Cygwin, due to calling file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With