From 8a563d9762670e9eec9420ba2dc12075c1dd0a8c Mon Sep 17 00:00:00 2001 From: Stephen Berman Date: Sun, 29 Jul 2018 01:14:41 +0200 Subject: [PATCH] Fix bugs in wdired.el involving dired-filename property After every change in wdired-mode, put the dired-filename text property on the file name. This ensures that changing some but not all characters in the name succeeds with non-nil wdired-use-interactive-rename (bug#32173) and it also ensures that changed names can be found (e.g. by dired-isearch-filenames) while still in wdired-mode. * lisp/wdired.el (wdired--restore-dired-filename-prop): New function. (wdired-change-to-wdired-mode): Add it to after-change-functions. (wdired-change-to-dired-mode): Remove it from after-change-functions. (wdired-finish-edit): Move invocation of wdired-change-to-dired-mode below invocation of wdired-do-renames, so that the latter runs wdired--restore-dired-filename-prop, but above the invocation of revert-buffer to avoid using wdired-revert, which changes back to wdired-mode. (wdired-search-and-rename): Wrap renaming in unwind-protect and if user types C-g when prompted to change the file name, make sure we return to dired-mode. --- lisp/wdired.el | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/lisp/wdired.el b/lisp/wdired.el index bb60e777769..1d0106775d6 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -255,6 +255,7 @@ See `wdired-mode'." (setq buffer-read-only nil) (dired-unadvertise default-directory) (add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t) + (add-hook 'after-change-functions 'wdired--restore-dired-filename-prop nil t) (setq major-mode 'wdired-mode) (setq mode-name "Editable Dired") (setq revert-buffer-function 'wdired-revert) @@ -363,6 +364,7 @@ non-nil means return old filename." (setq mode-name "Dired") (dired-advertise) (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t) + (remove-hook 'after-change-functions 'wdired--restore-dired-filename-prop t) (set (make-local-variable 'revert-buffer-function) 'dired-revert)) @@ -381,7 +383,6 @@ non-nil means return old filename." (defun wdired-finish-edit () "Actually rename files based on your editing in the Dired buffer." (interactive) - (wdired-change-to-dired-mode) (let ((changes nil) (errors 0) files-deleted @@ -423,6 +424,11 @@ non-nil means return old filename." (forward-line -1))) (when files-renamed (setq errors (+ errors (wdired-do-renames files-renamed)))) + ;; We have to be in wdired-mode when wdired-do-renames is executed + ;; so that wdired--restore-dired-filename-prop runs, but we have + ;; to change back to dired-mode before reverting the buffer to + ;; avoid using wdired-revert, which changes back to wdired-mode. + (wdired-change-to-dired-mode) (if changes (progn ;; If we are displaying a single file (rather than the @@ -543,19 +549,25 @@ and proceed depending on the answer." (goto-char (point-max)) (forward-line -1) (let ((done nil) + (failed t) curr-filename) (while (and (not done) (not (bobp))) (setq curr-filename (wdired-get-filename nil t)) (if (equal curr-filename filename-ori) - (progn - (setq done t) - (let ((inhibit-read-only t)) - (dired-move-to-filename) - (search-forward (wdired-get-filename t) nil t) - (replace-match (file-name-nondirectory filename-ori) t t)) - (dired-do-create-files-regexp - (function dired-rename-file) - "Move" 1 ".*" filename-new nil t)) + (unwind-protect + (progn + (setq done t) + (let ((inhibit-read-only t)) + (dired-move-to-filename) + (search-forward (wdired-get-filename t) nil t) + (replace-match (file-name-nondirectory filename-ori) t t)) + (dired-do-create-files-regexp + (function dired-rename-file) + "Move" 1 ".*" filename-new nil t) + (setq failed nil)) + ;; If user types C-g when prompted to change the file + ;; name, make sure we return to dired-mode. + (when failed (wdired-change-to-dired-mode))) (forward-line -1)))))) ;; marks a list of files for deletion @@ -586,6 +598,22 @@ Optional arguments are ignored." (not (y-or-n-p "Buffer changed. Discard changes and kill buffer? "))) (error "Error"))) +;; Added to after-change-functions in wdired-change-to-wdired-mode to +;; ensure that, on editing a file name, new characters get the +;; dired-filename text property, which allows functions that look for +;; this property (e.g. dired-isearch-filenames) to work in wdired-mode +;; and also avoids an error with non-nil wdired-use-interactive-rename +;; (bug#32173). +(defun wdired--restore-dired-filename-prop (beg end _len) + (save-match-data + (save-excursion + (beginning-of-line) + (when (re-search-forward directory-listing-before-filename-regexp + (line-end-position) t) + (setq beg (point) + end (line-end-position)) + (put-text-property beg end 'dired-filename t))))) + (defun wdired-next-line (arg) "Move down lines then position at filename or the current column. See `wdired-use-dired-vertical-movement'. Optional prefix ARG -- 2.39.2