Package: emacs;
Reported by: Rahul Martim Juliato <rahuljuliato <at> gmail.com>
Date: Wed, 26 Feb 2025 23:15:02 UTC
Severity: normal
Found in version 30.1
View this message in rfc822 format
From: Rahul Martim Juliato <rahuljuliato <at> gmail.com> To: Juri Linkov <juri <at> linkov.net> Cc: Rahul Martim Juliato <rahuljuliato <at> gmail.com>, 76603 <at> debbugs.gnu.org Subject: bug#76603: 30.1; multi-file-replace-regexp-as-diff won't end prompting with icomplete-show-matches-on-no-input Date: Wed, 12 Mar 2025 21:21:46 -0300
Juri Linkov <juri <at> linkov.net> writes: >> If I may add another inquire. > > Sorry, I missed this inquiry. > >> The command dired-do-find-regexp-and-replace, accepts marking files and >> directories before executing it. I initially thought I could do the >> same with dired-do-replace-regexp-as-diff but it only works marking >> files not directories. Thanks for this info. > > dired-do-find-regexp-and-replace uses dired-do-find-regexp > to get marked files. So I guess dired-do-replace-regexp-as-diff > could use dired-do-find-regexp as well? > >> So my first question is: are there any plans (or there is already some way) >> to make dired-do-replace-regexp-as-diff also find all files in a marked >> directory? > > There are no plans. If you could try to use dired-do-find-regexp > in dired-do-replace-regexp-as-diff this would be nice. > Maybe I could send a patch? >> Secondly: Are there any plans to make multi-file-replace-regexp-as-diff >> to work with glob patterns? > > Currently multi-file-replace-regexp-as-diff uses multi-isearch-read-files. > > I vaguely remember there exists such a function that reads a glob pattern, > but can't find it right away. Neither did I :( -- Thanks for taking a look into it Juri! In the meanwhile I created two `wrapper` functions to expand `multi-file-replace-regexp-as-diff' and do why I meant to. Do you think two more functions with extended functionality are worth a patch? I do not intend to replace the original ones, but provide: 1.) `multi-file-replace-regexp-as-diff-with-glob': Use it with glob pattern matching in files, including inside subfolders. 2.) `dired-do-replace-regexp-as-diff-with-directories': Use it with marked files and or directories in dired The code I'm currently using/testing: ```emacs-lisp ;; `M-x multi-file-replace-regexp-as-diff-with-glob RET' ;; ;; A wrapper for `multi-file-replace-regexp-as-diff' that extends its functionality ;; to support glob patterns for file matching. It recursively searches all files ;; in the specified directory (including subdirectories) that match the given glob ;; pattern (e.g., `*.js`), and displays the replacements as diffs in the ;; `*replace-diff*` buffer. This allows for easy review and application of changes ;; across multiple files. (defun glob-to-regexp (glob) "Convert a GLOB pattern (e.g., '*.el') to a regexp that `directory-files-recursively` can use." (concat "^" (replace-regexp-in-string (rx (any "*?.")) (lambda (match) (pcase match ("*" ".*") ("?" ".") ("." "\\\\.") ; Properly escape the dot (_ match))) glob) "$")) (defun multi-file-replace-regexp-as-diff-with-glob (dir regexp to-string &optional delimited glob-pattern) "Wrapper for `multi-file-replace-regexp-as-diff` that accepts a directory and a glob pattern. DIR is the directory to search recursively. REGEXP is the regular expression to replace. TO-STRING is the replacement string. DELIMITED is an optional argument passed to `multi-file-replace-regexp-as-diff`. GLOB-PATTERN is the glob pattern to match files (e.g., \"*.el\")." (interactive (let ((dir (file-truename (read-directory-name "Directory: "))) (common (query-replace-read-args (concat "Replace" (if current-prefix-arg " word" "") " regexp as diff in files") t t)) (glob-pattern (read-string "Glob pattern (e.g., *.el): " "*"))) (list dir (nth 0 common) (nth 1 common) (nth 2 common) glob-pattern))) (let* ((glob-regexp (glob-to-regexp glob-pattern)) (files (directory-files-recursively dir glob-regexp))) (if files (multi-file-replace-regexp-as-diff files regexp to-string delimited) (message "No files found for glob-pattern: %s" glob-pattern)))) ;; `M-x dired RET' mark files and/or directories then ;; `M-x dired-do-replace-regexp-as-diff-with-directories RET' ;; ;; A version of `dired-do-replace-regexp-as-diff' that adds support for selected ;; directories in Dired. When directories are marked, it recursively includes all ;; files within them (and their subdirectories) in the replacement operation. ;; The replacements are displayed as diffs in the `*replace-diff*` buffer, allowing ;; for review and application of changes across multiple files and directories. (defun expand-directories (items) "Expand ITEMS to include all files within directories (recursively). Directories themselves are excluded from the final list." (cl-loop for item in items if (file-directory-p item) append (let ((files (directory-files-recursively item ".*" t))) (cl-remove-if #'file-directory-p files)) else if (file-regular-p item) ; Ensure only regular files are included collect item)) (defun dired-do-replace-regexp-as-diff-with-directories (from to &optional delimited) "Do `replace-regexp' of FROM with TO as diff, on all marked files and directories. If a marked item is a directory, all files within it (recursively) are included. Third arg DELIMITED (prefix arg) means replace only word-delimited matches. The replacements are displayed in the buffer *replace-diff* that you can later apply as a patch after reviewing the changes." (interactive (let ((common (query-replace-read-args "Replace regexp as diff in marked files and directories" t t t))) (list (nth 0 common) (nth 1 common) (nth 2 common)))) (dired-post-do-command) (let* ((marked-items (dired-get-marked-files)) ; Include directories in the list (files (expand-directories marked-items))) (if files (progn (multi-file-replace-regexp-as-diff files from to delimited)) (message "No files found in marked items.")))) ``` -- Rahul Martim Juliato
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.