diff lisp/efs/dired-rgxp.el @ 98:0d2f883870bc r20-1b1

Import from CVS: tag r20-1b1
author cvs
date Mon, 13 Aug 2007 09:13:56 +0200
parents 8fc7fe29b841
children 7e54bd776075 9f59509498e1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/efs/dired-rgxp.el	Mon Aug 13 09:13:56 2007 +0200
@@ -0,0 +1,267 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; File:           dired-rgxp.el
+;; Dired Version: $Revision: 1.1 $
+;; RCS:
+;; Description:   Commands for running commands on files whose names
+;;                match a regular expression.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Requirements and provisions
+(provide 'dired-rgxp)
+(require 'dired)
+
+;;; Variables
+
+(defvar dired-flagging-regexp nil)
+;; Last regexp used to flag files.
+
+;;; Utility functions
+
+(defun dired-do-create-files-regexp
+  (file-creator operation arg regexp newname &optional whole-path marker-char)
+  ;; Create a new file for each marked file using regexps.
+  ;; FILE-CREATOR and OPERATION as in dired-create-files.
+  ;; ARG as in dired-get-marked-files.
+  ;; Matches each marked file against REGEXP and constructs the new
+  ;;   filename from NEWNAME (like in function replace-match).
+  ;; Optional arg WHOLE-PATH means match/replace the whole pathname
+  ;;   instead of only the non-directory part of the file.
+  ;; Optional arg MARKER-CHAR as in dired-create-files.
+  (let* ((fn-list (dired-get-marked-files nil arg))
+	 (name-constructor
+	  (if whole-path
+	      (list 'lambda '(from)
+		    (list 'let
+			  (list (list 'to
+				      (list 'dired-string-replace-match
+					    regexp 'from newname)))
+			  (list 'or 'to
+				(list 'dired-log
+				      '(buffer-name (current-buffer))
+				      "%s: %s did not match regexp %s\n"
+				      operation 'from regexp))
+			  'to))
+	    (list 'lambda '(from)
+		  (list 'let
+			(list (list 'to
+				    (list 'dired-string-replace-match regexp
+					  '(file-name-nondirectory from)
+					  newname)))
+			(list 'or 'to
+			      (list 'dired-log '(buffer-name (current-buffer))
+				    "%s: %s did not match regexp %s\n"
+				    operation '(file-name-nondirectory from)
+				    regexp))
+			'(and to
+			      (expand-file-name
+			       to (file-name-directory from)))))))
+	 (operation-prompt (concat operation " `%s' to `%s'?"))
+	 (rename-regexp-help-form (format "\
+Type SPC or `y' to %s one match, DEL or `n' to skip to next,
+`!' to %s all remaining matches with no more questions."
+					  (downcase operation)
+					  (downcase operation)))
+	 (query (list 'lambda '(from to)
+		      (list 'let
+			    (list (list 'help-form
+					rename-regexp-help-form))
+			    (list 'dired-query
+				  '(quote dired-file-creator-query)
+				  operation-prompt
+				  '(dired-abbreviate-file-name from)
+				  '(dired-abbreviate-file-name to))))))
+    (dired-create-files
+     file-creator operation fn-list name-constructor marker-char query)))
+
+(defun dired-mark-read-regexp (operation)
+  ;; Prompt user about performing OPERATION.
+  ;; Read and return list of: regexp newname arg whole-path.
+  (let* ((whole-path
+	  (equal 0 (prefix-numeric-value current-prefix-arg)))
+	 (arg
+	  (if whole-path nil current-prefix-arg))
+	 (regexp
+	  (dired-read-with-history
+	   (concat (if whole-path "Path " "") operation " from (regexp): ")
+	   dired-flagging-regexp 'dired-regexp-history))
+	 (newname
+	  (read-string
+	   (concat (if whole-path "Path " "") operation " " regexp " to: ")
+	   (and (not whole-path) (dired-dwim-target-directory)))))
+    (list regexp newname arg whole-path)))
+
+;;; Marking file names matching a regexp.
+
+(defun dired-mark-files-regexp (regexp &optional marker-char omission-files-p)
+  "\\<dired-mode-map>Mark all files matching REGEXP for use in later commands.
+
+A prefix argument \\[universal-argument] means to unmark them instead.
+
+A prefix argument 0 means to mark the files that would me omitted by \\[dired-omit-toggle].
+A prefix argument 1 means to unmark the files that would be omitted by \\[dired-omit-toggle].
+
+REGEXP is an Emacs regexp, not a shell wildcard.  Thus, use \"\\.o$\" for
+object files--just `.o' will mark more than you might think.  The files \".\"
+and \"..\" are never marked.
+"
+  (interactive
+   (let ((unmark (and (not (eq current-prefix-arg 0)) current-prefix-arg))
+	 (om-files-p (memq current-prefix-arg '(0 1)))
+	 regexp)
+     (if om-files-p
+	 (setq regexp (dired-omit-regexp))
+       (setq regexp (dired-read-with-history
+		    (concat (if unmark "Unmark" "Mark")
+			    " files (regexp): ") nil
+			    'dired-regexp-history)))
+     (list regexp (if unmark ?\ ) om-files-p)))
+  (let ((dired-marker-char (or marker-char dired-marker-char)))
+    (dired-mark-if
+     (and (not (looking-at dired-re-dot))
+	  (not (eolp))			; empty line
+	  (let ((fn (dired-get-filename nil t)))
+	    (and fn (string-match regexp (file-name-nondirectory fn)))))
+     (if omission-files-p
+	 "omission candidate file"
+       "matching file"))))
+
+(defun dired-flag-files-regexp (regexp)
+  "In dired, flag all files containing the specified REGEXP for deletion.
+The match is against the non-directory part of the filename.  Use `^'
+  and `$' to anchor matches.  Exclude subdirs by hiding them.
+`.' and `..' are never flagged."
+  (interactive (list (dired-read-with-history
+		      "Flag for deletion (regexp): " nil
+		      'dired-regexp-history)))
+  (dired-mark-files-regexp regexp dired-del-marker))
+
+(defun dired-mark-extension (extension &optional marker-char)
+  "Mark all files with a certain extension for use in later commands.
+A `.' is not prepended to the string entered."
+  ;; EXTENSION may also be a list of extensions instead of a single one.
+  ;; Optional MARKER-CHAR is marker to use.
+  (interactive "sMark files with extension: \nP")
+  (or (listp extension)
+      (setq extension (list extension)))
+  (dired-mark-files-regexp
+   (concat ".";; don't match names with nothing but an extension
+	   "\\("
+	   (mapconcat 'regexp-quote extension "\\|")
+	   "\\)$")
+   marker-char))
+
+(defun dired-flag-extension (extension)
+  "In dired, flag all files with a certain extension for deletion.
+A `.' is not prepended to the string entered."
+  (interactive "sFlag files with extension: ")
+  (dired-mark-extension extension dired-del-marker))
+
+(defun dired-cleanup (program)
+  "Flag for deletion dispensable files created by PROGRAM.
+See variable `dired-cleanup-alist'."
+  (interactive
+   (list
+    (let ((dired-cleanup-history (append dired-cleanup-history
+					 (mapcar 'car dired-cleanup-alist))))
+      (dired-completing-read
+       "Cleanup files for: " dired-cleanup-alist nil t nil
+       'dired-cleanup-history))))
+  (dired-flag-extension (cdr (assoc program dired-cleanup-alist))))
+
+;;; Commands on marked files whose names also match a regexp.
+
+(defun dired-do-rename-regexp (regexp newname &optional arg whole-path)
+  "Rename marked files containing REGEXP to NEWNAME.
+As each match is found, the user must type a character saying
+  what to do with it.  For directions, type \\[help-command] at that time.
+NEWNAME may contain \\=\\<n> or \\& as in `query-replace-regexp'.
+REGEXP defaults to the last regexp used.
+With a zero prefix arg, renaming by regexp affects the complete
+  pathname - usually only the non-directory part of file names is used
+  and changed."
+  (interactive (dired-mark-read-regexp "Rename"))
+  (dired-do-create-files-regexp
+   (function dired-rename-file)
+   "Rename" arg regexp newname whole-path dired-keep-marker-rename))
+
+(defun dired-do-copy-regexp (regexp newname &optional arg whole-path)
+  "Copy all marked files containing REGEXP to NEWNAME.
+See function `dired-rename-regexp' for more info."
+  (interactive (dired-mark-read-regexp "Copy"))
+  (dired-do-create-files-regexp
+   (function dired-copy-file)
+   (if dired-copy-preserve-time "Copy [-p]" "Copy")
+   arg regexp newname whole-path dired-keep-marker-copy))
+
+(defun dired-do-hardlink-regexp (regexp newname &optional arg whole-path)
+  "Hardlink all marked files containing REGEXP to NEWNAME.
+See function `dired-rename-regexp' for more info."
+  (interactive (dired-mark-read-regexp "HardLink"))
+  (dired-do-create-files-regexp
+   (function add-name-to-file)
+   "HardLink" arg regexp newname whole-path dired-keep-marker-hardlink))
+
+(defun dired-do-symlink-regexp (regexp newname &optional arg whole-path)
+  "Symlink all marked files containing REGEXP to NEWNAME.
+See function `dired-rename-regexp' for more info."
+  (interactive (dired-mark-read-regexp "SymLink"))
+  (dired-do-create-files-regexp
+   (function make-symbolic-link)
+   "SymLink" arg regexp newname whole-path dired-keep-marker-symlink))
+
+(defun dired-do-relsymlink-regexp (regexp newname &optional whole-path)
+  "RelSymlink all marked files containing REGEXP to NEWNAME.
+See functions `dired-rename-regexp' and `dired-do-relsymlink'
+  for more info."
+  (interactive (dired-mark-read-regexp "RelSymLink"))
+  (dired-do-create-files-regexp
+   (function dired-make-relative-symlink)
+   "RelSymLink" nil regexp newname whole-path dired-keep-marker-symlink))
+
+;;;; Modifying the case of file names.
+
+(defun dired-create-files-non-directory
+  (file-creator basename-constructor operation arg)
+  ;; Perform FILE-CREATOR on the non-directory part of marked files
+  ;; using function BASENAME-CONSTRUCTOR, with query for each file.
+  ;; OPERATION like in dired-create-files, ARG like in dired-get-marked-files.
+  (let (rename-non-directory-query)
+    (dired-create-files
+     file-creator
+     operation
+     (dired-get-marked-files nil arg)
+     (function
+      (lambda (from)
+	(let ((to (concat (file-name-directory from)
+			  (funcall basename-constructor
+				   (file-name-nondirectory from)))))
+	  (and (let ((help-form (format "\
+Type SPC or `y' to %s one file, DEL or `n' to skip to next,
+`!' to %s all remaining matches with no more questions."
+					(downcase operation)
+					(downcase operation))))
+		 (dired-query 'rename-non-directory-query
+			      (concat operation " `%s' to `%s'")
+			      (dired-make-relative from)
+			      (dired-make-relative to)))
+	       to))))
+     dired-keep-marker-rename)))
+
+(defun dired-rename-non-directory (basename-constructor operation arg)
+  (dired-create-files-non-directory
+   (function dired-rename-file)
+   basename-constructor operation arg))
+
+(defun dired-upcase (&optional arg)
+  "Rename all marked (or next ARG) files to upper case."
+  (interactive "P")
+  (dired-rename-non-directory (function upcase) "Rename upcase" arg))
+
+(defun dired-downcase (&optional arg)
+  "Rename all marked (or next ARG) files to lower case."
+  (interactive "P")
+  (dired-rename-non-directory (function downcase) "Rename downcase" arg))
+
+;;; end of dired-rgxp.el