From: kevin@edscom.demon.co.uk (Kevin Broadey)
Subject: Automatic templates based on file suffix
X-Disclaimer: These opinions are mine: others available on request.
Organization: EDS-Scicon, Milton Keynes, UK
X-Newsreader: GNUS 3.14.1
Date: Wed, 18 Nov 1992 16:49:39 GMT

I got hold of a copy of template.el by Tom Lord <lord+@andrew.cmu.edu> a
while ago and quite liked it, especially the idea of a "substitutions
file" which lets you specify on-the-fly replacements for macros in the
included template file.

One way I used it a lot was to include a skeleton file whenever I
started editing a new file, so I decided to modify it to run from
`find-file-hooks', using the file extension to select the template file.
I also tidied things up so that inclusion of a template could be undone
with a single "undo" command.

Here it is - hope you like it.

Kevin

------------------------------------------------------------------------
;; auto-template.el
;;
;; Written by Kevin Broadey <kbroadey@edscom.demon.co.uk>
;;
;; Version 1.0  02-Nov-92
;;
;; Read the DOC string for usage information.
;;
;; Based on template.el by Tom Lord <lord+@andrew.cmu.edu>.  I added the stuff
;; for running from find-file-hooks and generally hacked it beyond all
;; recognition.
;;
;; Usual GNU copyleft stuff.
;;
;; Mail me with bug reports and suggestions.

;; Mail me anyway if you like the package so I can feel all warm inside.

(defvar auto-template-dir "~/templates/"
  "*Directory containing template files.")

(defun auto-template (&optional template-file)

  "Insert the contents of TEMPLATE-FILE after point.  Mark is set at the
end of the inserted text.  If a \"substitutions file\" exists and is
readable, the substitutions are applied to the inserted text.  The
default directory for TEMPLATE-FILE is `auto-template-dir'.

A substitutions file has the same base name as TEMPLATE-FILE and suffix
\".sub\".  Each line looks like:-

    \"@PLACE-HOLDER@\"      (string-valued-sexp)
or
    \"@PLACE-HOLDER@\"      \"Prompt: \"

In the first case @PLACE_HOLDER@ is replaced by the value of the sexp,
and in the second the string is used as a prompt to read a replacement
string from the minibuffer.

The format of the place-holder is entirely up to you.  Just remember to
choose something that it unlikely to appear for real in the template
file.  Also, because substitutions are performed in the order they
appear, if the replacement for an earlier place-holder contains a later
one, this too will be replaced.  This is a feature, not a bug!

If you add this function to your `find-file-hooks' then when you visit a
new file it will automatically insert template file \"SUF.SUF\" from
`auto-template-dir', where SUF is the suffix for the new file.  It will
also apply substitutions file \"SUF.sub\" to the inserted text if it
exists and is readable."

  (interactive (list
		(let ((completion-ignored-extensions
		       (cons ".sub" completion-ignored-extensions)))
		  (read-file-name "Template file: " auto-template-dir nil t))))

  ;; If not called with a template file name, create one from the current
  ;; buffer's file name if this is a new file.
  (if (or template-file
	  (file-exists-p (buffer-file-name)))
      nil
    (setq template-file
	  (let* ((buffer-file-name (buffer-file-name))
		 (suffix (and buffer-file-name
			      (auto-template-get-suffix buffer-file-name)))
		 (file (and suffix
			    (expand-file-name (concat suffix "." suffix)
					      auto-template-dir))))
	    (and file
		 (file-readable-p file)
		 file))))

  ;; Do our stuff if we've got a template file.
  (if template-file
      (let ((substitution-file (concat
				(auto-template-strip-suffix template-file)
				".sub")))

	(let ((original-buffer (current-buffer))
	      (work-buffer (get-buffer-create " *auto-template*"))
	      substitutions)
	  ;; Note - I use a temporary buffer even when there is no
	  ;; substitutions file so that UNDO makes a new file's buffer go back
	  ;; to `unmodified'.  This didn't happen when I used `insert-file' to
	  ;; insert the file directly into the buffer - undo removed the text
	  ;; but left the buffer flagged as modified.
	  (set-buffer work-buffer)
	  (widen)
	  (erase-buffer)

	  ;; Read substitutions into a list if the file is readable.
	  (if (file-readable-p substitution-file)
	      (progn
		(insert "()")		; list delimiters
		(forward-char -1)
		(insert-file-contents substitution-file)
		(goto-char (point-min))
		(setq substitutions (read work-buffer))))

	  ;; Read in the template file.
	  (erase-buffer)
	  (insert-file-contents template-file)

	  ;; Apply the substitutions.
	  (while substitutions
	    (let ((place-holder (car substitutions))
		  (replacement (car (cdr substitutions))))
	      (setq substitutions (cdr (cdr substitutions)))
	      (setq replacement
		    (if (stringp replacement)
			(read-string replacement)
		      (eval replacement)))
	      (save-excursion
		(while (search-forward place-holder nil t)
		  (replace-match replacement t t)))
	      ))

	  ;; Insert the (possibly modified) template.
	  (set-buffer original-buffer)
	  (insert-buffer work-buffer)
	  (kill-buffer work-buffer)
	  ))))


(defun auto-template-get-suffix (file)
  "Return the file suffix for FILE, or NIL if none."
  (if (string-match "\\.\\([^./]+\\)$" file)
      (substring file (match-beginning 1) (match-end 1))))


(defun auto-template-strip-suffix (file)
  "Return FILE without its file suffix."
  (if (string-match "\\.[^./]+$" file)
      (substring file 0 (match-beginning 0))
    file))
------------------------------------------------------------------------
Ends
--
.signature: no such file or directory
Newsgroups: gnu.emacs.sources,rec.games.netrek