[comp.emacs] Template: a cool new package for GNU Emacs

wmesard@oracle.com (Wayne Mesard) (04/13/91)

Template is a bunch of enhancements to the old GNU Emacs Abbrev facility
we all know and love.  In addition to straight textual substitution,
Template will insert time- and date-stamps, your name and user-id and
the current file name.  It can prompt the user for strings.  It can also
position the cursor within the expanded text, and indent it in whatever
way is appropriate to the current major mode.

But wait! there's more: Template will also allow you to bind templates
to keys and automatically insert templates in new files (like
autoinsert.el does).  Now how much would you pay?

Previously, you had to get an Elisp programmer to write functions to do
things like this.  (E.g., there must be literally hundreds of functions
out there to do things like insert-timestamp or insert-c-for-statement.)
With Template, it's as simple as making an entry in a table.

Once I settled on, and memorized, some mnemonic names for my personal
template table, I've found that Template has made the boring part of
programming (i.e., typing) a lot easier.

Template can't enforce a coding standard, but it can make it much easier
to adhere to one.  If an entire development team agrees to use a common
template table with standard comment and code templates, you can't help
but wind up with similar coding styles.

Wayne();
WMesard@Oracle.COM

------------- snip --- snip --- snip ---------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of shell archive."
# Contents:  README template.txt template.el template-example.el
#   template-example.txt
# Wrapped by wmesard@tofu on Fri Apr 12 11:56:01 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1712 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XTemplate is a bunch of enhancements to the old GNU Emacs Abbrev facility
Xwe all know and love.  In addition to straight textual substitution,
XTemplate will insert time- and date-stamps, your name and user-id and
Xthe current file name.  It can prompt the user for strings.  It can also
Xposition the cursor within the expanded text, and indent it in whatever
Xway is appropriate to the current major mode.
X
XBut wait! there's more: Template will also allow you to bind templates
Xto keys and automatically insert templates in new files (like
Xautoinsert.el does).  Now how much would you pay?
X
XPreviously, you had to get an Elisp programmer to write functions to do
Xthings like this.  (E.g., there must be literally hundreds of functions
Xout there to do things like insert-timestamp or insert-c-for-statement.)
XWith Template, it's as simple as making an entry in a table.
X
XOnce I settled on, and memorized, some mnemonic names for my personal
Xtemplate table, I've found that Template has made the boring part of
Xprogramming (i.e., typing) a lot easier.
X
XTemplate can't enforce a coding standard, but it can make it much easier
Xto adhere to one.  If an entire development team agrees to use a common
Xtemplate table with standard comment and code templates, you can't help
Xbut wind up with similar coding styles.
X
XIn short, I'm too pleased with this to keep it to myself anymore.
X
XContents:
X
X README			This file.
X template.el:		The code.  Compile it, load it, live it.
X template.txt:		Documentation.
X template-example.el	The basic structure of and some ideas for your own
X			 template table.
X template-example.txt	Documentation for the example.
X
X
XComments, questions, suggestions to:
X  Wayne Mesard
X  WMesard@Oracle.COM

END_OF_FILE
echo shar: NEWLINE appended to \"'README'\"
if test 1713 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'template.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'template.txt'\"
else
echo shar: Extracting \"'template.txt'\" \(9555 characters\)
sed "s/^X//" >'template.txt' <<'END_OF_FILE'
XCopyright (c) 1991 by Wayne Mesard.
XMay be redistributed under the terms of the GNU Emacs General Public License.
X
X
XNAME:
X----
XTemplate
X
XSUMMARY:
X-------
XThis package can significantly reduce typing time and increase
Xformatting consistency of source code and comments.  It allows users to
Xeasily construct and use templates for complicated blocks of text
X(timestamps, comments, common program blocks).  Previously, people would
Xwrite specialized Elisp functions to accomplish this.
X
X
XWARNING:
X-------
XThis document is a detailed description of how Template works, all the
Xfeatures of the package and how to build your own template tables.
XUnless you're a total geek, don't read this; it'll just turn you off.
X
XTemplate table users: All you need to know is that typing a template
X  name followed by "Control-C X" will expand that template.  You also need
X  a list of the specific templates in the table that you're using.
X
XTemplate table builders: You can probably figure out how to construct a
X  template table by looking at an existing one.  The file template-example.el
X  was included with the Template distribution.  It should get you
X  started.  After you get your feet wet, read this document to learn
X  about cool things like auto-insertion and binding templates to keys. 
X
X
XKEY BINDINGS:
X--- --------
X
XControl-C x: Expands the template to the left of the cursor.  (This is
X             really just the plain old expand-abbrev command.  Normally,
X             it's bound to the more awkward Control-X '.)
X
X
XAs with all my Emacs modifications, no key binding will be done if the
Xvariable DONT-BIND-MY-KEYS is set.  So if you don't want me messing with
Xyour keymap add the following line to the top of your .emacs file:
X
X  (setq dont-bind-my-keys t)
X
X[I like this convention and recommend that other Elisp coders adopt it.]
X
X
XDESCRIPTION:
X-----------
X
XCREATING TEMPLATES.
X
XThe Template package is built on top of the GNU Emacs Abbrev facility.
XWriting a template table is a lot like writing an abbrev table except
Xthat the expanded text can contain Template directives which
Xcontrol what gets inserted into the buffer.  (This works via a little
Xknown feature of Abbrev which allows each entry to specify a Lisp
Xfunction to be called after the text is expanded.)
X
XConsider four examples:
X
X (add-templates 'c-mode-abbrev-table '(
X    ("d" 	"#define " 		nil)
X    ("i" 	"#include <~@.h>\n" 	template-indent)
X
X    ("masthead"	"/* Filename: ~fn. Copyright (c) ~dY BIG Corp. */\n"
X					template-expand)
X
X    ("mal"    "if ((~@ = (~s0 *)~>>malloc(~s1 * sizeof(~s0))) == (~s0 *)NULL)\n"
X		(lambda () (template-prompt-indent "Datatype: " "Quantity: ")))
X
X    ))
X
XThe first template, "d", simply expands to "#define ".  This is fairly
Xuninteresting and, in fact, could have been accomplished with plain old
XAbbrev.
X
XThe second template, "i", expands to "#include<.h>" plus a carriage
Xreturn.  Notice the "~@" directive in the template definition.
XThis means that the cursor will be positioned at this point in the text
Xafter it is expanded (since this is where the user will probably want
Xto continue typing).
X
XThe "masthead" template expands to a copyright notice suitable for use
Xas the first line of a source code file.  The "~fn" and "~dY" directives
Xwill expand to the name of the file, and the year, respectively.
X
XThe "mal" template is a more complicated example.  It's for entering a
Xmalloc() call of the form:
X
X  if ((var = (type *)malloc(qty * sizeof(type))) == (type *)NULL)
X    ...
X
XThis is something that C programmers have to type all the time.  This
Xtemplate simplifies the process by prompting the user for TYPE and QTY.
XAdditionally, if you have another template named "malloc" defined, it
Xwill use that instead of the word "malloc".  Finally it places the
Xcursor right before the "=" so the user can quickly enter the VAR.
X
XHopefully, these examples have demonstrated that Template is quite
Xpowerful yet still fairly easy to use.
X
XOh yeah, nearly forgot, ADD-TEMPLATES is just like Emacs' DEFINE-
XABBREV-TABLE except that ADD-TEMPLATES doesn't destroy entries already
Xin the table.  So, your project group could have a common template file,
Xand then each user can have private additions or modifications.
X
X
XEXPANSION FUNCTIONS.
X
XAs shown above, each template definition is of the form 
X(NAME TEXT EXPANSION-FUNCTION).  The valid expansion functions are:
X
X nil:  Use this if the template is a simple text expansion (i.e., no
X       directives) which you don't want re-indented.
X
X template-expand:  
X       Use this for simple templates with directives.
X
X template-indent:
X       Use this if you want to make sure each line of the expansion is
X       properly justified.  The Template package indents each line in
X       the expansion in whatever way is appropriate for the current mode
X       and user settings.  So, e.g., two people who have different
X       indentation settings for C mode can use the same templates and it
X       will do the right thing for both of them.  
X
X template-prompt:
X      If a template contains any "~sN" directives (see below), then
X      it must be expanded with template-prompt (or template-prompt-indent).
X      It will prompt the user for the appropriate value(s) in the
X      minibuffer.  As was shown in the "mal" example above, the format
X      is somewhat ugly: 
X
X         (lambda () (template-prompt "First Prompt: " "Second Prompt: " ...))
X
X      [Actually, it's sort of an accident that this works at all, so I
X      guess we shouldn't complain.]
X
X template-prompt-indent:
X      This is essentially a combination of template-prompt and
X      template-indent.  It requires the ugly lambda format.
X
X
XTEMPLATE DIRECTIVES.
X
XThe valid directives are:
X
X ~dy: year ("91")
X ~dY: year ("1991")
X ~dm: month ("apr")
X ~dn: month, numeric ("9", "12")
X ~dN: month, numeric ("09", "12")
X ~dd: date ("1", "31")
X ~dD: date ("01", "31")
X ~dw: day of week ("tue")
X ~ta: "am" or "pm"
X ~th: hour, 12hr system ("2", "11")
X ~tH: hour, 12hr system ("02", "11")
X ~te: hour, 24hr system ("2", "23")
X ~tE: hour, 24hr system ("02", "23")
X ~tm: minutes ("09", "59")
X ~ts: seconds ("09", "59")
X ~ui: user id
X ~uN: the first N letters of the user id (where N is a single digit)
X ~un: user name
X ~fn: filename of the current buffer
X ~fd: directory of the current buffer
X ~fp: filename prefix (i.e., up to the last period)
X ~fe: filename extension (i.e., after the last period)
X ~sN: the Nth user-specified string (where N is a single digit).
X      (See documentation on the function TEMPLATE-PROMPT for details.)
X ~~:  the template prefix char ("~")
X ~@:  indicates that the cursor should be placed here when done
X ~>>: indicates that the following word may be a template name and it should
X      be recursively expanded
X ~>@: same as "~>>"; in addition the cursor will be left where the
X      recursive template puts it. (Normally, "~>>" ignores "~@"s in the
X      recursive template.)
X ~pC: use C to pad single-digit numbers (where C is any character).
X      (See documentation on the variable TEMPLATE-PAD-CHAR for details.)
X
XIf the conversion command is uppercase or capitalized, then the replacement 
Xtext will be uppercase or capitalized, respectively.
X
X"~>>" and "~>@" can be used to mix-and-match several templates.  For
Xexample, if your "dot h" file masthead is the same as your "dot c" file
Xmasthead plus some other junk, you could define a template for it as
X"~>@masthead~>>junk".
X
XThe directives "~dM", "~dd", "~tH" and "~tE" all pad single digit
Xnumbers to two characters.  E.g., "9" is displayed as "09" and "0" is
Xdisplayed as "00".  If you want to pad with a character other than "0",
Xset the variable TEMPLATE-PAD-CHAR; or, to override TEMPLATE-PAD-CHAR on a
Xper-template basis, use the "~p" directive.
X
X
XAUTO-INSERTION OF TEMPLATES.
X
XThe Template package can automatically insert a template whenever you
Xcreate a new file.  This behavior is controlled by the variable
Xauto-template-alist.  Its format is similar to Emacs' AUTO-MODE-ALIST.
XFor example, if you defined a template named "masthead" that you want to
Xautomatically insert whenever you create a new ".c" or ".h" file, and a
Xtemplate named "manskeleton" that you want inserted whenever you create
Xa new ".man" file, you would put the following in your Emacs init file:
X
X  (setq auto-template-alist '(("\\.[ch]$" . masthead) 
X			      ("\\.man$" . manskeleton)))
X
XPeople typically use longer, more descriptive, names for templates that
Xwill be auto-inserted since they hardly ever have to type them.
X
X
XBINDING TEMPLATES TO KEYS.
X
XFor the true Emacs weenie--who likes to have everything bound to
Xkeys--it is possible to turn templates into functions.  Three examples
Xwill illustrate how this works.  These lines could be placed in a .emacs
Xfile, or in a template table file itself:
X
X  (define-key c-mode-map "\C-cm" (template-function "mal"))
X  (global-set-key        "\C-ct" (template-function "dstamp" "dtstamp"))
X  (define-key c-mode-map "\C-cf" (template-function "for" nil 'c-insert-for))
X
XThe first example binds the "mal" template to "Control-C m" in C
Xbuffers.  The second example binds the "dstamp" template to "Control-C
Xt" and the "dtstamp" template to "Control-U Control-C t".  The final
Xexample binds a template named "for" to "Control-C f" and creates a real
Xlive Emacs command called C-INSERT-FOR, suitable for use with C-h f and
XESC x.
X
X
XAUTHOR:
X------
XWayne Mesard
XWMesard@Oracle.COM
X[As always, I am anxious to hear what you think about Templates
X including problems, suggestions, things you've added.  Basically, I
X just like to get email.]

END_OF_FILE
echo shar: NEWLINE appended to \"'template.txt'\"
if test 9556 -ne `wc -c <'template.txt'`; then
    echo shar: \"'template.txt'\" unpacked with wrong size!
fi
# end of 'template.txt'
fi
if test -f 'template.el' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'template.el'\"
else
echo shar: Extracting \"'template.el'\" \(13159 characters\)
sed "s/^X//" >'template.el' <<'END_OF_FILE'
X;;; Copyright (c) 1991 by Wayne Mesard.  May be redistributed under the terms
X;;; of the GNU Emacs General Public License.
X
X;;; 
X;;; TEMPLATE
X;;; 
X
X;;; COMMANDS
X;;    None.
X;;; KEY BINDINGS
X;;    Control-C x:	a more convenient binding for expand-abbrev
X;;; PUBLIC VARIABLES
X;;    auto-template-alist
X;;    template-prefix-char
X;;    template-pad-char
X;;; PUBLIC FUNCTIONS
X;;    add-templates
X;;    define-template-table     (a synonym for define-abbrev-table)
X;;    template-expand
X;;    template-indent
X;;    template-prompt
X;;    template-prompt-indent
X;;    template-function
X
X;;; HISTORY
X;;    1.5 wmesard - Apr 11, 1991: Changed time and date directives
X;;    1.4 wmesard - Feb 14, 1991: 
X;;         Added "template-function"
X;;         Rewrote insert-timestamp as a template-function and moved
X;;          to oracle-templates.el.
X;;         Changed some names (to abstract away the abbrev-ness of all this).
X;;    1.3 wmesard - Nov 12, 1990: Improved "add-templates"
X;;    1.2 wmesard - Oct 17, 1990: Added "add-templates"
X;;    1.1 wmesard - Oct 15, 1990:
X;;         Added auto-template-facility
X;;         Added ~>> and ~>@ recurse facility
X;;         Changed ~u2 to ~uN
X;;	   Added "dont-bind-my-keys".  If this is set to non-nil before this
X;;	    file is loaded, then the key-bindings won't be performed.
X;;    1.0 wmesard - Jul 31, 1990: Created.
X
X;;; BUGS
X;;   If a template doesn't contain ~@ and ends in a substution, the cursor
X;;   will be left in the middle of the template instead of the end.
X;;   E.g.:   "Today is ~dw" => "Today is Wed" with the cursor on
X;;           the "W" in "Wed".
X;;   Workaround: Tack ~@ on the end of the template.
X
X;;; AUTHOR
X;;    Wayne Mesard, WMesard@Oracle.com
X
X;;; 
X;;; KEY BINDINGS
X;;; 
X
X(if (not (and (boundp 'dont-bind-my-keys) dont-bind-my-keys))
X    (global-set-key "\C-cx" 'expand-abbrev) 	; Easier to remember than C-x '
X  )
X
X;;; 
X;;; PARAMETERS
X;;; 
X
X
X(defvar auto-template-alist nil
X  "An alist of filename patterns and corresponding template names.
XEach element looks like (REGEXP . TEMPLATE-SYMBOL).
XVisiting a new file whose name matches REGEXP causes the template to
Xbe inserted into the buffer.
X
XThis facility is a functional super-duper-set of autoinsert.el.")
X
X(defconst template-prefix-char "~"
X  "The character searched for by template-expand-region when looking for text
Xto modify.  The value of this variable must be a string containting a single
Xcharacter.")
X
X(defconst template-pad-char ?0
X  "*By default, pad with this char for ~dM, ~dD, ~tH and ~tE.  Pad char
Xcan be changed on a per-template basis via the ~p directive.")
X
X
X;;; 
X;;; FUNCTIONS
X;;; 
X
X
X;; Allow tables to be extended rather than redefined.
X;;
X;; Example of use:
X;;  (add-templates 'c-mode-abbrev-table
X;;    '(("def" "#define")
X;;      ("day" "today is ~dn" template-expand)
X;;      ))
X
X(defun add-templates (tabname definitions)
X  "Just like define-abbrev-table, except existing abbrevs are not destroyed.
XArgs are the same too: TABNAME is a symbol, DEFINITIONS is a list of elements
Xof the form (NAME EXPANSION HOOK USECOUNT)."
X  (while definitions
X    (apply 'define-abbrev (symbol-value tabname)
X	   (car definitions))
X    (setq definitions (cdr definitions))
X    ))
X
X(defmacro define-template-table (tabname definitions)
X  "A synonym for define-abbrev-table.  See that function for details; but
Xwe recommend that you use ADD-TEMPLATES instead."
X  (list 'define-abbrev-table tabname definitions))
X
X;; 
X;; Auto templates
X;; 
X
X(setq find-file-hooks
X      (cons 'auto-template find-file-hooks))
X
X(defun auto-template ()
X  (if (and (not buffer-read-only)
X	   (zerop (buffer-size)))
X      (let ((alist auto-template-alist)
X	    (fn (file-name-sans-versions buffer-file-name))
X	    (done nil))
X	(while (and (not done) alist)
X	  (if (and (string-match (car (car alist)) fn)
X		   (abbrev-symbol (symbol-name (cdr (car alist)))))
X	      (progn
X		(insert (symbol-name (cdr (car alist))))
X		(expand-abbrev)
X		(setq done t)
X		(set-buffer-modified-p nil)
X		(message "New file. Inserted template: %s"
X			 (symbol-name (cdr (car alist))))
X		))
X	  (setq alist (cdr alist))
X	  ))
X    ))
X
X
X;; This could--and maybe should--be a macro -wsm2/14/91.
X
X(defun template-function (TEM1 &optional TEM2 FUNCNAME)
X  "In true Lisp fashion, this is a function building function.
XIt generates a function that inserts and expands a template, TEM1.  If optional 
Xsecond arg TEM2 is specified, then the generated function will also insert and
Xexpand TEM2 when preceded by \\[universal-argument].  If optional third arg FUNCNAME, a symbol,
Xis specified, then a real live function is generated suitable for use with
X\\[describe-function], \\[execute-extended-command], etc.
X
XTEMPLATE-FUNCTION is intended to bind templates to keys.  E.g.:
X (global-set-key \"\\C-ct\" 
X                 (template-function \"dstamp\" \"dtstamp\" 'insert-timestamp)))
X (define-key c-mode-map \"\\C-cf\" (template-function \"fordown\" \"forup\"))"
X  (let* ((docdef 
X	  (if FUNCNAME
X	      (apply 
X	       (function concat)
X	       "Insert and expand the template named \"" TEM1 "\"."
X	       (if TEM2
X		   (list "\nWith a prefix arg, use \"" TEM2 "\" instead.")))
X	    ))
X	 (fundef 
X	  (if TEM2
X	      (list 'lambda '(arg) docdef '(interactive "P")
X		    '(abbrev-prefix-mark) 
X		    (list 'insert (list 'if 'arg TEM2 TEM1))
X		    '(let ((executing-macro t)) (expand-abbrev)))
X	    (list 'lambda () docdef '(interactive)
X		  '(abbrev-prefix-mark) (list 'insert TEM1)
X		  '(let ((executing-macro t)) (expand-abbrev))
X		  )))
X	 )
X    (if FUNCNAME
X	(progn
X	  (fset FUNCNAME fundef)
X	  FUNCNAME)
X      fundef)))
X
X
X(defun template-prompt-indent (&rest prompts)
X  (template-prompt-1 t prompts))
X
X(defun template-prompt (&rest prompts)
X  (template-prompt-1 nil prompts))
X
X;; This is over-complicated in order to prevent the user from seeing the
X;; template before template-indent gets called.
X;; The screen is redrawn when the prompt appears in the minibuffer.
X;; So we actually undo the expansion, and then redo it after the
X;; prompting is complete.
X
X(defun template-prompt-1 (indentP prompts)
X  (let ((last-text last-abbrev-text))
X    (unexpand-abbrev)
X    (let ((strs (mapcar 'read-string prompts)))
X      (delete-backward-char (length last-text))
X      (insert (abbrev-expansion last-text))
X      (if indentP
X	  (template-indent strs)
X	(template-expand-region last-abbrev-location (point) strs)
X	))
X    ))
X
X
X(defun template-indent (&optional strs)
X  (let* ((endpt (point-marker))
X	 (boln (save-excursion
X		 (goto-char last-abbrev-location)
X		 (beginning-of-line)
X		 (point))))
X    (template-expand-region last-abbrev-location endpt strs)
X    ;; Use boln instead of last-abbrev-location to make sure that the first
X    ;; line gets indented first.  (This would burn "case" abbrev.) -wsm7/15/90.
X    (indent-region boln endpt nil)
X    ;; The next call is just to be sure point does the right thing.  Without it
X    ;; Inserting this:     would leave point here:     instead of here:
X    ;;
X    ;;      {                         {                        {
X    ;;                                X                          X
X    ;;      }                         }                        }
X    (funcall indent-line-function)
X    ))
X
X
X(defun template-expand ()
X  (template-expand-region last-abbrev-location (point))
X  )
X
X(defun template-expand-region (start end &optional replacement-strings)
X  "The following replacements are made in the text between START and END:
X
XThis:  Is replaced by:
X----   --------------
X ~dy: year (``91'')
X ~dY: year (``1991'')
X ~dm: month (``apr'')
X ~dn: month, numeric (``9'', ``12'')
X ~dN: month, numeric (``09'', ``12'')
X ~dd: date (``1'', ``31'')
X ~dD: date (``01'', ``31'')
X ~dw: day of week (``tue'')
X ~ta: ``am'' or ``pm''
X ~th: hour, 12hr system (``2'', ``11'')
X ~tH: hour, 12hr system (``02'', ``11'')
X ~te: hour, 24hr system (``2'', ``23'')
X ~tE: hour, 24hr system (``02'', ``23'')
X ~tm: minutes (``09'', ``59'')
X ~ts: seconds (``09'', ``59'')
X ~ui: user id
X ~uN: the first N letters of the user id (where N is a single digit)
X ~un: user name
X ~fn: filename of the current buffer
X ~fd: directory of the current buffer
X ~fp: filename prefix (i.e., up to the last period)
X ~fe: filename extension (i.e., after the last period)
X ~sN: the Nth user-specified string (where N is a single digit).
X      (See documentation on the function TEMPLATE-PROMPT for details.)
X ~~:  the template prefix char (``~'')
X ~@:  indicates that the cursor should be placed here when done
X ~>>: indicates that the following word may be a template name and it should
X      be recursively expanded
X ~>@: same as ``~>>''; in addition the cursor will be left where the
X      recursive template puts it. (Normally, ``~>>'' ignores ``~@''s in the
X      recursive template.)
X ~pC: use C to pad single-digit numbers (where C is any character).
X      (See documentation on the variable TEMPLATE-PAD-CHAR for details.)
X
XIf the conversion command is uppercase or capitalized, then the replacement 
Xtext will be uppercase or capitalized, respectively."
X
X  (let ((interactive-text nil)
X	(endm (set-marker (make-marker) end))
X	(point-here (point-marker))
X	(case-fold-search t)		; Ignore case of the conversion chars
X	(template-pad-char template-pad-char)
X	(ts nil)
X	(fn nil))
X    (goto-char start)
X    (while (and (< (point) endm)
X		(search-forward template-prefix-char endm t nil))
X      (let* ((token (following-char))
X	     (modifier (char-after (1+ (point))))
X	     (token-len 2)
X	     (replacement
X	      (cond ((char-equal token ?d)           ; DATE
X		     (if (null ts)
X			 (setq ts (current-time-string)))
X		     (cond ((= modifier ?y) ; YY
X			    (substring ts 22))
X			   ((= modifier ?Y) ; YYYY
X			    (substring ts 20))
X			   ((char-equal modifier ?n) ; Number of month
X			    (template-maybe-pad (= modifier ?N)
X			     (1+ (/ (string-match 
X				     (substring ts 4 7)
X				     "JanFebMarAprMayJunJulAugSepOctNovDec")
X				    3))))
X			   ((char-equal modifier ?m) ; MONth
X			    (downcase (substring ts 4 7)))
X			   ((char-equal modifier ?d) ; Date
X			    (template-maybe-pad (= modifier ?D)
X			     (string-to-int (substring ts 8 10))))
X			   ((char-equal modifier ?w) ; day of Week
X			    (downcase (substring ts 0 3)))
X			   ))
X		    ((char-equal token ?t)	     ; TIME
X		     (if (null ts)
X			 (setq ts (current-time-string)))
X		     (cond ((char-equal modifier ?a) ; am/pm 
X			    (if (< (string-to-int (substring ts 11 13)) 12)
X				"am"
X			      "pm"))
X			   ((char-equal modifier ?e) ; hours 24hr clock
X			    (template-maybe-pad (= modifier ?E)
X			     (string-to-int (substring ts 11 13))))
X			   ((char-equal modifier ?h) ; hours 12hr clock
X			    (let* ((r (string-to-int (substring ts 11 13)))
X				   (h (if (zerop (% r 12)) 12 (% r 12))))
X			      (template-maybe-pad (= modifier ?H) h)
X			      ))
X			   ((char-equal modifier ?m) ; minutes
X			    (substring ts 14 16))
X			   ((char-equal modifier ?s) ; seconds
X			    (substring ts 17 19))
X			   ))
X		    ((char-equal token ?u)           ; USER
X		     (cond ((char-equal modifier ?i) ; User login name
X			    (user-login-name))
X			   ((char-equal modifier ?n) ; User full name
X			    (downcase (user-full-name)))
X			   ((and (> modifier ?0)     ; 1st N chars of userid
X				 (<= modifier ?9))
X			    (substring (user-login-name) 0 (- modifier ?0)))
X			   ))
X		    ((char-equal token ?f)	     ; FILE
X		     (if (null fn)
X			 (setq fn (file-name-sans-versions (buffer-name))))
X		     (cond ((char-equal modifier ?d) ; Path and file name
X			    (if (buffer-file-name)
X				(file-name-directory (buffer-file-name))
X			      ""))
X			   ((char-equal modifier ?n) ; Buffer name
X			    fn)
X			   ((char-equal modifier ?p) ; Filename prefix
X			    (substring fn
X				       0
X				       (string-match "\\.[^.]*$" fn)))
X			   ((char-equal modifier ?e) ; file name extension
X			    (let ((i (string-match "\\.[^.]*$" fn)))
X			      (if i
X				(substring fn (1+ i))
X				"")))
X			   ))
X		    ((char-equal token ?s) 	      ; STRING
X		     (or (nth (- modifier ?0) replacement-strings)
X			 ""))
X		    ((char-equal token 
X				 (string-to-char template-prefix-char))
X		     (setq token-len 1)
X		     template-prefix-char)
X		    ((char-equal token ?@)	     ; LEAVE POINT HERE
X		     (setq token-len 1)
X		     (setq point-here (1- (point))) 
X		     "")
X		    ((char-equal token ?>)           ; RECURSE ON NEXT WORD
X		     (save-excursion
X		       (forward-word 1)
X		       (let ((executing-macro t))
X			 (expand-abbrev))
X		       (if (char-equal modifier ?@)
X			   (setq point-here (- (point) 3))
X			 ))
X		     "")
X		    ((char-equal token ?p)           ; CHANGE PADDING
X		     (setq template-pad-char modifier)
X		     "")
X		    )))
X	(if replacement
X	    (progn
X	      (delete-char token-len)
X	      (delete-backward-char 1)
X	      (insert 
X	       (if (= token (downcase token))
X		   replacement
X		 (if (= modifier (upcase modifier))
X		     (upcase replacement)
X		   (capitalize replacement))
X		 ))
X	      ))
X	))
X    (goto-char point-here)
X    ))
X
X
X(defun template-maybe-pad (padP num)
X  (if (and padP (< num 10))
X      (format "%c%d" template-pad-char num)
X    (concat num)
X    ))
X      
X;;; 
X;;; 
X;;; 
X
X(provide 'template)

END_OF_FILE
echo shar: NEWLINE appended to \"'template.el'\"
if test 13160 -ne `wc -c <'template.el'`; then
    echo shar: \"'template.el'\" unpacked with wrong size!
fi
# end of 'template.el'
fi
if test -f 'template-example.el' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'template-example.el'\"
else
echo shar: Extracting \"'template-example.el'\" \(2953 characters\)
sed "s/^X//" >'template-example.el' <<'END_OF_FILE'
X;;; TEMPLATE-EXAMPLE
X
X;; This file tries to load "template.elc".
X;; The "load-path" variable, as set in your Emacs init file, should include
X;; a directory containing "template.elc".
X;;
X;; Documentation and details in "template.txt" and "template-example.txt".
X
X
X(require 'template)
X
X;;
X;; INSERT-TIMESTAMP
X;;
X
X(if (not (and (boundp 'dont-bind-my-keys) dont-bind-my-keys))
X    (global-set-key "\C-ct"
X		    (template-function "dstamp" "dtstamp" 'insert-timestamp))
X  )
X
X(add-templates 'global-abbrev-table '(
X    ("dstamp"	"-~u2~dn/~dd/~dy." 			template-expand)
X    ("dtstamp"	"-~u2~dn/~dd/~dy;~th:~tm~ta~@"		template-expand)
X    ))
X
X;;
X;; Auto-insert these templates when a new file gets created
X;;
X
X(setq auto-template-alist '(("\\.c$" . masthead) ("\\.h$" . doth)))
X
X
X(add-templates 'c-mode-abbrev-table '(
X
X;;
X;; PREPROCESSOR TEMPLATES
X;;
X
X
X    ("i" 	"#include <~@.h>\n" 	template-indent)
X
X    ("d" 	"#define " nil)
X
X    ("ifd"	"#ifdef ~@
X
X#endif\n"		template-indent)
X
X
X    ("iifd"	"#ifdef ~S0
X~@
X#else  /* ~S0 */
X
X#endif /* ~S0 */\n" 	(lambda ()
X			  (template-prompt-indent 
X			   "#ifdef condition: ")))
X
X;;
X;; VANILLA C TEMPLATES
X;;
X
X
X    ("b" 	"{
X~@
X}"			template-indent)
X
X
X    ("s"	"switch (~@)
X{
X
X}"			template-indent)
X
X
X    ("c"	"case ~@:
X
Xbreak;"			template-indent)
X
X
X    ("if"	"if (~@)
X{
X
X}\n"			template-indent)
X
X
X    ("ife"	"if (~@)
X{
X
X}
Xelse
X{
X
X}\n"			template-indent)
X
X
X    ("for"	"for (~@; ; )
X{
X
X}\n"			template-indent)
X
X
X    ("fori"	"for (i = 0; i < ~@; ++i)
X{
X
X}\n"			template-indent)
X
X
X    ("ifor"	"for (~s0 = 0; ~s0 < ~@; ++~s0)
X{
X
X}\n"			(lambda ()
X			  (template-prompt-indent "Iteration variable: ")))
X
X    ("w"	"while (~@)
X{
X
X}\n"			template-indent)
X
X
X
X;;
X;; STANDARD COMMENT TEMPLATES
X;;
X
X
X    ("masthead"	"/* Filename: ~fn. Copyright (c) ~dY BIG Corp. 
X * May be redistributed under the terms of the GNU Emacs General Public License.
X */\n"
X					template-expand)
X
X    ("hifndef"	"#ifndef ~FP
X#define ~FP
X
X~@
X
X#endif /* ~FP */"		template-expand)
X
X
X    ("doth"	"~>>masthead~>@hifndef"	
X				template-expand)
X
X
X;;
X;; OTHER USEFUL COMMENT TEMPLATES
X;;
X
X
X    ("fd"	"/**
XNAME:    
X  ~@ - 
XPURPOSE:
X  
XARGS:    
X  > 
XRETURNS: 
X  < 
XNOTES:
X  
X**/\n"				template-expand)
X
X
X;;
X;; OTHER USEFUL TEMPLATES
X;;
X
X
X    ("im"	"if ((~@ = (~s0 *) ~>>malloc(sizeof(~s0))) == (~s0 *)0)\n"
X     				(lambda () 
X				  (template-prompt-indent
X				   "Datatype: ")))
X
X
X
X
X    ("imw"	"~@ = (~s0 *) ~>>malloc(sizeof(~s0));"
X				(lambda () 
X				  (template-prompt-indent
X				   "Datatype: ")))
X
X
X    ("imm"     "if ((~@ = (~s0 *)~>>malloc(~s1 * sizeof(~s0))) == (~s0 *)0)\n"
X				(lambda () 
X				  (template-prompt-indent 
X				   "Datatype: " "Quantity: ")))
X
X
X    ("global"	"
X#ifdef ~FP_DEFINE_GLOBALS
X  /*  */
X   ~@
X#else
X  extern 
X#endif /* ~FP_DEFINE_GLOBALS */"	template-expand)
X
X
X    ("main"	"main(argc, argv)
Xint argc;
Xchar **argv;
X{
X~@
X}\n"					template-indent)
X
X))
X
X
X;;; 
X;;; It's not a module, it's a FEATUREP.
X;;; 
X
X(provide 'template-example)

END_OF_FILE
echo shar: NEWLINE appended to \"'template-example.el'\"
if test 2954 -ne `wc -c <'template-example.el'`; then
    echo shar: \"'template-example.el'\" unpacked with wrong size!
fi
# end of 'template-example.el'
fi
if test -f 'template-example.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'template-example.txt'\"
else
echo shar: Extracting \"'template-example.txt'\" \(1926 characters\)
sed "s/^X//" >'template-example.txt' <<'END_OF_FILE'
XNAME:
X----
XTemplate-Example
X
XKEY BINDINGS:
X--- --------
XControl-C t: Inserts the first two chars of the user's id followed by
X             the date.  When prefaced by Control-U, also inserts the
X	     current time.
X
X
XAs with all my Emacs modifications, no key binding will be done if the
Xvariable DONT-BIND-MY-KEYS is set.  So if you don't want me messing with
Xyour keymap add the following line to the top of your .emacs file:
X
X  (setq dont-bind-my-keys t)
X
X[I like this convention and recommend that other Elisp coders adopt it.]
X
X
XAUTO INSERTS:
X---- -------
XNew ".c" files automatically get the "masthead" template inserted.
XNew ".h" files automatically get the "doth" template inserted.
X
XTEMPLATES:
X---------
XThese templates are active in C mode only:
X
X i:	   #Include <.h>
X d:	   #Define
X ifd:	   #IFDef/endif
X iifd:	   Interactive #IFDef/else/endif (prompts for macro name)
X b:	   Braces {}
X s:	   Switch statment
X c:	   Case clause
X if:	   IF statement
X ife:	   IF/Else statement
X for:	   FOR statment
X fori:	   FOR statement with variable named "i"
X ifor:	   Interactive FOR statment (prompts for variable name)
X w:	   While statment
X im:	   Interactive Malloc (prompts for datatype)
X imw:	   Interactive Malloc Wrong (unsafe version of "im")
X imm:	   Interactive Malloc Many (prompts for datatype and quantity)
X global:   standard ".h" file declaration/definition section
X main:	   MAIN function body
X fd:	   standard Function Description comment block
X
XThe following templates are invoked by the auto-template-alist and
Xgenerally not directly by the user:
X
X masthead: standard copyright notice
X hifndef:  standard ifndef wrapper for ".h" files
X doth:	   masthead + hifndef
X
XNOTES:
X-----
Xtemplate-example.el tries to load Template itself via the REQUIRE
Xfunction.  So, before loading template-example.el you should make sure
Xthat either: 1) template.el has already been loaded or 2) template.el is
Xon your load-path.

END_OF_FILE
echo shar: NEWLINE appended to \"'template-example.txt'\"
if test 1927 -ne `wc -c <'template-example.txt'`; then
    echo shar: \"'template-example.txt'\" unpacked with wrong size!
fi
# end of 'template-example.txt'
fi
echo shar: End of shell archive.
exit 0
--
Wayne();
WMesard@Oracle.COM