[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] scratch/add-vdiff 952440e 002/258: Initial commit
From: |
Justin Burkett |
Subject: |
[elpa] scratch/add-vdiff 952440e 002/258: Initial commit |
Date: |
Wed, 17 May 2017 08:13:10 -0400 (EDT) |
branch: scratch/add-vdiff
commit 952440e4841fc4933296b19624314c25b88ae16a
Author: justbur <address@hidden>
Commit: justbur <address@hidden>
Initial commit
---
vdiff.el | 540 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 540 insertions(+)
diff --git a/vdiff.el b/vdiff.el
new file mode 100644
index 0000000..4bd21db
--- /dev/null
+++ b/vdiff.el
@@ -0,0 +1,540 @@
+(defvar vdiff-buffer-a nil)
+(defvar vdiff-buffer-b nil)
+(defvar vdiff-process-buffer " *vdiff*")
+(defvar vdiff-diff-data nil)
+(defvar vdiff-diff-data-w-text nil)
+(defvar vdiff-diff-code-regexp
+ "^\\([0-9]+\\),?\\([0-9]+\\)?\\([adc]\\)\\([0-9]+\\),?\\([0-9]+\\)?")
+(defvar vdiff-diff-program (executable-find "diff"))
+
+;; * Utilities
+
+(defun vdiff-maybe-int (str)
+ (when str (string-to-int str)))
+
+(defun vdiff-buffer-a-p ()
+ (eq (current-buffer) vdiff-buffer-a))
+
+(defun vdiff-buffer-b-p ()
+ (eq (current-buffer) vdiff-buffer-b))
+
+(defun vdiff-buffer-p ()
+ (memq (current-buffer) (list vdiff-buffer-a vdiff-buffer-b)))
+
+(defun vdiff-other-buffer ()
+ (if (vdiff-buffer-a-p) vdiff-buffer-b vdiff-buffer-a))
+
+(defun vdiff-other-window ()
+ (get-buffer-window (vdiff-other-buffer)))
+
+(defun vdiff-move-to-line (n)
+ (goto-char (point-min))
+ (forward-line (1- n)))
+
+(defun vdiff-overlay-at-point (&optional prior pos)
+ (let ((pos (or pos (point))))
+ (catch 'yes
+ (dolist (ovr (overlays-at
+ (if prior
+ (max (point-min)
+ (1- pos))
+ pos)))
+ (when (overlay-get ovr 'vdiff-type)
+ (throw 'yes ovr))))))
+
+(defun vdiff-overlays-in-region (beg end)
+ (let (ovrs)
+ (dolist (ovr (overlays-in beg end))
+ (when (overlay-get ovr 'vdiff-type)
+ (push ovr ovrs)))
+ (nreverse ovrs)))
+
+(defun vdiff-maybe-exit-overlay (&optional up)
+ (let* ((ovr (vdiff-overlay-at-point up))
+ (type (when ovr (overlay-get ovr 'vdiff-type))))
+ (when (memq type '(addition change))
+ (let ((range (overlay-get ovr 'vdiff-range)))
+ (goto-char (if up (car range) (cdr range)))))))
+
+(defvar vdiff-inhibit-window-switch nil)
+
+(defmacro vdiff-with-other-window (&rest body)
+ `(when (and (vdiff-buffer-p)
+ (not vdiff-inhibit-window-switch)
+ (vdiff-other-window))
+ (setq vdiff-inhibit-window-switch t)
+ (save-selected-window
+ (unwind-protect
+ (progn
+ (select-window (vdiff-other-window))
+ ,@body)
+ (setq vdiff-inhibit-window-switch nil)))))
+
+;; (defun vdiff-diff-sentinel (process event)
+;; (cond ((string= event "finished\n"))
+;; ((string-match "exited abnormally with code \\([0-9]+\\)\n" event)
+;; (user-error "%s" event))))
+
+
+(defun vdiff-parse-diff-output ()
+ (setq vdiff-diff-data nil)
+ (let (res)
+ (with-current-buffer vdiff-process-buffer
+ (goto-char (point-min))
+ (while (re-search-forward vdiff-diff-code-regexp nil t)
+ (push (list (match-string 3)
+ (cons (vdiff-maybe-int (match-string 1))
+ (vdiff-maybe-int (match-string 2)))
+ (cons (vdiff-maybe-int (match-string 4))
+ (vdiff-maybe-int (match-string 5))))
+ res)))
+ (setq vdiff-diff-data (nreverse res))))
+
+(defun vdiff-calc-diff ()
+ (let ((file-a (make-temp-file "vdiff-a-"))
+ (file-b (make-temp-file "vdiff-b-"))
+ line-string hunk-header a-lines b-lines res
+ message-log-max)
+ (with-current-buffer vdiff-buffer-a
+ (write-region nil nil file-a))
+ (with-current-buffer vdiff-buffer-b
+ (write-region nil nil file-b))
+ (with-current-buffer (get-buffer-create vdiff-process-buffer)
+ (erase-buffer))
+ (call-process vdiff-diff-program
+ nil vdiff-process-buffer nil
+ file-a file-b)
+ (vdiff-parse-diff-output)))
+
+(defun vdiff-remove-all-overlays ()
+ (with-current-buffer vdiff-buffer-a
+ (remove-overlays))
+ (with-current-buffer vdiff-buffer-b
+ (remove-overlays)))
+
+(defun vdiff-save-buffers ()
+ (with-current-buffer vdiff-buffer-a
+ (save-buffer))
+ (with-current-buffer vdiff-buffer-b
+ (save-buffer)))
+
+;; * Add overlays
+
+(defvar vdiff-subtraction-overlays '())
+(defvar vdiff-change-overlays '())
+
+(defun vdiff-add-subtraction-overlays
+ (buffer start-line target-range amount)
+ (with-current-buffer buffer
+ (vdiff-move-to-line start-line)
+ (end-of-line)
+ (let ((position (1+ (point)))
+ text)
+ (dotimes (i amount)
+ (push
+ (make-string
+ (1- (window-width (get-buffer-window vdiff-buffer-a))) ?-)
+ text))
+ (let ((ovr (make-overlay position (1+ position))))
+ (overlay-put ovr 'before-string
+ (propertize
+ (concat
+ (mapconcat #'identity text "\n")
+ "\n")
+ 'face '(:background "#440000")))
+ (overlay-put ovr 'vdiff-type 'subtraction)
+ (overlay-put ovr 'vdiff-target-range target-range)
+ (push ovr vdiff-subtraction-overlays)))))
+
+(defun vdiff-add-change-overlays
+ (buffer start-line lines target-range &optional addition)
+ (with-current-buffer buffer
+ (vdiff-move-to-line start-line)
+ (let ((beg (point))
+ (end (progn (forward-line lines)
+ (point))))
+ (let ((ovr (make-overlay beg end)))
+ (overlay-put ovr 'face (if addition
+ '(:background "#004422")
+ '(:background "#353500")))
+ (overlay-put ovr 'vdiff-type (if addition
+ 'addition
+ 'change))
+ (overlay-put ovr 'vdiff-range (cons beg end))
+ (overlay-put ovr 'vdiff-target-range target-range)
+ (push ovr vdiff-change-overlays)))))
+
+(defun vdiff-refresh-diff-overlays ()
+ (interactive)
+ (vdiff-remove-all-overlays)
+ (vdiff-calc-diff)
+ (vdiff-refresh-line-maps)
+ (save-excursion
+ (dolist (header vdiff-diff-data)
+ (let* ((code (nth 0 header))
+ (a-range (nth 1 header))
+ (a-beg (car a-range))
+ (a-end (if (cdr-safe a-range)
+ (cdr a-range)
+ (car a-range)))
+ (a-norm-range (cons a-beg a-end))
+ (a-length (1+ (- a-end a-beg)))
+ (b-range (nth 2 header))
+ (b-beg (car b-range))
+ (b-end (if (cdr-safe b-range)
+ (cdr b-range)
+ (car b-range)))
+ (b-norm-range (cons b-beg b-end))
+ (b-length (1+ (- b-end b-beg))))
+ (cond ((string= code "d")
+ (vdiff-add-subtraction-overlays
+ vdiff-buffer-b b-beg a-norm-range a-length)
+ (vdiff-add-change-overlays
+ vdiff-buffer-a a-beg a-length b-norm-range t))
+ ((string= code "a")
+ (vdiff-add-subtraction-overlays
+ vdiff-buffer-a a-beg b-norm-range b-length)
+ (vdiff-add-change-overlays
+ vdiff-buffer-b b-beg b-length a-norm-range t))
+ ((and (string= code "c") (> a-length b-length))
+ (vdiff-add-change-overlays
+ vdiff-buffer-a a-beg a-length b-norm-range)
+ (vdiff-add-change-overlays
+ vdiff-buffer-b b-beg b-length a-norm-range)
+ (vdiff-add-subtraction-overlays
+ vdiff-buffer-b b-end nil (- a-length b-length)))
+ ((and (string= code "c") (< a-length b-length))
+ (vdiff-add-change-overlays
+ vdiff-buffer-a a-beg a-length b-norm-range)
+ (vdiff-add-change-overlays
+ vdiff-buffer-b b-beg b-length a-norm-range)
+ (vdiff-add-subtraction-overlays
+ vdiff-buffer-a a-end nil (- b-length a-length)))
+ ((string= code "c")
+ (vdiff-add-change-overlays
+ vdiff-buffer-a a-beg a-length b-norm-range)
+ (vdiff-add-change-overlays
+ vdiff-buffer-b b-beg b-length a-norm-range)))))))
+
+;; * Moving changes
+
+(defun vdiff-push-changes (beg end &optional pull)
+ (interactive
+ (if (region-active-p)
+ (list (region-beginning) (region-end))
+ (list (if (or (= (line-number-at-pos) 1)
+ (vdiff-overlay-at-point
+ nil (line-beginning-position)))
+ (line-beginning-position)
+ (save-excursion
+ (forward-line -1)
+ (line-beginning-position)))
+ (line-end-position))))
+ (let* ((ovrs (overlays-in beg end)))
+ (dolist (ovr ovrs)
+ (cond ((memq (overlay-get ovr 'vdiff-type)
+ '(change addition))
+ (vdiff-push-pull-change-overlay ovr pull))
+ ((eq (overlay-get ovr 'vdiff-type) 'subtraction)
+ (vdiff-push-pull-subtraction-overlay ovr pull))))
+ (vdiff-refresh-diff-overlays)))
+
+(defun vdiff-pull-changes (beg end)
+ (interactive
+ (if (region-active-p)
+ (list (region-beginning) (region-end))
+ (list (if (or (= (line-number-at-pos) 1)
+ (vdiff-overlay-at-point
+ nil (line-beginning-position)))
+ (line-beginning-position)
+ (save-excursion
+ (forward-line -1)
+ (line-beginning-position)))
+ (line-end-position))))
+ (vdiff-push-changes beg end t))
+
+(defun vdiff-push-pull-change-overlay (chg-ovr &optional pull)
+ (cond ((not (overlayp chg-ovr))
+ (message "No change found"))
+ (pull
+ (let* ((target-rng (overlay-get chg-ovr 'vdiff-target-range))
+ (pos (vdiff-pos-at-line-beginning
+ (car target-rng) (vdiff-other-buffer))))
+ (vdiff-with-other-window
+ (vdiff-push-changes pos (1+ pos)))))
+ (t
+ (let* ((addition (eq 'addition (overlay-get chg-ovr 'vdiff-type)))
+ (target-rng (overlay-get chg-ovr 'vdiff-target-range))
+ (text (buffer-substring-no-properties
+ (overlay-start chg-ovr)
+ (overlay-end chg-ovr))))
+ (with-current-buffer (vdiff-other-buffer)
+ (if addition
+ (vdiff-move-to-line (1+ (car target-rng)))
+ (vdiff-move-to-line (car target-rng))
+ (delete-region (point)
+ (save-excursion
+ (forward-line
+ (1+ (- (cdr target-rng)
+ (car target-rng))))
+ (point))))
+ (insert text))))))
+
+(defun vdiff-push-pull-subtraction-overlay (sub-ovr &optional pull)
+ (cond ((not (overlayp sub-ovr))
+ (message "No change found"))
+ (pull
+ (let* ((target-rng (overlay-get sub-ovr 'vdiff-target-range))
+ (pos (vdiff-pos-at-line-beginning
+ (car target-rng) (vdiff-other-buffer))))
+ (vdiff-with-other-window
+ (vdiff-push-changes pos (1+ pos)))))
+ (t
+ (let* ((target-rng
+ (overlay-get sub-ovr 'vdiff-target-range)))
+ (when target-rng
+ (with-current-buffer (vdiff-other-buffer)
+ (vdiff-move-to-line (car target-rng))
+ (delete-region (point)
+ (save-excursion
+ (vdiff-move-to-line
+ (1+ (cdr target-rng)))
+ (point)))))))))
+
+;; * Scrolling and line syncing
+
+(defvar vdiff-line-map nil)
+
+(defun vdiff-refresh-line-maps ()
+ (let (new-map)
+ (dolist (entry vdiff-diff-data)
+ (let* ((code (car entry))
+ (a-lines (nth 1 entry))
+ (a-beg (car a-lines))
+ (a-end (or (cdr-safe a-lines)
+ (car a-lines)))
+ ;; (a-length (1+ (- a-end a-beg)) )
+ (b-lines (nth 2 entry))
+ (b-beg (car b-lines))
+ (b-end (or (cdr-safe b-lines)
+ (car b-lines)))
+ ;; (b-length (1+ (- b-end b-beg)))
+ (delta 0))
+ (cond ((string= code "d")
+ (push (cons (1- a-beg) b-beg) new-map)
+ (push (cons (1+ a-end) (1+ b-end)) new-map))
+ ((string= code "a")
+ (push (cons a-beg (1- b-beg)) new-map)
+ (push (cons (1+ a-end) (1+ b-end)) new-map))
+ ((and (string= code "c"))
+ (push (cons (1- a-beg) (1- b-beg)) new-map)
+ (push (cons (1+ a-end) (1+ b-end)) new-map)))))
+ (setq vdiff-line-map (nreverse new-map))))
+
+(defun vdiff-translate-line (line &optional B-to-A)
+ (let ((nearest-line
+ (catch 'closest
+ (let (closest)
+ (dolist (entry vdiff-line-map)
+ (if (> (if B-to-A
+ (cdr entry)
+ (car entry)) line)
+ (throw 'closest closest)
+ (setq closest entry)))
+ (throw 'closest closest)))))
+ (cond ((and nearest-line B-to-A)
+ (+ (- line (cdr nearest-line)) (car nearest-line)))
+ (nearest-line
+ (+ (- line (car nearest-line)) (cdr nearest-line)))
+ (t line))))
+
+(defun vdiff-goto-corresponding-line (line in-b)
+ (interactive (list (line-number-at-pos)
+ (not (vdiff-buffer-a-p))))
+ (vdiff-refresh-diff-overlays)
+ (let* ((new-line (vdiff-translate-line line in-b))
+ (new-pos (vdiff-pos-at-line-beginning new-line)))
+ (select-window (vdiff-other-window))
+ (goto-char new-pos)))
+
+(defun vdiff-sync-line (line in-a)
+ (interactive (list (line-number-at-pos)
+ (not (vdiff-buffer-a-p))))
+ (let ((new-line (vdiff-translate-line
+ line (not in-a)))
+ (other-buffer (vdiff-other-buffer))
+ (other-window (vdiff-other-window)))
+ (set-window-point
+ other-window
+ (vdiff-pos-at-line-beginning new-line other-buffer))))
+
+(defun vdiff-sync-and-center ()
+ (interactive)
+ (vdiff-sync-line (line-number-at-pos) (vdiff-buffer-a-p))
+ (recenter)
+ (vdiff-with-other-window
+ (recenter)))
+
+(defvar vdiff-window-a-start nil)
+(defvar vdiff-window-b-start nil)
+
+(defun vdiff-pos-at-line-beginning (line &optional buffer)
+ (with-current-buffer (or buffer (current-buffer))
+ (save-excursion
+ (vdiff-move-to-line line)
+ (line-beginning-position))))
+
+(defun vdiff-scroll-other (window window-start)
+ (let ((win-a (get-buffer-window vdiff-buffer-a))
+ (win-b (get-buffer-window vdiff-buffer-b)))
+ (when (and (eq window (selected-window))
+ (window-live-p win-a)
+ (window-live-p win-b)
+ (memq window (list win-a win-b)))
+ (let* ((in-b (eq window win-b))
+ (this-window (if in-b win-b win-a))
+ (other-window (if in-b win-a win-b))
+ (other-buffer (if in-b vdiff-buffer-a
+ vdiff-buffer-b))
+ (this-line (line-number-at-pos (point)))
+ (other-line (vdiff-translate-line
+ this-line in-b))
+ (this-start (line-number-at-pos window-start))
+ (other-start (vdiff-translate-line
+ this-start in-b))
+ (other-start-pos (vdiff-pos-at-line-beginning
+ other-start other-buffer))
+ other-pos)
+ (set-window-start other-window other-start-pos)
+ (vdiff-with-other-window
+ (goto-char (vdiff-pos-at-line-beginning other-line)))))))
+
+(defun vdiff-toggle-lock ()
+ (interactive)
+ (with-current-buffer vdiff-buffer-a
+ (vdiff-sync-line (line-number-at-pos) t)
+ (scroll-all-mode)))
+
+(defvar vdiff-scroll-command-cnt 0)
+(defvar vdiff-copied-commands '(next-line
+ previous-line
+ evil-next-line
+ evil-previous-line
+ beginning-of-buffer
+ end-of-buffer))
+(defvar vdiff-inhibit-sync nil)
+
+(defun vdiff-sync-scroll ()
+ ;; Use real-this-command because evil-next-line and evil-previous-line
pretend
+ ;; they are next-line and previous-line
+ (when (and (memq real-this-command vdiff-copied-commands)
+ (not vdiff-inhibit-sync))
+ (let ((this-line (line-number-at-pos))
+ ;; This is necessary to not screw up the cursor column after calling
+ ;; next-line or previous-line again from the other buffer
+ temporary-goal-column)
+ (vdiff-with-other-window
+ (ignore-errors
+ (let ((vdiff-inhibit-sync t))
+ (call-interactively real-this-command))
+ (if (< vdiff-scroll-command-cnt 40)
+ (incf vdiff-scroll-command-cnt)
+ ;; (message "syncing lines")
+ (setq vdiff-scroll-command-cnt 0)
+ (vdiff-move-to-line
+ (vdiff-translate-line
+ this-line (vdiff-buffer-a-p)))))))))
+
+;; * Movement
+
+(defun vdiff-next-change ()
+ (interactive)
+ (vdiff-maybe-exit-overlay)
+ (let ((next (next-overlay-change (point))))
+ (if (= next (point-max))
+ (message "No more changes")
+ (goto-char next)
+ (while (and (not (eobp))
+ (not (vdiff-overlay-at-point)))
+ (goto-char next)
+ (setq next (next-overlay-change (point))))
+ (vdiff-sync-and-center))))
+
+(defun vdiff-previous-change ()
+ (interactive)
+ (vdiff-maybe-exit-overlay t)
+ (let ((next (previous-overlay-change (point))))
+ (if (= next (point-min))
+ (message "No more changes")
+ (goto-char next)
+ (while (and (not (bobp))
+ (not (vdiff-overlay-at-point)))
+ (goto-char next)
+ (setq next (previous-overlay-change (point))))
+ (vdiff-sync-and-center))))
+
+
+;; * Entry points
+
+(defun vdiff-files (A B &optional horizontal)
+ (interactive (let ((file-a (read-file-name "File 1: ")))
+ (list
+ file-a
+ (read-file-name
+ (format "[File 1 %s] File 2: "
+ (file-name-nondirectory file-a)))
+ current-prefix-arg)))
+ (let (a-window b-window)
+ (delete-other-windows)
+ (find-file A)
+ (goto-char (point-min))
+ (setq vdiff-buffer-a (current-buffer))
+ (setq b-window (if horizontal
+ (split-window-vertically)
+ (split-window-horizontally)))
+ (find-file-other-window B)
+ (setq vdiff-buffer-b (window-buffer b-window))
+ (setq vdiff-window-a-start
+ (window-start (get-buffer-window vdiff-buffer-a)))
+ (setq vdiff-window-b-start (window-start b-window))
+ (with-current-buffer vdiff-buffer-a
+ (vdiff-mode 1))
+ (with-current-buffer vdiff-buffer-b
+ (vdiff-mode 1))
+ (vdiff-refresh-diff-overlays)))
+
+(defvar vdiff-mode-map (make-sparse-keymap))
+(define-key vdiff-mode-map "\C-l" 'vdiff-sync-and-center)
+(define-key vdiff-mode-map "\C-cg" 'vdiff-goto-corresponding-line)
+(define-key vdiff-mode-map "\C-cn" 'vdiff-next-change)
+(define-key vdiff-mode-map "\C-cp" 'vdiff-previous-change)
+(define-key vdiff-mode-map "\C-ct" 'vdiff-push-changes)
+(define-key vdiff-mode-map "\C-co" 'vdiff-pull-changes)
+
+(define-minor-mode vdiff-mode
+ " "
+ nil " VDIFF" 'vdiff-mode-map
+ (if vdiff-mode
+ (progn
+ ;; (add-hook 'evil-insert-state-exit-hook
+ ;; #'vdiff-refresh-diff-overlays)
+ (setq cursor-in-non-selected-windows nil)
+ (add-hook 'after-save-hook #'vdiff-refresh-diff-overlays nil t)
+ (add-hook 'window-scroll-functions #'vdiff-scroll-other)
+ (add-hook 'post-command-hook #'vdiff-sync-scroll)
+ )
+ ;; (add-hook 'evil-insert-state-exit-hook
+ ;; #'vdiff-refresh-diff-overlays)
+ (setq cursor-in-non-selected-windows t)
+ (setq vdiff-diff-data nil)
+ (setq vdiff-diff-data-w-text nil)
+ (vdiff-remove-all-overlays)
+ (remove-hook 'post-command-hook #'vdiff-sync-scroll)
+ (remove-hook 'after-save-hook #'vdiff-refresh-diff-overlays t)
+ (remove-hook 'window-scroll-functions #'vdiff-scroll-other)))
+
+;; (evil-define-minor-mode-key 'normal vdiff-mode
+;; (kbd "<up>") 'vdiff-previous-change
+;; (kbd "<right>") 'vdiff-push-changes
+;; (kbd "<left>") 'vdiff-pull-changes
+;; (kbd "<down>") 'vdiff-next-change)
- [elpa] scratch/add-vdiff 28c939f 194/258: Document new option, (continued)
- [elpa] scratch/add-vdiff 28c939f 194/258: Document new option, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 133e187 193/258: Allow folds to close on point but make optional, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 4dd194b 190/258: Update screenshot with refinements, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff b840935 202/258: Use more specific faces for refinements, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff f4332f2 212/258: Fix typo in Commentary section, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 1549115 005/258: Add option to lock scrolling by default, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 0f640d3 007/258: Add header info, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 72c20a5 010/258: Add gitignore, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 016518f 016/258: Fix folds at end of buffer, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 10b7760 018/258: Add faces, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 952440e 002/258: Initial commit,
Justin Burkett <=
- [elpa] scratch/add-vdiff 245850f 028/258: Load cl-lib for using its function, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 988c476 027/258: Add new defcustoms to README, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff b77efe3 008/258: Add README and improve docstrings, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff ce10994 003/258: Introduce defcustoms and use lists instead of .., Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff ad6035d 015/258: Implement folding of unchanged lines, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff af75c6d 036/258: Add vdiff-exit, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff e8834fa 035/258: Fix fold size calcs, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 9547850 041/258: Use diff faces from theme, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff bac92b3 037/258: Improve line translation and command mirroring, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 6b6f6e7 044/258: Force fold refresh on window size change, Justin Burkett, 2017/05/17