]> code.delx.au - gnu-emacs-elpa/blobdiff - dired-async.el
Unquote all callbacks.
[gnu-emacs-elpa] / dired-async.el
index e1b9729268420b6afa159c00997b256a2c54a769..2da733abcd1924cb2d98e4600286bab777197032 100644 (file)
@@ -1,7 +1,6 @@
-;;; dired-async.el --- Copy/move/delete asynchronously in dired.
+;;; dired-async.el --- Asynchronous dired actions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012~2014 John Wiegley
-;; Copyright (C) 2012~2014 Thierry Volpiatto
+;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
 
 ;; Authors: John Wiegley <jwiegley@gmail.com>
 ;;          Thierry Volpiatto <thierry.volpiatto@gmail.com>
 ;;; Commentary:
 
 ;; This file provide a redefinition of `dired-create-file' function,
-;; which must be loaded *after* dired-aux.el, performs copies,
-;; moves and all what is handled by `dired-create-file' in the background
-;; using a slave Emacs process, by means of the async.el module.
+;; performs copies, moves and all what is handled by `dired-create-file'
+;; in the background using a slave Emacs process,
+;; by means of the async.el module.
 ;; To use it, put this in your .emacs:
-;;
-;;   (eval-after-load "dired-aux"
-;;     '(require 'dired-async))
-;;
-;;
+
+;;     (dired-async-mode 1)
+
+;; This will enable async copy/rename etc...
+;; in dired and helm.
 
 ;;; Code:
 \f
@@ -68,19 +67,13 @@ Should take same args as `message'."
   :group 'dired-async
   :type 'string)
 
-(defcustom dired-async-be-async t
-  "When non--nil make `dired-create-file' async.
-This allow to turn off async features provided to this package."
-  :group 'dired-async
-  :type  'boolean)
-
 (defface dired-async-message
     '((t (:foreground "yellow")))
   "Face used for mode-line message."
   :group 'dired-async)
 
 (defface dired-async-mode-message
-    '((t (:background "Firebrick1")))
+    '((t (:foreground "Gold")))
   "Face used for `dired-async--modeline-mode' lighter."
   :group 'dired-async)
 
@@ -117,7 +110,7 @@ This allow to turn off async features provided to this package."
   (interactive)
   (let* ((processes (dired-async-processes))
          (proc (car (last processes))))
-    (delete-process proc)
+    (and proc (delete-process proc))
     (unless (> (length processes) 1)
       (dired-async--modeline-mode -1))))
 
@@ -151,18 +144,17 @@ This allow to turn off async features provided to this package."
                                        (buffer-name b)) b))))
        (when buf (kill-buffer buf))))))
 
+(defvar overwrite-query)
 (defun dired-async-create-files (file-creator operation fn-list name-constructor
-                                 &optional marker-char)
+                                 &optional _marker-char)
   "Same as `dired-create-files' but asynchronous.
 
 See `dired-create-files' for the behavior of arguments."
   (setq dired-async-operation nil)
-  (let (dired-create-files-failures failures async-fn-list
-                                    skipped (success-count 0) (total (length fn-list))
-                                    (callback `(lambda (&optional ignore)
-                                                 (dired-async-after-file-create ,(length fn-list)))))
-    (let (to overwrite-query
-             overwrite-backup-query)    ; for dired-handle-overwrite
+  (setq overwrite-query nil)
+  (let ((total (length fn-list))
+        failures async-fn-list skipped callback)
+    (let (to)
       (dolist (from fn-list)
         (setq to (funcall name-constructor from))
         (if (equal to from)
@@ -172,7 +164,8 @@ See `dired-create-files' for the behavior of arguments."
                          (downcase operation) from)))
         (if (not to)
             (setq skipped (cons (dired-make-relative from) skipped))
-            (let* ((overwrite (file-exists-p to))
+            (let* ((overwrite (and (null (eq file-creator 'backup-file))
+                                   (file-exists-p to)))
                    (dired-overwrite-confirmed ; for dired-handle-overwrite
                     (and overwrite
                          (let ((help-form '(format "\
@@ -180,14 +173,7 @@ Type SPC or `y' to overwrite file `%s',
 DEL or `n' to skip to next,
 ESC or `q' to not overwrite any of the remaining files,
 `!' to overwrite all remaining files with no more questions." to)))
-                           (dired-query 'overwrite-query
-                                        "Overwrite `%s'?" to))))
-                   ;; must determine if FROM is marked before file-creator
-                   ;; gets a chance to delete it (in case of a move).
-                   (actual-marker-char
-                    (cond  ((integerp marker-char) marker-char)
-                           (marker-char (dired-file-marker from)) ; slow
-                           (t nil))))
+                           (dired-query 'overwrite-query "Overwrite `%s'?" to)))))
               ;; Handle the `dired-copy-file' file-creator specially
               ;; When copying a directory to another directory or
               ;; possibly to itself or one of its subdirectories.
@@ -221,40 +207,63 @@ ESC or `q' to not overwrite any of the remaining files,
                         (push (dired-make-relative from) failures)
                         (dired-log "%s `%s' to `%s' failed"
                                    operation from to)))
-                  (push (cons from to) async-fn-list))))))
+                  (push (cons from to) async-fn-list)))))
+      (setq callback
+            (lambda (&optional _ignore)
+               (dired-async-after-file-create total)
+               (when (string= (downcase operation) "rename")
+                 (cl-loop for (file . to) in async-fn-list
+                          for bf = (get-file-buffer file)
+                          do (and bf (with-current-buffer bf
+                                       (set-visited-file-name to nil t))))))))
     ;; Handle error happening in host emacs.
-    (cond
-      (dired-create-files-failures
-       (setq failures (nconc failures dired-create-files-failures))
-       (dired-log-summary
-        (format "%s failed for %d file%s in %d requests"
-                operation (length failures)
-                (dired-plural-s (length failures))
-                total)
-        failures))
-      (failures
-       (dired-log-summary
-        (format "%s failed for %d of %d file%s"
-                operation (length failures)
-                total (dired-plural-s total))
-        failures))
-      (skipped
-       (dired-log-summary
-        (format "%s: %d of %d file%s skipped"
-                operation (length skipped) total
-                (dired-plural-s total))
-        skipped))
-      (t (message "%s: %s file%s"
-                  operation success-count (dired-plural-s success-count))))
+    (cond (failures
+           (dired-log-summary
+            (format "%s failed for %d of %d file%s"
+                    operation (length failures)
+                    total (dired-plural-s total))
+            failures))
+          (skipped
+           (dired-log-summary
+            (format "%s: %d of %d file%s skipped"
+                    operation (length skipped) total
+                    (dired-plural-s total))
+            skipped)))
     ;; Start async process.
     (when async-fn-list
       (async-start `(lambda ()
                       (require 'cl-lib) (require 'dired-aux) (require 'dired-x)
                       ,(async-inject-variables dired-async-env-variables-regexp)
                       (condition-case err
-                          (let ((dired-recursive-copies (quote always)))
-                            (cl-loop for (f . d) in (quote ,async-fn-list)
-                                     do (funcall (quote ,file-creator) f d t)))
+                          (let ((dired-recursive-copies (quote always))
+                                (dired-copy-preserve-time
+                                 ,dired-copy-preserve-time))
+                            (setq overwrite-backup-query nil)
+                            ;; Inline `backup-file' as long as it is not
+                            ;; available in emacs.
+                            (defalias 'backup-file
+                                ;; Same feature as "cp --backup=numbered from to"
+                                ;; Symlinks are copied as file from source unlike
+                                ;; `dired-copy-file' which is same as cp -d.
+                                ;; Directories are omitted.
+                                (lambda (from to ok)
+                                  (cond ((file-directory-p from) (ignore))
+                                        (t (let ((count 0))
+                                             (while (let ((attrs (file-attributes to)))
+                                                      (and attrs (null (nth 0 attrs))))
+                                               (cl-incf count)
+                                               (setq to (concat (file-name-sans-versions to)
+                                                                (format ".~%s~" count)))))
+                                           (condition-case err
+                                               (copy-file from to ok dired-copy-preserve-time)
+                                             (file-date-error
+                                              (push (dired-make-relative from)
+                                                    dired-create-files-failures)
+                                              (dired-log "Can't set date on %s:\n%s\n" from err)))))))
+                            ;; Now run the FILE-CREATOR function on files.
+                            (cl-loop with fn = (quote ,file-creator)
+                                     for (from . dest) in (quote ,async-fn-list)
+                                     do (funcall fn from dest t)))
                         (file-error
                          (with-temp-file ,dired-async-log-file
                            (insert (format "%S" err)))))
@@ -265,14 +274,22 @@ ESC or `q' to not overwrite any of the remaining files,
       (setq dired-async-operation (list operation (length async-fn-list)))
       (message "%s proceeding asynchronously..." operation))))
 
+(defadvice dired-create-files (around dired-async)
+  (dired-async-create-files file-creator operation fn-list
+                            name-constructor marker-char))
+
 ;;;###autoload
 (define-minor-mode dired-async-mode
     "Do dired actions asynchronously."
-  :group 'helm
+  :group 'dired-async
   :global t
   (if dired-async-mode
-      (advice-add 'dired-create-files :override #'dired-async-create-files)
-      (advice-remove 'dired-create-files #'dired-async-create-files)))
+      (if (fboundp 'advice-add)
+          (advice-add 'dired-create-files :override #'dired-async-create-files)
+          (ad-activate 'dired-create-files))
+      (if (fboundp 'advice-remove)
+          (advice-remove 'dired-create-files #'dired-async-create-files)
+          (ad-deactivate 'dired-create-files))))
 
 
 (provide 'dired-async)