branch: elpa/helm
commit f32ac746d54b9e9f29d653a8594280f6d2eea4af
Author: Thierry Volpiatto <thie...@posteo.net>
Commit: Thierry Volpiatto <thie...@posteo.net>

    Add restore backup files action to hff
---
 helm-files.el | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/helm-files.el b/helm-files.el
index 99a0d28b36..89825d6db6 100644
--- a/helm-files.el
+++ b/helm-files.el
@@ -4450,6 +4450,64 @@ Arg FILE is the real part of candidate, a filename with 
no props."
       (message "No suitable Icons package found")))
   (clrhash helm-ff--list-directory-cache))
 
+;;; Action transformer
+;;
+(defun helm-ff--in-backup-directory ()
+  (when backup-directory-alist
+    (cl-loop for (_p . f) in backup-directory-alist
+             thereis (file-equal-p f helm-ff-default-directory))))
+
+(defun helm-ff-restore-backups (_candidate)
+  (let ((mkd (helm-marked-candidates))
+        (copied 0)
+        ovw)
+    (cl-dolist (file mkd)
+      (let (dest)
+        (when (string-match "\\(?:\\`\\([!]\\)[^!]*\\1.*\\)\\|\\(?:~\\'\\)"
+                            (helm-basename file))
+          (setq dest (helm-aand (replace-regexp-in-string
+                                 "\\.~[[:digit:]]*~?"
+                                 "" (helm-basename file))
+                                (helm-ff--normalize-backup-name it)
+                                (if (string-match "\\`/" it)
+                                    it
+                                  ;; If basename doesn't contain now
+                                  ;; "/", that's mean it was a backup file
+                                  ;; stored in current directory, just
+                                  ;; expand it to this directory.
+                                  (expand-file-name it 
helm-ff-default-directory))))
+          (if (and (file-exists-p dest) (null ovw))
+              (helm-acase (helm-read-answer
+                           (format "Overwrite `%s' (answer [y,n,!,q])? " dest)
+                           '("y" "n" "!" "q"))
+                ("y" (cl-incf copied) (copy-file file dest t t t t))
+                ("n" (ignore))
+                ("!" (setq ovw t) (cl-incf copied) (copy-file file dest t t t 
t))
+                ("q" (setq copied nil) (cl-return (message "Abort restoring 
files"))))
+            (cl-incf copied)
+            (copy-file file dest t t t t)))))
+    (when (numberp copied)
+      (message "(%s/%s) files copied" copied (length mkd)))))
+
+(defun helm-ff--normalize-backup-name (fname)
+  "Normalize backup FNAME to its original name."
+  ;; When Emacs build a backup filename for the backup directory it
+  ;; replace "/" by "!" in the basedir of file and double the "!" in
+  ;; the basename, this is done by `make-backup-file-name-1'.  We want
+  ;; to replace only the "!" in the basedir part of FNAME.
+  (with-temp-buffer
+    (insert fname)
+    (goto-char (point-min))
+    (save-excursion
+      (when (looking-at "!") (replace-match "/"))
+      (while (re-search-forward "[^!]\\([!]\\)[^!]" nil t)
+        (replace-match "/" nil nil nil 1)))
+    (let ((count 0) rep)
+      (while (re-search-forward "!" nil t)
+        (cl-incf count))
+      (setq rep (make-string (/ count 2) ?!))
+      (replace-regexp-in-string "[!]+" rep (buffer-string)))))
+
 (defun helm-find-files-action-transformer (actions candidate)
   "Action transformer for `helm-source-find-files'."
   (let ((str-at-point (with-helm-current-buffer
@@ -4496,6 +4554,12 @@ Arg FILE is the real part of candidate, a filename with 
no props."
                 (file-exists-p candidate))
            (helm-append-at-nth
             actions '(("Browse url file" . browse-url-of-file)) 2))
+          ((and (helm-ff--in-backup-directory)
+                (cl-loop for file in (helm-marked-candidates)
+                         always (string-match 
"\\(?:\\`\\([!]\\)[^!]*\\1.*\\)\\|\\(?:~\\'\\)"
+                                              (helm-basename file))))
+           (helm-append-at-nth
+            actions '(("Restore backup file(s)" . helm-ff-restore-backups)) 1))
           (t actions))))
 
 ;;; Trashing files

Reply via email to