Mercurial > hg > xemacs-beta
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)))