Improved Hex editing
From Vim Tips Wiki
Tip 1518 • Previous Tip • Next Tip
Created: October 3, 2007 Complexity: basic Author: Fritzophrenic Version: 7.0
The help files for Vim include the following advice for automating the xxd-style hex editing capabilities for Vim:
" vim -b : edit binary using xxd-format! augroup Binary au! au BufReadPre *.bin let &bin=1 au BufReadPost *.bin if &bin | %!xxd au BufReadPost *.bin set ft=xxd | endif au BufWritePre *.bin if &bin | %!xxd -r au BufWritePre *.bin endif au BufWritePost *.bin if &bin | %!xxd au BufWritePost *.bin set nomod | endif augroup END
There are a few problems with this approach:
- Only files with a .bin extension are opened this way, even if editing a file in binary mode (e.g. with ++bin)
- This sets the binary option for any future documents opened as well. If you use tabe, for example, or if you have Vim set up to open new files in tabs, then any new files opened will open in binary mode.
- If you decide to edit a binary file without the xxd, the BufWrite autocommands will try to convert it with xxd -r anyway.
- Viewing a file in "xxd mode" requires you to modify the file, so read-only files will warn you if you try to do so, even if you make no changes. Buffers with 'nomodifiable' will cause errors.
- If you go back into non-xxd editing, the filetype will still be xxd.
These problems can be fixed as follows:
- Trigger on all files if they are being edited with the binary option. Modify the extension-specific autocmd to set the binary option.
- Use setlocal rather than using the global binary option.
- Maintain a variable for each buffer that tracks whether the file is in "xxd mode". Only restore to non-xxd before writing if this variable says we are in the appropriate mode.
- Temporarily clear the read-only flag whenever you transition between xxd and non-xxd mode, resetting it afterward.
- Store the filetype when entering xxd mode and restore it when leaving.
Below is some code for your vimrc file that does all of this:
" autocmds to automatically enter hex mode and handle file writes properly
if has("autocmd")
" vim -b : edit binary using xxd-format!
augroup Binary
au!
au BufReadPre *.bin,*.hex setlocal binary
au BufReadPost *
\ if &binary | Hexmode | endif
au BufWritePre *
\ if exists("b:editHex") && b:editHex && &binary |
\ let oldro=&ro | let &ro=0 |
\ let oldma=&ma | let &ma=1 |
\ exe "%!xxd -r" |
\ let &ma=oldma | let &ro=oldro |
\ unlet oldma | unlet oldro |
\ endif
au BufWritePost *
\ if exists("b:editHex") && b:editHex && &binary |
\ let oldro=&ro | let &ro=0 |
\ let oldma=&ma | let &ma=1 |
\ exe "%!xxd" |
\ exe "set nomod" |
\ let &ma=oldma | let &ro=oldro |
\ unlet oldma | unlet oldro |
\ endif
augroup END
endif
" ex command for toggling hex mode - define mapping if desired
command -bar Hexmode call ToggleHex()
" helper function to toggle hex mode
function ToggleHex()
" hex mode should be considered a read-only operation
" save values for modified and read-only for restoration later,
" and clear the read-only flag for now
let l:modified=&mod
let l:oldreadonly=&readonly
let &readonly=0
let l:oldmodifiable=&modifiable
let &modifiable=1
if !exists("b:editHex") || !b:editHex
" save old options
let b:oldft=&ft
let b:oldbin=&bin
" set new options
setlocal binary " make sure it overrides any textwidth, etc.
let &ft="xxd"
" set status
let b:editHex=1
" switch to hex editor
%!xxd
else
" restore old options
let &ft=b:oldft
if !b:oldbin
setlocal nobinary
endif
" set status
let b:editHex=0
" return to normal editing
%!xxd -r
endif
" restore values for modified and read only state
let &mod=l:modified
let &readonly=l:oldreadonly
let &modifiable=l:oldmodifiable
endfunction
This will make Vim automatically use xxd-format hex editing when the file is opened in binary mode, and will automatically (locally) set binary mode for .bin and .hex files! In addition, it provides a command "Hexmode" for entering the xxd format properly. You may want to use key mappings to allow easier access.
You may need to take steps to avoid the "Hit ENTER to continue prompt if you use this tip.
Here are commands to use to launch any file(s) in hex mode in a separate "hex editor" Vim server. Under Windows, you can easily add these commands to your "Send To" menu if you use the full path for gvim.exe in place of "vim". Remove the "-p" and "--remote-tab-silent" option if you do not want the tabbed interface. The -c "set binary" ensures that any tabwidth, wrap, etc. settings are overwritten after the file finishes loading.
- Launch in tabs in a new dedicated Vim hex editor: vim -p -b -c "set binary" --servername HEXVIM <files>
- Launch in tabs in an existing dedicated Vim hex editor: vim -b -c "set binary" --servername HEXVIM --remote-tab-silent <files>
[edit] References
- :help hex-editing
- :help :autocmd
- :help internal-variables
- :help edit-binary
- Set_options_or_named_registers_with_let
[edit] Comments
script#666 provides similar (and extended) capability, though I have never used it and can't vouch for its usefulness/completeness/correctness.
