home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / dired / dired-trns.el < prev    next >
Encoding:
Text File  |  1994-09-20  |  7.7 KB  |  193 lines

  1. ;; dired-trns.el - file transformers for dired shell commands.
  2.  
  3. ;; Id: dired-trns.el,v 1.6 1991/07/05 13:36:01 sk RelBeta 
  4.  
  5. ;; Code contributed by Hans Chalupsky <hans@cs.Buffalo.EDU>.
  6. ;; Integrated with my dired.el sk@sparc0 11-Jan-1991 14:38.
  7. ;; And hacked up a bit.
  8.  
  9. ;; LISPDIR ENTRY for the Elisp Archive ===============================
  10. ;;    LCD Archive Entry:
  11. ;;    dired-trns|Hans Chalupsky|hans@cs.Buffalo.EDU
  12. ;;    |Filename Transformation for Tree Dired Shell Commands 
  13. ;;    |Date: 1991/07/05 13:36:01 |Revision: 1.6 |
  14.  
  15. ;; INSTALLATION ======================================================
  16. ;; Put this file into your load-path and add (load "dired-trns") to
  17. ;; your dired-load-hook, e.g.
  18. ;;
  19. ;; (setq dired-load-hook '(lambda ()
  20. ;;               ;; possibly more statements here
  21. ;;              (load "dired-trns")))
  22.  
  23. ;; Transformers are functions that take a file (a string) as an argument
  24. ;; and transform it into some other string (e.g., a filename without an
  25. ;; extension).
  26. ;;
  27. ;; Each transformer is associated with a dispatch character. The associations
  28. ;; are stored in a keymap for fast and easy lookup. The dispatch character
  29. ;; is used to activate the associated transformer function at a particular
  30. ;; position in a shell command issued in dired.
  31. ;;
  32. ;; Transformers can be used to construct complicated shell commands that
  33. ;; operate on a large number of files, for example, they allow to create
  34. ;; functionality such as "mv *.lsp *.lisp" where each .lsp file is
  35. ;; renamed into a a file with same name but new extension .lisp.
  36.  
  37. (defvar dired-trans-map (make-keymap)
  38.   "Array that associates keys with file transformer functions")
  39.  
  40. (defmacro dired-trans-define (char &rest body)
  41.   "Macro that assigns the transformer function (lambda (file) BODY) to 
  42. CHAR (a character or string). BODY must return a string (the transformed
  43. file or whatever. This macro allows easy definition of user specific
  44. transformation functions."
  45.   (if (not (stringp char)) (setq char (char-to-string char)))
  46.   (list 'define-key 'dired-trans-map char
  47.     (list 'function (append '(lambda (file)) body))))
  48.  
  49. (defun dired-trans-run (transformers file)
  50.   "Applies each transformer supplied in the string TRANSFORMERS in sequence
  51. to FILE and returns the concatenation of the results."
  52.   (mapconcat (function
  53.           (lambda (transformer)
  54.         (setq transformer (char-to-string transformer))
  55.         (funcall (or (lookup-key dired-trans-map transformer)
  56.                  (error "Undefined transfomer: %s" transformer))
  57.              file)))
  58.          transformers nil))
  59.  
  60. (defvar dired-trans-re-ext "\\.[^.]*\\(\\.\\(\\(g?z\\)\\|Z\\)\\)?$"
  61.   "The part of a filename matching this regexp will be viewed as extension")
  62.  
  63. (defun dired-trans-init ()
  64.   "Defines a basic set of useful transformers.
  65.  
  66. *  is a noop that returns the unmodified filename (equivalent to [dbe]).
  67. n  returns the Name component of a filename without directory information
  68. d  returns the Directory component of a filename
  69. b  returns the Basename of a filename, i.e., the name of the file without
  70.    directory and extension (see dired-trans-re-ext)
  71.    A basename with directory component can be obtained by [db].
  72. e  returns the Extension of a filename (i.e., whatever
  73.    dired-trans-re-ext splits off)
  74. v  returns a file without directory and without ,v suffixes if any.
  75. z  returns a file without directory and without .Z .z .gz suffixes if any."
  76.   (dired-trans-define
  77.    "*" file)
  78.   (dired-trans-define
  79.    "n" (or (file-name-nondirectory file) ""))
  80.   (dired-trans-define
  81.    "d" (or (file-name-directory file) ""))
  82.   (dired-trans-define
  83.    "b" (setq file (dired-trans-run "n" file))
  84.        (substring file 0 (string-match dired-trans-re-ext file)))
  85.   (dired-trans-define
  86.    "e" (let ((e (string-match dired-trans-re-ext file)))
  87.      (if e
  88.          (substring file e)
  89.        "")))
  90.   (dired-trans-define
  91.    "v" (setq file (dired-trans-run "n" file))
  92.        (substring file 0 (string-match ",v$" file)))
  93.   (dired-trans-define
  94.    "z" (setq file (dired-trans-run "n" file))
  95.        (substring file 0 (string-match "\\.\\(\\(g?z\\)\\|Z\\)$" file)))
  96.   )
  97.  
  98. (dired-trans-init)
  99.  
  100. (defun dired-trans-mklist (files &optional transformers)
  101.   "Takes a list of FILES and applies the sequence of TRANSFORMERS to each
  102. of them. The transformed results are concatenated, separated by 
  103. dired-mark-separator, prefixed by dired-mark-prefix and postfixed by
  104. dired-mark-postfix to generate a file list suitable for a particular shell."
  105.   (if (not (consp files))(setq files (list files)))
  106.   (if (null transformers) (setq transformers "*"))
  107.   (let ((file-list
  108.      (mapconcat (function
  109.              (lambda (file)
  110.                (shell-quote
  111.             (dired-trans-run transformers file))))
  112.             files dired-mark-separator)))
  113.     (if (> (length files) 1)
  114.     (concat dired-mark-prefix file-list dired-mark-postfix)
  115.       file-list)))
  116.  
  117. ;; By default, transformations can be specified like this:
  118. ;; [db] or [dv] or #z# or #dbe# or #dbe  (blank at the end).
  119.     
  120. (defvar dired-trans-starters "[#[]"
  121.   "User definable set of characters to be used to indicate the start of a
  122. transformer sequence")
  123.  
  124. (defvar dired-trans-enders "[]# ]"
  125.   "User definable set of characters to be used to indicate the end of a
  126. transformer sequence")
  127.  
  128. (defun dired-trans-expand (command files)
  129.   "Takes a shell COMMAND and a list of FILES and substitutes each occurance
  130. of a transformer sequence by an accordingly transformed file list. Special
  131. characters such as [,] or * can be quoted with a backslash."
  132.   (let ((quoted nil)
  133.     (collect-transformers nil)
  134.     (transformers ""))
  135.     (mapconcat (function
  136.         (lambda (char)
  137.           (setq char (char-to-string char))
  138.           (cond (quoted (setq quoted nil) char)
  139.             ((equal char "\\") (setq quoted t) nil)
  140.             (collect-transformers
  141.              (cond ((string-match dired-trans-enders char)
  142.                 (setq collect-transformers nil)
  143.                 (prog1 (dired-trans-mklist
  144.                     files transformers)
  145.                   (setq transformers "")))
  146.                    (t (setq transformers
  147.                     (concat transformers char))
  148.                   nil)))
  149.             ((string-match dired-trans-starters char)
  150.                           (setq collect-transformers t) nil)
  151.             ;; for compatibility and as a special case that should
  152.             ;; not be redefinable by the user (used below)
  153.             ((equal char "*")
  154.              (dired-trans-mklist files "*"))
  155.             (t char))))
  156.            command nil)))
  157.  
  158. (defun dired-trans-make (command files &optional all-at-once)
  159.   "Takes a shell COMMAND and a list of FILES and returns a command operating
  160. on the list of files (transformed if COMMAND contains transformers). If
  161. ALL-AT-ONCE is t the resulting command will be of the form
  162.   cmd file1 file2 ... fileN
  163. otherwise it will be
  164.   cmd file1; cmd file2; ... cmd fileN;
  165. Both examples assume a single reference to the file list."
  166.   (let (fns expanded-command)
  167.     (cond (all-at-once
  168.        (setq expanded-command (dired-trans-expand command files))
  169.        (if (equal command expanded-command)
  170.            (concat command (dired-trans-expand " *" files))
  171.            expanded-command))
  172.       (t (mapconcat
  173.           (function
  174.            (lambda (file)
  175.          (dired-trans-make command file t)))
  176.           files ";")))))
  177.  
  178. ;; Redefine this function from dired.el:
  179.  
  180. (defun dired-shell-stuff-it (command file-list on-each &optional raw-arg)
  181. "Make up a shell command line from COMMAND and FILE-LIST.
  182. If ON-EACH is t, COMMAND should be applied to each file, else
  183.   simply concat all files.
  184. The list of marked files is appended to the command string unless asterisks
  185.   `*' or transformer sequences enclosed in `[]' indicate the place(s) where 
  186.   the (transformed) list should go.  See documentation of function
  187.   dired-trans-init for a list of transformers.
  188. With a zero argument the resulting command will be of the form
  189.   cmd file1; cmd file2; ... cmd fileN assuming only one reference to the
  190.   file list. E.g., to rename all .lsp files into .lisp files mark all the
  191.   .lsp files and issue the command `mv * [db].lisp' ."
  192.   (dired-trans-make command file-list (not on-each)))
  193.