diff lisp/dired/dired-trns.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/dired/dired-trns.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,192 @@
+;; dired-trns.el - file transformers for dired shell commands.
+
+;; Id: dired-trns.el,v 1.6 1991/07/05 13:36:01 sk RelBeta 
+
+;; Code contributed by Hans Chalupsky <hans@cs.Buffalo.EDU>.
+;; Integrated with my dired.el sk@sparc0 11-Jan-1991 14:38.
+;; And hacked up a bit.
+
+;; LISPDIR ENTRY for the Elisp Archive ===============================
+;;    LCD Archive Entry:
+;;    dired-trns|Hans Chalupsky|hans@cs.Buffalo.EDU
+;;    |Filename Transformation for Tree Dired Shell Commands 
+;;    |Date: 1991/07/05 13:36:01 |Revision: 1.6 |
+
+;; INSTALLATION ======================================================
+;; Put this file into your load-path and add (load "dired-trns") to
+;; your dired-load-hook, e.g.
+;;
+;; (setq dired-load-hook '(lambda ()
+;; 			  ;; possibly more statements here
+;;			  (load "dired-trns")))
+
+;; Transformers are functions that take a file (a string) as an argument
+;; and transform it into some other string (e.g., a filename without an
+;; extension).
+;;
+;; Each transformer is associated with a dispatch character. The associations
+;; are stored in a keymap for fast and easy lookup. The dispatch character
+;; is used to activate the associated transformer function at a particular
+;; position in a shell command issued in dired.
+;;
+;; Transformers can be used to construct complicated shell commands that
+;; operate on a large number of files, for example, they allow to create
+;; functionality such as "mv *.lsp *.lisp" where each .lsp file is
+;; renamed into a a file with same name but new extension .lisp.
+
+(defvar dired-trans-map (make-keymap)
+  "Array that associates keys with file transformer functions")
+
+(defmacro dired-trans-define (char &rest body)
+  "Macro that assigns the transformer function (lambda (file) BODY) to 
+CHAR (a character or string). BODY must return a string (the transformed
+file or whatever. This macro allows easy definition of user specific
+transformation functions."
+  (if (not (stringp char)) (setq char (char-to-string char)))
+  (list 'define-key 'dired-trans-map char
+	(list 'function (append '(lambda (file)) body))))
+
+(defun dired-trans-run (transformers file)
+  "Applies each transformer supplied in the string TRANSFORMERS in sequence
+to FILE and returns the concatenation of the results."
+  (mapconcat (function
+	      (lambda (transformer)
+		(setq transformer (char-to-string transformer))
+		(funcall (or (lookup-key dired-trans-map transformer)
+			     (error "Undefined transfomer: %s" transformer))
+			 file)))
+	     transformers nil))
+
+(defvar dired-trans-re-ext "\\.[^.]*\\(\\.\\(\\(g?z\\)\\|Z\\)\\)?$"
+  "The part of a filename matching this regexp will be viewed as extension")
+
+(defun dired-trans-init ()
+  "Defines a basic set of useful transformers.
+
+*  is a noop that returns the unmodified filename (equivalent to [dbe]).
+n  returns the Name component of a filename without directory information
+d  returns the Directory component of a filename
+b  returns the Basename of a filename, i.e., the name of the file without
+   directory and extension (see dired-trans-re-ext)
+   A basename with directory component can be obtained by [db].
+e  returns the Extension of a filename (i.e., whatever
+   dired-trans-re-ext splits off)
+v  returns a file without directory and without ,v suffixes if any.
+z  returns a file without directory and without .Z .z .gz suffixes if any."
+  (dired-trans-define
+   "*" file)
+  (dired-trans-define
+   "n" (or (file-name-nondirectory file) ""))
+  (dired-trans-define
+   "d" (or (file-name-directory file) ""))
+  (dired-trans-define
+   "b" (setq file (dired-trans-run "n" file))
+       (substring file 0 (string-match dired-trans-re-ext file)))
+  (dired-trans-define
+   "e" (let ((e (string-match dired-trans-re-ext file)))
+	 (if e
+	     (substring file e)
+	   "")))
+  (dired-trans-define
+   "v" (setq file (dired-trans-run "n" file))
+       (substring file 0 (string-match ",v$" file)))
+  (dired-trans-define
+   "z" (setq file (dired-trans-run "n" file))
+       (substring file 0 (string-match "\\.\\(\\(g?z\\)\\|Z\\)$" file)))
+  )
+
+(dired-trans-init)
+
+(defun dired-trans-mklist (files &optional transformers)
+  "Takes a list of FILES and applies the sequence of TRANSFORMERS to each
+of them. The transformed results are concatenated, separated by 
+dired-mark-separator, prefixed by dired-mark-prefix and postfixed by
+dired-mark-postfix to generate a file list suitable for a particular shell."
+  (if (not (consp files))(setq files (list files)))
+  (if (null transformers) (setq transformers "*"))
+  (let ((file-list
+	 (mapconcat (function
+		     (lambda (file)
+		       (shell-quote
+			(dired-trans-run transformers file))))
+		    files dired-mark-separator)))
+    (if (> (length files) 1)
+	(concat dired-mark-prefix file-list dired-mark-postfix)
+      file-list)))
+
+;; By default, transformations can be specified like this:
+;; [db] or [dv] or #z# or #dbe# or #dbe  (blank at the end).
+    
+(defvar dired-trans-starters "[#[]"
+  "User definable set of characters to be used to indicate the start of a
+transformer sequence")
+
+(defvar dired-trans-enders "[]# ]"
+  "User definable set of characters to be used to indicate the end of a
+transformer sequence")
+
+(defun dired-trans-expand (command files)
+  "Takes a shell COMMAND and a list of FILES and substitutes each occurance
+of a transformer sequence by an accordingly transformed file list. Special
+characters such as [,] or * can be quoted with a backslash."
+  (let ((quoted nil)
+	(collect-transformers nil)
+	(transformers ""))
+    (mapconcat (function
+		(lambda (char)
+		  (setq char (char-to-string char))
+		  (cond (quoted (setq quoted nil) char)
+			((equal char "\\") (setq quoted t) nil)
+			(collect-transformers
+			 (cond ((string-match dired-trans-enders char)
+				(setq collect-transformers nil)
+				(prog1 (dired-trans-mklist
+					files transformers)
+				  (setq transformers "")))
+			       (t (setq transformers
+					(concat transformers char))
+				  nil)))
+			((string-match dired-trans-starters char)
+                          (setq collect-transformers t) nil)
+			;; for compatibility and as a special case that should
+			;; not be redefinable by the user (used below)
+			((equal char "*")
+			 (dired-trans-mklist files "*"))
+			(t char))))
+	       command nil)))
+
+(defun dired-trans-make (command files &optional all-at-once)
+  "Takes a shell COMMAND and a list of FILES and returns a command operating
+on the list of files (transformed if COMMAND contains transformers). If
+ALL-AT-ONCE is t the resulting command will be of the form
+  cmd file1 file2 ... fileN
+otherwise it will be
+  cmd file1; cmd file2; ... cmd fileN;
+Both examples assume a single reference to the file list."
+  (let (fns expanded-command)
+    (cond (all-at-once
+	   (setq expanded-command (dired-trans-expand command files))
+	   (if (equal command expanded-command)
+	       (concat command (dired-trans-expand " *" files))
+	       expanded-command))
+	  (t (mapconcat
+	      (function
+	       (lambda (file)
+		 (dired-trans-make command file t)))
+	      files ";")))))
+
+;; Redefine this function from dired.el:
+
+(defun dired-shell-stuff-it (command file-list on-each &optional raw-arg)
+"Make up a shell command line from COMMAND and FILE-LIST.
+If ON-EACH is t, COMMAND should be applied to each file, else
+  simply concat all files.
+The list of marked files is appended to the command string unless asterisks
+  `*' or transformer sequences enclosed in `[]' indicate the place(s) where 
+  the (transformed) list should go.  See documentation of function
+  dired-trans-init for a list of transformers.
+With a zero argument the resulting command will be of the form
+  cmd file1; cmd file2; ... cmd fileN assuming only one reference to the
+  file list. E.g., to rename all .lsp files into .lisp files mark all the
+  .lsp files and issue the command `mv * [db].lisp' ."
+  (dired-trans-make command file-list (not on-each)))