home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / auto-template.el < prev    next >
Encoding:
Text File  |  1992-11-25  |  5.6 KB  |  164 lines

  1. ; Path: hal.com!olivea!uunet!pipex!demon!edscom!kevin
  2. ; From: kevin@edscom.demon.co.uk (Kevin Broadey)
  3. ; Newsgroups: gnu.emacs.sources
  4. ; Subject: Automatic templates based on file suffix
  5. ; Date: 18 Nov 92 16:49:39 GMT
  6. ; Organization: EDS-Scicon, Milton Keynes, UK
  7. ; I got hold of a copy of template.el by Tom Lord <lord+@andrew.cmu.edu> a
  8. ; while ago and quite liked it, especially the idea of a "substitutions
  9. ; file" which lets you specify on-the-fly replacements for macros in the
  10. ; included template file.
  11. ; One way I used it a lot was to include a skeleton file whenever I
  12. ; started editing a new file, so I decided to modify it to run from
  13. ; `find-file-hooks', using the file extension to select the template file.
  14. ; I also tidied things up so that inclusion of a template could be undone
  15. ; with a single "undo" command.
  16. ; Here it is - hope you like it.
  17. ; Kevin
  18. ; ------------------------------------------------------------------------
  19. ;; auto-template.el
  20. ;;
  21. ;; LCD Archive Entry:
  22. ;; auto-template|Kevin Broadey|kevin@edscom.demon.co.uk|
  23. ;; Auto insert templates with macro replacement based on file extension.|
  24. ;; 92-11-02|1.0|~/misc/auto-template.el.Z|
  25. ;;
  26. ;; Written by Kevin Broadey <kbroadey@edscom.demon.co.uk>
  27. ;;
  28. ;; Version 1.0  02-Nov-92
  29. ;;
  30. ;; Read the DOC string for usage information.
  31. ;;
  32. ;; Based on template.el by Tom Lord <lord+@andrew.cmu.edu>.  I added the stuff
  33. ;; for running from find-file-hooks and generally hacked it beyond all
  34. ;; recognition.
  35. ;;
  36. ;; Usual GNU copyleft stuff.
  37. ;;
  38. ;; Mail me with bug reports and suggestions.
  39.  
  40. ;; Mail me anyway if you like the package so I can feel all warm inside.
  41.  
  42. (defvar auto-template-dir "~/templates/"
  43.   "*Directory containing template files.")
  44.  
  45. (defun auto-template (&optional template-file)
  46.  
  47.   "Insert the contents of TEMPLATE-FILE after point.  Mark is set at the
  48. end of the inserted text.  If a \"substitutions file\" exists and is
  49. readable, the substitutions are applied to the inserted text.  The
  50. default directory for TEMPLATE-FILE is `auto-template-dir'.
  51.  
  52. A substitutions file has the same base name as TEMPLATE-FILE and suffix
  53. \".sub\".  Each line looks like:-
  54.  
  55.     \"@PLACE-HOLDER@\"      (string-valued-sexp)
  56. or
  57.     \"@PLACE-HOLDER@\"      \"Prompt: \"
  58.  
  59. In the first case @PLACE_HOLDER@ is replaced by the value of the sexp,
  60. and in the second the string is used as a prompt to read a replacement
  61. string from the minibuffer.
  62.  
  63. The format of the place-holder is entirely up to you.  Just remember to
  64. choose something that it unlikely to appear for real in the template
  65. file.  Also, because substitutions are performed in the order they
  66. appear, if the replacement for an earlier place-holder contains a later
  67. one, this too will be replaced.  This is a feature, not a bug!
  68.  
  69. If you add this function to your `find-file-hooks' then when you visit a
  70. new file it will automatically insert template file \"SUF.SUF\" from
  71. `auto-template-dir', where SUF is the suffix for the new file.  It will
  72. also apply substitutions file \"SUF.sub\" to the inserted text if it
  73. exists and is readable."
  74.  
  75.   (interactive (list
  76.         (let ((completion-ignored-extensions
  77.                (cons ".sub" completion-ignored-extensions)))
  78.           (read-file-name "Template file: " auto-template-dir nil t))))
  79.  
  80.   ;; If not called with a template file name, create one from the current
  81.   ;; buffer's file name if this is a new file.
  82.   (if (or template-file
  83.       (file-exists-p (buffer-file-name)))
  84.       nil
  85.     (setq template-file
  86.       (let* ((buffer-file-name (buffer-file-name))
  87.          (suffix (and buffer-file-name
  88.                   (auto-template-get-suffix buffer-file-name)))
  89.          (file (and suffix
  90.                 (expand-file-name (concat suffix "." suffix)
  91.                           auto-template-dir))))
  92.         (and file
  93.          (file-readable-p file)
  94.          file))))
  95.  
  96.   ;; Do our stuff if we've got a template file.
  97.   (if template-file
  98.       (let ((substitution-file (concat
  99.                 (auto-template-strip-suffix template-file)
  100.                 ".sub")))
  101.  
  102.     (let ((original-buffer (current-buffer))
  103.           (work-buffer (get-buffer-create " *auto-template*"))
  104.           substitutions)
  105.       ;; Note - I use a temporary buffer even when there is no
  106.       ;; substitutions file so that UNDO makes a new file's buffer go back
  107.       ;; to `unmodified'.  This didn't happen when I used `insert-file' to
  108.       ;; insert the file directly into the buffer - undo removed the text
  109.       ;; but left the buffer flagged as modified.
  110.       (set-buffer work-buffer)
  111.       (widen)
  112.       (erase-buffer)
  113.  
  114.       ;; Read substitutions into a list if the file is readable.
  115.       (if (file-readable-p substitution-file)
  116.           (progn
  117.         (insert "()")        ; list delimiters
  118.         (forward-char -1)
  119.         (insert-file-contents substitution-file)
  120.         (goto-char (point-min))
  121.         (setq substitutions (read work-buffer))))
  122.  
  123.       ;; Read in the template file.
  124.       (erase-buffer)
  125.       (insert-file-contents template-file)
  126.  
  127.       ;; Apply the substitutions.
  128.       (while substitutions
  129.         (let ((place-holder (car substitutions))
  130.           (replacement (car (cdr substitutions))))
  131.           (setq substitutions (cdr (cdr substitutions)))
  132.           (setq replacement
  133.             (if (stringp replacement)
  134.             (read-string replacement)
  135.               (eval replacement)))
  136.           (save-excursion
  137.         (while (search-forward place-holder nil t)
  138.           (replace-match replacement t t)))
  139.           ))
  140.  
  141.       ;; Insert the (possibly modified) template.
  142.       (set-buffer original-buffer)
  143.       (insert-buffer work-buffer)
  144.       (kill-buffer work-buffer)
  145.       ))))
  146.  
  147.  
  148. (defun auto-template-get-suffix (file)
  149.   "Return the file suffix for FILE, or NIL if none."
  150.   (if (string-match "\\.\\([^./]+\\)$" file)
  151.       (substring file (match-beginning 1) (match-end 1))))
  152.  
  153.  
  154. (defun auto-template-strip-suffix (file)
  155.   "Return FILE without its file suffix."
  156.   (if (string-match "\\.[^./]+$" file)
  157.       (substring file 0 (match-beginning 0))
  158.     file))
  159.