Skip to content

Latest commit

 

History

History
222 lines (163 loc) · 8.44 KB

README.md

File metadata and controls

222 lines (163 loc) · 8.44 KB

Intro

vim plugin to diff two directories like BeyondCompare by using diff

inspired by will133/vim-dirdiff

  • why another directory diff plugin?

    • fully async and queued, works well with tons of files, even for vim 7.3! (by ZFVimJob)
    • works well on Windows without sh or diff env
    • format the diff result as vertical split file tree view, which should be more human-readable
    • more friendly file sync operation using the same mappings as builtin vimdiff
    • automatically backup before destructive actions (by ZFVimBackup)
    • better file or directory exclude logic (by ZFVimIgnore)

if you like my work, check here for a list of my vim plugins, or buy me a coffee

How to use

  1. requirement

    • vim 8.0 or neovim : recommend, fully async
    • vim 7.3 or above : all features work as expected, with some lag due to lack of job
  2. install by vim-plug or any other plugin manager:

    Plug 'ZSaberLv0/ZFVimDirDiff'
    Plug 'ZSaberLv0/ZFVimJob' " required
    Plug 'ZSaberLv0/ZFVimIgnore' " optional, but recommended for auto ignore setup
    Plug 'ZSaberLv0/ZFVimBackup' " optional, but recommended for auto backup
    
  3. use :ZFDirDiff command to start diff

    :ZFDirDiff pathA pathB
    

    if path contains spaces:

    :ZFDirDiff path\ A path\ B
    :call ZFDirDiff("path A", "path B")
    
  4. use :ZFDirDiffMark to mark two directories to start diff

    Open a file and :ZFDirDiffMark and the containing directory will be stored as a diff candidate. Then repeat with another file and you'll be asked to diff the two.

    :edit pathA/file.vim
    :ZFDirDiffMark
    :edit pathB/file.vim
    :ZFDirDiffMark
    

    Or integrate with your file manager. For vim-dirvish, add ~/.vim/ftplugin/dirvish.vim:

     nnoremap <buffer> X :<C-u>ZFDirDiffMark <C-r><C-l><CR>
    

    Or for netrw, add ~/.vim/ftplugin/netrw.vim:

     nnoremap <buffer> X :<C-u>ZFDirDiffMark <C-r>=b:netrw_curdir<CR>/<C-r><C-l><CR>
    

    Then X on two directories.

  5. you can also start diff from scrooloose/nerdtree: inside nerdtree window, press m to popup menu, press z to choose mark to diff, and mark another node again to start diff

  6. you may also use it as command line diff tool

    vim -c 'call ZFDirDiff("path A", "path B")'
    sh ZFDirDiff.sh "path A" "path B"
    
  7. within the diff window:

    • use DD to update the diff result under cursor
    • use o or <cr> to diff current file, or fold/unfold current dir
    • use O to unfold all contents under current dir, x to fold to parent, X to fold to root
    • use cd to make current dir as diff root dir, u to go up for current side, and U to go up for both side
    • use DM to mark current file, and DM again on another file to diff these two files
    • use ]c or DJ to move to next diff, [c or DK to prev diff, use Dj / Dk to move to next / prev diff file
    • use do or DH to sync from another side to current side, dp or DL to sync from current side to another side
    • use a to add new file or dir
    • use dd to delete node under cursor
    • use DN to mark mutiple files, when done, use do/DH/dp/DL/dd to sync or delete marked files
    • use p to copy the node's path, and P for the node's full path
    • use q to exit diff
    • you may also want to use ZSaberLv0/ZFVimIndentMove or easymotion/vim-easymotion to quickly move between file tree node
  8. within the file diff window:

    • it's vim's builtin diff, see :h diff for more info
    • use q to quick file diff and back to owner diff window

Configs

this plugin should work well without any extra config

for experienced user, here's some configs you may interest

Diff logic

  • let g:ZFDirDiff_autoBackup = 1 : whether perform auto backup, see https://github.com/ZSaberLv0/ZFVimBackup

  • let g:ZFDirDiff_ignoreEmptyDir = 1 : whether ignore empty dir

  • let g:ZFDirDiff_ignoreSpace = 0 : whether ignore empty lines and spaces (not supported for python backend)

  • let g:ZFIgnoreOption_ZFDirDiff = {...} : ignore options, see https://github.com/ZSaberLv0/ZFVimIgnore

    let g:ZFIgnoreOption_ZFDirDiff = {
                \   'bin' : 0,
                \   'media' : 0,
                \   'ZFDirDiff' : 1,
                \ }
    

Keymap (inside diff window)

  • let g:ZFDirDiffKeymap_update = [] : update entire diff window
  • let g:ZFDirDiffKeymap_updateParent = ['DD'] : update diff under cursor
  • let g:ZFDirDiffKeymap_open = ['<cr>', 'o'] : toggle dir open or open file diff
  • let g:ZFDirDiffKeymap_foldOpenAll = [] : open all node under cursor, including same files
  • let g:ZFDirDiffKeymap_foldOpenAllDiff = ['O'] : open all diff node under cursor
  • let g:ZFDirDiffKeymap_foldClose = ['x'] : close node
  • let g:ZFDirDiffKeymap_foldCloseAll = ['X'] : close all node
  • let g:ZFDirDiffKeymap_goParent = ['U'] : make both left and right diff window go to parent dir
  • let g:ZFDirDiffKeymap_diffThisDir = ['cd'] : change current side's root to node under cursor
  • let g:ZFDirDiffKeymap_diffParentDir = ['u'] : change current side's root to parent
  • let g:ZFDirDiffKeymap_markToDiff = ['DM'] : mark node under cursor, mark again to diff with two marked node
  • let g:ZFDirDiffKeymap_markToSync = ['DN'] : mark one or more nodes, to sync mutiple nodes at once
  • let g:ZFDirDiffKeymap_quit = ['q'] : quit diff
  • let g:ZFDirDiffKeymap_diffNext = [']c', 'DJ'] : jump to next visible diff
  • let g:ZFDirDiffKeymap_diffPrev = ['[c', 'DK'] : jump to prev visible diff
  • let g:ZFDirDiffKeymap_diffNextFile = ['Dj'] : jump to next diff file, auto open closed dir
  • let g:ZFDirDiffKeymap_diffPrevFile = ['Dk'] : jump to prev diff file, auto open closed dir
  • let g:ZFDirDiffKeymap_syncToHere = ['do', 'DH'] : sync nodes from there to here
  • let g:ZFDirDiffKeymap_syncToThere = ['dp', 'DL'] : sync nodes from here to there
  • let g:ZFDirDiffKeymap_add = ['a'] : add new node, end with / to add dir
  • let g:ZFDirDiffKeymap_delete = ['dd'] : delete selected nodes
  • let g:ZFDirDiffKeymap_getPath = ['p'] : get relative path of node under cursor
  • let g:ZFDirDiffKeymap_getFullPath = ['P'] : get absolute path of node under cursor

Keymap (inside file diff window)

  • let g:ZFDirDiffKeymap_quitFileDiff = ['q'] : quit file diff, and go back to its owner diff window

UI spec

  • let g:ZFDirDiffUIChar_dir_prefix_closed = '+ '
  • let g:ZFDirDiffUIChar_dir_prefix_opened = '~ '
  • let g:ZFDirDiffUIChar_dir_postfix = '/'
  • let g:ZFDirDiffUIChar_file_prefix = ' '
  • let g:ZFDirDiffUIChar_file_postfix = ''
  • let g:ZFDirDiffUI_tabstop = 2
  • let g:ZFDirDiffUI_autoOpenSingleChildDir = 1
  • let g:ZFDirDiffUI_showSameDir = 1
  • let g:ZFDirDiffUI_showSameFile = 1

Highlight

highlight default link ZFDirDiffHL_Header Title
highlight default link ZFDirDiffHL_Tail Title
highlight default link ZFDirDiffHL_DirChecking SpecialKey
highlight default link ZFDirDiffHL_DirSame Folded
highlight default link ZFDirDiffHL_DirDiff DiffAdd
highlight default link ZFDirDiffHL_FileChecking SpecialKey
highlight default link ZFDirDiffHL_FileSame Folded
highlight default link ZFDirDiffHL_FileDiff DiffText
highlight default link ZFDirDiffHL_DirOnlyHere DiffAdd
highlight default link ZFDirDiffHL_FileOnlyHere DiffAdd
highlight default link ZFDirDiffHL_ConflictDirHere ErrorMsg
highlight default link ZFDirDiffHL_ConflictDirThere WarningMsg
highlight default link ZFDirDiffHL_MarkToDiff Cursor
highlight default link ZFDirDiffHL_MarkToSync Cursor

FAQ

  • Q: screen keeps blink when diff updating in background

    A: unfortunately, I have no idea for how to solve this issue, mainly because of matchadd() must inside proper window, causing frequent window switching

  • Q: use as git difftool --dir-diff

    A: #45