Enhance diff-mode with Ivy
My current job requires me to review the freelancer's patches and apply them to our code branch under Perforce control. Due to my client's security policy, the freelancer can only work on isolated sandbox environment and can't access our code base directly.
I need two steps to finish the task:
- Open the freelancer's patch in
diff-apply-hunkto apply the hunks interactively
The problem is
diff-mode always ask me to specify the file to be patched.
I read the code of
diff-apply-hunk. The logic of
diff-apply-hunk is simple. It tries different algorithms to guess the right file to patch. When the algorithms fail, it calls API
read-file-name to ask me to provide the file path manually. If right file is found, the algorithms will work again and
read-file-name will never be used for other hunks.
Here is my solution. I can find the file to patch in recent opened files because I store all of them by
(setq recentf-max-saved-items 2048). I plan to use
ivy-read from Ivy to locate the file at first. If this step fails , I can still fall back on original API
Here is the code
(defvar ffip-read-file-name-hijacked-p nil) (defun ffip-diff-apply-hunk (&optional reverse) (interactive "P") (unless recentf-mode (recentf-mode 1)) (setq ffip-read-file-name-hijacked-p t) (defadvice read-file-name (around ffip-read-file-name-hack activate) (cond (ffip-read-file-name-hijacked-p (let* ((args (ad-get-args 0)) (file-name (file-name-nondirectory (nth 2 args))) (cands (remove nil (mapcar (lambda (s) (if (string-match-p (format "%s$" file-name) s) s)) (mapcar #'substring-no-properties recentf-list)))) (rlt (ivy-read "Recentf: " cands))) (if rlt (setq ad-return-value rlt) rlt ad-doit))) (t ad-do-it))) (diff-apply-hunk reverse) (setq ffip-read-file-name-hijacked-p nil))
ffip-diff-apply-hunk can replace
BTW, I can edit the patch on the spot when applying hunks. Similar to the work flow of
git add --patch.
The solution is added into https://github.com/technomancy/find-file-in-project.