From c1127a5bde1779a98749bd63b8d6df345d7e7d6b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 27 Apr 2020 01:42:31 -0400 Subject: [PATCH] Rewrite move/copy/delete file commands To use rename-file, copy-file and delete-file, so these commands can enjoy the benefits of any plugins that have advised these, like org-roam does for rename-file. --- core/autoload/files.el | 169 +++++++++++--------------- modules/editor/evil/autoload/files.el | 4 +- 2 files changed, 71 insertions(+), 102 deletions(-) diff --git a/core/autoload/files.el b/core/autoload/files.el index 65d0a6639..b62925d43 100644 --- a/core/autoload/files.el +++ b/core/autoload/files.el @@ -203,52 +203,29 @@ single file or nested compound statement of `and' and `or' statements." ;; ;;; Helpers -(defun doom--forget-file (path) - "Ensure `recentf', `projectile' and `save-place' forget OLD-PATH." - (when (bound-and-true-p recentf-mode) - (recentf-remove-if-non-kept path)) - (when (and (bound-and-true-p projectile-mode) - (doom-project-p) - (projectile-file-cached-p path (doom-project-root))) - (projectile-purge-file-from-cache path)) - (when (bound-and-true-p save-place-mode) - (save-place-forget-unreadable-files))) - -(defun doom--update-file (path) - (when (featurep 'vc) - (vc-file-clearprops path) - (vc-resynch-buffer path nil t)) - (when (featurep 'magit) - (when-let (default-directory (magit-toplevel (file-name-directory path))) - (magit-refresh)))) - -(defun doom--copy-file (old-path new-path &optional force-p) - (let* ((new-path (expand-file-name new-path)) - (old-path (file-truename old-path)) - (new-path (apply #'expand-file-name - (if (or (directory-name-p new-path) - (file-directory-p new-path)) - (list (file-name-nondirectory old-path) new-path) - (list new-path)))) - (new-path-dir (file-name-directory new-path)) - (project-root (doom-project-root)) - (short-new-name (if (and project-root (file-in-directory-p new-path project-root)) - (file-relative-name new-path project-root) - (abbreviate-file-name new-path)))) - (unless (file-directory-p new-path-dir) - (make-directory new-path-dir t)) - (when (buffer-modified-p) - (save-buffer)) - (cond ((file-equal-p old-path new-path) - (throw 'status 'overwrite-self)) - ((and (file-exists-p new-path) - (not force-p) - (not (y-or-n-p (format "File already exists at %s, overwrite?" short-new-name)))) - (throw 'status 'aborted)) - ((file-exists-p old-path) - (copy-file old-path new-path t) - short-new-name) - (short-new-name)))) +(defun doom--update-files (&rest files) + "Ensure FILES are updated in `recentf', `magit' and `save-place'." + (let (toplevels) + (dolist (file files) + (when (featurep 'vc) + (vc-file-clearprops file) + (when-let (buffer (get-file-buffer file)) + (with-current-buffer buffer + (vc-refresh-state)))) + (when (featurep 'magit) + (when-let (default-directory (magit-toplevel (file-name-directory file))) + (cl-pushnew default-directory toplevels))) + (unless (file-readable-p file) + (when (bound-and-true-p recentf-mode) + (recentf-remove-if-non-kept file)) + (when (and (bound-and-true-p projectile-mode) + (doom-project-p) + (projectile-file-cached-p file (doom-project-root))) + (projectile-purge-file-from-cache file)))) + (dolist (default-directory toplevels) + (magit-refresh)) + (when (bound-and-true-p save-place-mode) + (save-place-forget-unreadable-files)))) ;; @@ -256,73 +233,67 @@ single file or nested compound statement of `and' and `or' statements." ;;;###autoload (defun doom/delete-this-file (&optional path force-p) - "Delete FILENAME (defaults to the file associated with current buffer) and -kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)." + "Delete PATH, kill its buffers and expunge it from vc/magit cache. + +If PATH is not specified, default to the current buffer's file. + +If FORCE-P, delete without confirmation." (interactive - (list (file-truename (buffer-file-name)) + (list (buffer-file-name (buffer-base-buffer)) current-prefix-arg)) - (let* ((fbase (file-name-sans-extension (file-name-nondirectory path))) - (buf (current-buffer))) - (cond ((not (file-exists-p path)) - (error "File doesn't exist: %s" path)) - ((not (or force-p (y-or-n-p (format "Really delete %s?" fbase)))) - (message "Aborted") - nil) - ((unwind-protect - (progn (delete-file path) t) - (let ((short-path (file-relative-name path (doom-project-root)))) - (if (file-exists-p path) - (error "Failed to delete %s" short-path) - ;; Ensures that windows displaying this buffer will be switched - ;; to real buffers (`doom-real-buffer-p') - (doom/kill-this-buffer-in-all-windows buf t) - (doom--forget-file path) - (doom--update-file path) - (message "Successfully deleted %s" short-path)))))))) + (let* ((path (or path (buffer-file-name (buffer-base-buffer)))) + (short-path (abbreviate-file-name path))) + (unless (and path (file-exists-p path)) + (user-error "Buffer is not visiting any file")) + (unless (file-exists-p path) + (error "File doesn't exist: %s" path)) + (unless (or force-p (y-or-n-p (format "Really delete %S?" short-path))) + (user-error "Aborted")) + (let ((buf (current-buffer))) + (unwind-protect + (progn (delete-file path) t) + (if (file-exists-p path) + (error "Failed to delete %S" short-path) + ;; Ensures that windows displaying this buffer will be switched to + ;; real buffers (`doom-real-buffer-p') + (doom/kill-this-buffer-in-all-windows buf t) + (doom--update-files path) + (message "Deleted %S" short-path)))))) ;;;###autoload (defun doom/copy-this-file (new-path &optional force-p) - "Copy current buffer's file to NEW-PATH. If FORCE-P, overwrite the destination -file if it exists, without confirmation." + "Copy current buffer's file to NEW-PATH. + +If FORCE-P, overwrite the destination file if it exists, without confirmation." (interactive (list (read-file-name "Copy file to: ") current-prefix-arg)) - (pcase (catch 'status - (when-let (dest (doom--copy-file (buffer-file-name) new-path force-p)) - (doom--update-file new-path) - (message "File successfully copied to %s" dest))) - (`overwrite-self (error "Cannot overwrite self")) - (`aborted (message "Aborted")) - (_ t))) + (unless (and buffer-file-name (file-exists-p buffer-file-name)) + (user-error "Buffer is not visiting any file")) + (let ((old-path (buffer-file-name (buffer-base-buffer))) + (new-path (expand-file-name new-path))) + (make-directory (file-name-directory new-path) 't) + (copy-file old-path new-path (or force-p 1)) + (doom--update-files old-path new-path) + (message "File copied to %S" (abbreviate-file-name new-path)))) ;;;###autoload (defun doom/move-this-file (new-path &optional force-p) - "Move current buffer's file to NEW-PATH. If FORCE-P, overwrite the destination -file if it exists, without confirmation." + "Move current buffer's file to NEW-PATH. + +If FORCE-P, overwrite the destination file if it exists, without confirmation." (interactive (list (read-file-name "Move file to: ") current-prefix-arg)) - (pcase (catch 'status - (let ((old-path (buffer-file-name)) - (new-path (expand-file-name new-path))) - (when-let (dest (doom--copy-file old-path new-path force-p)) - (doom--forget-file old-path) - (when (file-exists-p old-path) - (delete-file old-path)) - (mapc #'doom--update-file - (delq - nil (list (if (ignore-errors - (file-equal-p (doom-project-root old-path) - (doom-project-root new-path))) - nil - old-path) - new-path))) - (kill-current-buffer) - (find-file new-path) - (message "File successfully moved to %s" dest)))) - (`overwrite-self (error "Cannot overwrite self")) - (`aborted (message "Aborted")) - (_ t))) + (unless (and buffer-file-name (file-exists-p buffer-file-name)) + (user-error "Buffer is not visiting any file")) + (let ((old-path (buffer-file-name (buffer-base-buffer))) + (new-path (expand-file-name new-path))) + (make-directory (file-name-directory new-path) 't) + (rename-file old-path new-path (or force-p 1)) + (set-visited-file-name new-path t t) + (doom--update-files old-path new-path) + (message "File moved to %S" (abbreviate-file-name new-path)))) (defun doom--sudo-file-path (file) (let ((host (or (file-remote-p file 'host) "localhost"))) diff --git a/modules/editor/evil/autoload/files.el b/modules/editor/evil/autoload/files.el index ac3daed1b..93de22915 100644 --- a/modules/editor/evil/autoload/files.el +++ b/modules/editor/evil/autoload/files.el @@ -6,8 +6,7 @@ kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)." :repeat nil (interactive "") - (doom/delete-this-file (or filename (file-truename buffer-file-name)) - force-p)) + (doom/delete-this-file filename force-p)) ;;;###autoload (autoload '+evil:move-this-file "editor/evil/autoload/files" nil t) (evil-define-command +evil:move-this-file (new-path &optional force-p) @@ -30,4 +29,3 @@ overwrite the destination file if it exists, without confirmation." (when (or (not new-path) (string-empty-p new-path)) (user-error "No new path was specified")) (doom/copy-this-file new-path force-p)) -