[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] scratch/add-vdiff 88ce867 088/258: Initial attempt at refine comm
From: |
Justin Burkett |
Subject: |
[elpa] scratch/add-vdiff 88ce867 088/258: Initial attempt at refine commands |
Date: |
Wed, 17 May 2017 08:13:28 -0400 (EDT) |
branch: scratch/add-vdiff
commit 88ce867215ca0d73ff9861f49fb14aa7fb1cb956
Author: justbur <address@hidden>
Commit: justbur <address@hidden>
Initial attempt at refine commands
* vdiff-default-refinement-syntax-code controls how words are defined in
refinements.
* vdiff-refine-this-change[-x] processes the sub-diff and highlights
changed words, where x may be word or symbol (default is word)
* vdiff-refine-all-changes is simliar for whole buffer
Create new code section
Combine two diff words functions
More word diff tweaks
more refinements
---
vdiff.el | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 209 insertions(+), 9 deletions(-)
diff --git a/vdiff.el b/vdiff.el
index 98f4cea..0396ba0 100644
--- a/vdiff.el
+++ b/vdiff.el
@@ -100,6 +100,19 @@ text on the first line, and the width of the buffer."
:group 'vdiff
:type 'function)
+(defcustom vdiff-default-refinement-syntax-code "w"
+ "Default syntax table class code to use for identifying
+\"words\" in \`vdiff-refine-this-change'. Some useful options are
+
+\"w\" (default) words
+\"w_\" symbols \(really words plus symbol constituents\)
+\"-\" whitespace
+
+For more information see
+https://www.gnu.org/software/emacs/manual/html_node/elisp/Syntax-Class-Table.html"
+ :group 'vdiff
+ :type 'string)
+
(defface vdiff-addition-face
'((t :inherit diff-added))
"Face for additions"
@@ -125,9 +138,16 @@ text on the first line, and the width of the buffer."
"Face for changes"
:group 'vdiff)
+(defface vdiff-word-changed-face
+ '((t :inherit highlight))
+ "Face for word changes within a hunk"
+ :group 'vdiff)
+
(defvar vdiff--buffers nil)
(defvar vdiff--temp-files nil)
-(defvar vdiff--process-buffer " *vdiff*")
+(defvar vdiff--word-diff-temp-files nil)
+(defvar vdiff--process-buffer " *vdiff* ")
+(defvar vdiff--word-diff-output-buffer " *vdiff-word* ")
(defvar vdiff--diff-data nil)
(defvar vdiff--diff-code-regexp
"^\\([0-9]+\\),?\\([0-9]+\\)?\\([adc]\\)\\([0-9]+\\),?\\([0-9]+\\)?")
@@ -230,6 +250,8 @@ text on the first line, and the width of the buffer."
(with-current-buffer buf
,@body))))
+;; * Main overlay refresh routine
+
(defun vdiff-refresh ()
"Asynchronously refresh diff information."
(interactive)
@@ -243,9 +265,9 @@ text on the first line, and the width of the buffer."
(proc (get-buffer-process
vdiff--process-buffer)))
(with-current-buffer (car vdiff--buffers)
- (write-region nil nil (car vdiff--temp-files)))
+ (write-region nil nil (car vdiff--temp-files) nil 'quietly))
(with-current-buffer (cadr vdiff--buffers)
- (write-region nil nil (cadr vdiff--temp-files)))
+ (write-region nil nil (cadr vdiff--temp-files) nil 'quietly))
(when proc
(kill-process proc))
(with-current-buffer (get-buffer-create vdiff--process-buffer)
@@ -267,7 +289,7 @@ text on the first line, and the width of the buffer."
(t
(cons beg (or end beg))))))
-(defun vdiff--diff-refresh-1 (_proc event)
+(defun vdiff--diff-refresh-1 (proc event)
"This is the sentinel for `vdiff-refresh'. It does the job of
parsing the diff output and triggering the overlay updates."
(cond ((string= "finished\n" event)
@@ -278,7 +300,7 @@ parsing the diff output and triggering the overlay updates."
((string= "exited abnormally with code 1\n" event)
(setq vdiff--diff-data nil)
(let (res)
- (with-current-buffer vdiff--process-buffer
+ (with-current-buffer (process-buffer proc)
(goto-char (point-min))
(while (re-search-forward vdiff--diff-code-regexp nil t)
(let* ((code (match-string 3))
@@ -306,6 +328,176 @@ parsing the diff output and triggering the overlay
updates."
(interactive)
(vdiff--with-all-buffers (save-buffer)))
+;; * Word diffs
+
+(defun vdiff--overlay-to-words (&optional ovr syntax-code)
+ "Convert OVR to string of \"words\", one per line."
+ (let* ((ovr (or ovr (vdiff--overlay-at-pos)))
+ (word-syn (or syntax-code
+ vdiff-default-refinement-syntax-code))
+ (not-word-syn (concat "^" word-syn))
+ last-word-end buf-syntax ovr-text)
+ (with-current-buffer (overlay-buffer ovr)
+ (setq buf-syntax (syntax-table))
+ (setq ovr-text (buffer-substring-no-properties
+ (overlay-start ovr)
+ (overlay-end ovr))))
+ (with-temp-buffer
+ (set-syntax-table buf-syntax)
+ (insert ovr-text)
+ (goto-char (point-min))
+ (skip-syntax-forward not-word-syn)
+ (delete-region (point-min) (point))
+ (while (not (eobp))
+ (skip-syntax-forward word-syn)
+ (insert "\n")
+ (setq last-word-end (point))
+ (skip-syntax-forward not-word-syn)
+ (delete-region last-word-end (point)))
+ (buffer-string))))
+
+(defun vdiff--diff-words (this-ovr other-ovr &optional syntax-code)
+ "Diff \"words\" between THIS-OVR and OTHER-OVR"
+ (when (and (eq (overlay-get this-ovr 'vdiff-type) 'change)
+ (overlayp other-ovr))
+ (let* ((a-words (vdiff--overlay-to-words this-ovr syntax-code))
+ (b-words (vdiff--overlay-to-words other-ovr syntax-code))
+ (tmp-file-a (car vdiff--word-diff-temp-files))
+ (tmp-file-b (cadr vdiff--word-diff-temp-files))
+ (out-buffer (get-buffer-create
+ vdiff--word-diff-output-buffer))
+ (a-result '())
+ (b-result '()))
+ (write-region a-words nil tmp-file-a nil 'quietly)
+ (write-region b-words nil tmp-file-b nil 'quietly)
+ (with-current-buffer out-buffer (erase-buffer))
+ (when (= 1 (call-process
+ vdiff-diff-program nil out-buffer nil tmp-file-a tmp-file-b))
+ (with-current-buffer out-buffer
+ (goto-char (point-min))
+ (while (re-search-forward vdiff--diff-code-regexp nil t)
+ (let ((a-change (list (string-to-int (match-string 1))))
+ (b-change (list (string-to-int (match-string 4)))))
+ (forward-line 1)
+ (while (and (not (eobp))
+ (not (looking-at-p vdiff--diff-code-regexp)))
+ (cond ((looking-at-p "^<")
+ (push (buffer-substring-no-properties
+ (+ 2 (point)) (line-end-position))
+ a-change))
+ ((looking-at-p "^>")
+ (push (buffer-substring-no-properties
+ (+ 2 (point)) (line-end-position))
+ b-change)))
+ (forward-line 1))
+ (when (cdr a-change)
+ (push (nreverse a-change) a-result))
+ (when (cdr b-change)
+ (push (nreverse b-change) b-result))))
+ (cons (nreverse a-result) (nreverse b-result)))))))
+
+(defun vdiff-refine-this-change (&optional syntax-code ovr)
+ "Highlight word differences in current change/hunk.
+
+This uses `vdiff-default-refinement-syntax-code' for the
+definition of a \"word\", unless one is provided using
+SYNTAX-CODE."
+ (interactive (list vdiff-default-refinement-syntax-code
+ (vdiff--overlay-at-pos)))
+ (let* ((ovr (or ovr (vdiff--overlay-at-pos)))
+ (other-ovr (when (overlayp ovr)
+ (overlay-get ovr 'vdiff-other-overlay)))
+ (word-syn (or syntax-code
+ vdiff-default-refinement-syntax-code))
+ (not-word-syn (concat "^" word-syn))
+ instructions ovr-ins)
+ (when (and ovr
+ other-ovr
+ (consp (setq instructions
+ (vdiff--diff-words ovr other-ovr))))
+ (dolist (curr-ovr (list ovr other-ovr))
+ (setq ovr-ins (if (eq curr-ovr ovr)
+ (car instructions)
+ (cdr instructions)))
+ (with-current-buffer (overlay-buffer curr-ovr)
+ (save-excursion
+ (let ((current-word-n 1))
+ (goto-char (overlay-start curr-ovr))
+ (skip-syntax-forward not-word-syn)
+ (dolist (ins ovr-ins)
+ (dotimes (_ (- (car ins) current-word-n))
+ (skip-syntax-forward word-syn)
+ (skip-syntax-forward not-word-syn))
+ (setq current-word-n (car ins))
+ (let* ((words (cdr ins))
+ (word-ovr
+ (make-overlay
+ (point)
+ (progn
+ (dotimes (_ (length words))
+ (skip-syntax-forward not-word-syn)
+ (skip-syntax-forward word-syn))
+ (point)))))
+ (cl-incf current-word-n (length words))
+ (overlay-put word-ovr 'vdiff t)
+ (overlay-put word-ovr 'face 'vdiff-word-changed-face)
+ (overlay-put word-ovr 'vdiff-refinement t)
+ (skip-syntax-forward not-word-syn))))))))))
+
+;; Not working yet
+;; (defun vdiff-refine-this-change-whitespace (ovr)
+;; "Highlight whitespace differences in current change/hunk."
+;; (interactive (list (vdiff--overlay-at-pos)))
+;; (vdiff-refine-this-change "-" ovr))
+
+(defun vdiff-refine-this-change-symbol (ovr)
+ "Highlight symbol differences in current change/hunk."
+ (interactive (list (vdiff--overlay-at-pos)))
+ (vdiff-refine-this-change "w_" ovr))
+
+(defun vdiff-refine-this-change-word (ovr)
+ "Highlight word differences in current change/hunk."
+ (interactive (list (vdiff--overlay-at-pos)))
+ (vdiff-refine-this-change "w" ovr))
+
+(defun vdiff-remove-refinements-in-change (ovr)
+ (interactive (list (vdiff--overlay-at-pos)))
+ (dolist (chg-ovr (list ovr
+ (overlay-get ovr 'vdiff-other-overlay)))
+ (dolist (sub-ovr (overlays-in
+ (overlay-start chg-ovr)
+ (overlay-end chg-ovr)))
+ (when (overlay-get sub-ovr 'vdiff-refinement)
+ (delete-overlay sub-ovr)))))
+
+(defun vdiff-refine-all-changes (&optional syntax-code)
+ "Highlight word differences in all hunks.
+
+This uses `vdiff-default-refinement-syntax-code' for the
+definition of a \"word\", unless one is provided using
+SYNTAX-CODE.
+See `vdiff-default-refinement-syntax-code' to change the definition
+of a \"word\"."
+ (interactive)
+ (dolist (ovr (overlays-in (point-min) (point-max)))
+ (vdiff-refine-this-change syntax-code ovr)))
+
+;; Not working yet
+;; (defun vdiff-refine-all-changes-whitespace ()
+;; "Highlight whitespace differences in all hunks."
+;; (interactive)
+;; (vdiff-refine-all-changes "-"))
+
+(defun vdiff-refine-all-changes-symbol ()
+ "Highlight symbol differences in all hunks."
+ (interactive)
+ (vdiff-refine-all-changes "w_"))
+
+(defun vdiff-refine-all-changes-word ()
+ "Highlight word differences in all hunks."
+ (interactive)
+ (vdiff-refine-all-changes "w"))
+
;; * Add overlays
(defun vdiff--make-subtraction-string (n-lines)
@@ -985,6 +1177,8 @@ asked to select two buffers."
(define-key map "C" 'vdiff-close-all-folds)
(define-key map "t" 'vdiff-close-other-folds)
(define-key map "h" 'vdiff-maybe-hydra)
+ (define-key map "f" 'vdiff-refine-this-change)
+ (define-key map "F" 'vdiff-refine-all-changes)
map))
(defvar vdiff-scroll-lock-mode)
@@ -999,6 +1193,9 @@ commands like `vdiff-files' or `vdiff-buffers'."
(setq vdiff--temp-files
(list (make-temp-file "vdiff--temp-a-")
(make-temp-file "vdiff--temp-b-")))
+ (setq vdiff--word-diff-temp-files
+ (list (make-temp-file "vdiff--overlay-diff-temp-a-")
+ (make-temp-file "vdiff--overlay-diff-temp-b-")))
(setq cursor-in-non-selected-windows nil)
(add-hook 'after-save-hook #'vdiff-refresh nil t)
(add-hook 'window-size-change-functions
@@ -1017,6 +1214,7 @@ commands like `vdiff-files' or `vdiff-buffers'."
(setq vdiff--buffers nil)
(setq vdiff--line-map nil)
(setq vdiff--temp-files nil)
+ (setq vdiff--word-diff-temp-files nil)
(when (process-live-p vdiff--process-buffer)
(kill-process vdiff--process-buffer))
(when (buffer-live-p vdiff--process-buffer)
@@ -1044,12 +1242,12 @@ enabled automatically if `vdiff-lock-scrolling' is
non-nil."
(defhydra vdiff-hydra (nil nil :hint nil :foreign-keys run)
(concat (propertize
"\
- Navigation^^^^ Transmit^^ Folds^^^^ Other^^^^
"
+ Navigation^^^^ Refine^^ Transmit^^ Folds^^^^ Other^^^^
"
'face 'header-line)
"
- _n_/_N_ next change/fold _s_ send _o_/_O_ open (all) _u_^ ^
update diff
- _p_/_P_ prev change/fold _r_ receive _c_/_C_ close (all) _w_^ ^
save buffers
- _g_^ ^ goto corresp. line ^ ^ _t_^ ^ close other _q_/_Q_
quit hydra/vdiff")
+ _n_/_N_ next chge/fold _f_ this _s_ send _o_/_O_ open (all) _u_^ ^
update diff
+ _p_/_P_ prev chge/fold _F_ all _r_ receive _c_/_C_ close (all) _w_^ ^
save buffers
+ _g_^ ^ switch buffers ^ ^ ^ ^ _t_^ ^ close other _q_/_Q_
quit hydra/vdiff")
("n" vdiff-next-change)
("p" vdiff-previous-change)
("N" vdiff-next-fold)
@@ -1064,6 +1262,8 @@ enabled automatically if `vdiff-lock-scrolling' is
non-nil."
("t" vdiff-close-other-folds)
("u" vdiff-refresh)
("w" vdiff-save-buffers)
+ ("f" vdiff-refine-this-change)
+ ("F" vdiff-refine-all-changes)
("q" nil :exit t)
("Q" vdiff-quit :exit t)))
- [elpa] scratch/add-vdiff c46b76b 111/258: Set window point on scroll, (continued)
- [elpa] scratch/add-vdiff c46b76b 111/258: Set window point on scroll, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff fd8c973 109/258: Remove post-command-hook, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 25a7516 128/258: Only run scroll-function once per command, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 25ec344 134/258: Require diff-mode so that diff-mode faces are available, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 371febc 135/258: Add option to automatically refine hunks, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 9b3ffb0 150/258: Don't distiguish exit code 0 from 1, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff d33845c 167/258: Minor change in cleanup, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff edfae89 176/258: Cleanup vdiff-buffers, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 85a4d4e 087/258: Fix point jumping after sending changes, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff f041c58 102/258: Sync lines after sending changes, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 88ce867 088/258: Initial attempt at refine commands,
Justin Burkett <=
- [elpa] scratch/add-vdiff f3ca6cb 110/258: Tweak vscroll function, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 84380fb 113/258: Delete unused lexical vars, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 40351c6 079/258: Exit hydra on vdiff exit, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 4bb84e4 073/258: Add update command to hydra, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 81478be 117/258: Lock diff data for certain operations, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 20bd4b4 092/258: Change terminology, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 3d8e224 127/258: Simplify insertion arrow code, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff bd80900 126/258: Merge pull request #7 from syohex/fix-package, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 1102da8 129/258: Avoid subtraction overlays larger than window-height, Justin Burkett, 2017/05/17
- [elpa] scratch/add-vdiff 7135738 132/258: Version 0.1, Justin Burkett, 2017/05/17