old-www/LDP/LG/issue39/marsden.html

375 lines
17 KiB
HTML

<!--startcut ==========================================================-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<title>EMACSulation LG #39</title>
<link rev="made" href="mailto:emarsden+emacs@laas.fr">
<meta name="keywords" content="emacs, template, expansions, dmacro">
<meta name="description" content="Templating mechanisms in Emacs: how
to use auto-inserted contents and skeletons."
<meta name="author" content="Eric Marsden">
<meta name="generator" content="Emacs">
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!--endcut ============================================================-->
<H4>
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">EMACSulation</font></H1>
<H4>By <a href="mailto:emarsden@mail.dotcom.fr">Eric Marsden</a></H4>
</center>
<P> <HR> <P>
<blockquote><small>
This column is devoted to making the best use of Emacs, text editor
extraordinaire. Each issue I plan to present an Emacs extension
which can improve your productivity, make the sun shine more brightly
and the grass greener.
</small></blockquote>
<h1>Templating</h1>
<p> Documents often conform to a boilerplate: a regular structure which is
boring to type in for each document. Most wordprocessors recognise this
and allow you to create templates for business letters, technical
reports, memos etc. Emacs can do one better than these static
&quot;skeletons&quot;, since its templating mechanism allows you to
insert dynamically generated text, according to the file's name, your
login, the date, or the results of a shell command.
<p> The Emacs auto-insertion mechanism allows you to set up boilerplates
which will be instanciated upon file creation, based on the new file's
name or mode. For example, when you create a file called
<tt>lsys.h</tt>, it will ask you <em>Perform C / C++ header
auto-insertion?</em>, and if you say yes might insert something like
</p>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
<font color="#ff0000">
/**********************************************************************
* lsys.h
*
* Eric Marsden &lt;emarsden@mail.dotcom.fr&gt;
* Time-stamp: &lt;&gt;
**********************************************************************/</font>
#<font color="#5f9ea0">ifndef</font> <font color="#b8860b">_LSYS_H_</font>
#<font color="#5f9ea0">define</font> <font color="#b8860b">_LSYS_H_</font>
#<font color="#5f9ea0">endif</font> <font color="#ff0000">/* _LSYS_H_ */</font>
</pre>
</td></tr></table>
<p> Note that <tt>#ifdefs</tt> have been generated to protect against
multiple inclusions of the header. You might want to add additional
elements such as your company's copyright blabber, skeletal revision
history comments, or an RCS version $Id. The auto-inserted content
depends on the major mode: upon creation of a file called
<tt>lsys.sgml</tt> the auto-inserted text might be </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
&lt;<font color="#4682b4">!DOCTYPE</font> ARTICLE PUBLIC <font color="#a0522d">&quot;-//Davenport//DTD DocBook V3.0//EN&quot;</font> [
]&gt;
&lt;<font color="#0000cd">article</font>&gt;
&lt;<font color="#0000cd">artheader</font>&gt;
&lt;<font color="#0000cd">date</font>&gt;1999-03-01&lt;<font color="#0000cd">/date</font>&gt;
&lt;<font color="#0000cd">title</font>&gt; &lt;<font color="#0000cd">/title</font>&gt;
&lt;<font color="#0000cd">subtitle</font>&gt; &lt;<font color="#0000cd">/subtitle</font>&gt;
&lt;<font color="#0000cd">author</font>&gt;
&lt;<font color="#0000cd">firstname</font>&gt;Eric&lt;<font color="#0000cd">/firstname</font>&gt;
&lt;<font color="#0000cd">surname</font>&gt;Marsden&lt;<font color="#0000cd">/surname</font>&gt;
&lt;<font color="#0000cd">affiliation</font>&gt;&lt;<font color="#0000cd">orgname</font>&gt;CULTe&lt;<font color="#0000cd">/orgname</font>&gt;&lt;<font color="#0000cd">/affiliation</font>&gt;
&lt;<font color="#0000cd">/author</font>&gt;
&lt;<font color="#0000cd">authorinitials</font>&gt;ecm&lt;<font color="#0000cd">/authorinitials</font>&gt;
&lt;<font color="#0000cd">abstract</font>&gt;
&lt;<font color="#0000cd">para</font>&gt;
&lt;<font color="#0000cd">/para</font>&gt;
&lt;<font color="#0000cd">/abstract</font>&gt;
&lt;<font color="#0000cd">/artheader</font>&gt;
&lt;<font color="#0000cd">sect1</font>&gt;&lt;<font color="#0000cd">title</font>&gt; &lt;<font color="#0000cd">/title</font>&gt;
&lt;<font color="#0000cd">para</font>&gt;
&lt;<font color="#0000cd">/para</font>&gt;
&lt;<font color="#0000cd">/sect1</font>&gt;
&lt;<font color="#0000cd">/article</font>&gt;
</pre>
</td></tr></table>
<p> [These font-enhanced program listings were generated by Hrvoje Niksic's
excellent <a
href="http://jagor.srce.hr/~hniksic/htmlize.el">htmlize</a> package,
which generates HTML renderings of font-locked buffers.] Auto-insertion
can be activated by saying </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre>
(add-hook 'find-file-hooks 'auto-insert)
(setq auto-insert-directory (expand-file-name <font color="#a0522d">&quot;~/.autoinsert/&quot;</font>))
</pre>
</td></tr></table>
<p> The <strong>autoinsert package</strong> (written by Charlie Martin) is
distributed with default templates for several modes. There are two
ways of customizing the auto-inserted contents: the simplest (which
doesn't require any knowledge of elisp) involves placing files in
the directory <tt>~/.autoinsert/</tt> and registering them with
autoinsert: </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre>
(define-auto-insert &quot;\\.html\\'&quot; "autoinsert.html")
</pre>
</td></tr></table>
<p> The <tt>&quot;\\.html\\'&quot;</tt> is a regular expression which
matches filenames ending in <tt>.html</tt> (note the use of
<tt>\\'</tt> to match the end of a string, rather than <tt>$</tt> for
the end of a line, since filenames are allowed to contain newline
characters). This should lead to the contents of the file
<tt>~/.autoinsert/autoinsert.html</tt> being inserted automatically
when you create a file whose name ends in <tt>.html</tt>. This method
only allows insertion of static content. Insertion of dynamically
generated content is also possible if you know some Emacs Lisp; here is
some code which creates skeleton C or C++ headers, as in the first
example in this article: </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
<font color="#ff0000">;; autoinsert.el</font>
(define-auto-insert
(cons <font color="#a0522d">&quot;\\.\\([Hh]\\)\\'&quot;</font> <font color="#a0522d">&quot;My C / C++ header&quot;</font>)
'(nil
<font color="#a0522d">&quot;/*&quot;</font> (make-string 69 ?*) <font color="#a0522d">&quot;\n&quot;</font>
<font color="#a0522d">&quot; * &quot;</font> (file-name-nondirectory buffer-file-name) <font color="#a0522d">&quot;\n&quot;</font>
<font color="#a0522d">&quot; *\n&quot;</font>
<font color="#a0522d">&quot; * &quot;</font> (user-full-name) <font color="#a0522d">&quot; &lt;&quot;</font> user-mail-address <font color="#a0522d">&quot;&gt;\n&quot;</font>
<font color="#a0522d">&quot; * Time-stamp: &lt;&gt;\n&quot;</font>
<font color="#a0522d">&quot; *&quot;</font> (make-string 69 ?*) <font color="#a0522d">&quot;*/\n&quot;</font>
(<font color="#4682b4">let*</font> ((noext (substring buffer-file-name 0 (match-beginning 0)))
(nopath (file-name-nondirectory noext))
(ident (concat <font color="#a0522d">&quot;_&quot;</font> (upcase nopath) <font color="#a0522d">&quot;_H_&quot;</font>)))
(concat <font color="#a0522d">&quot;#ifndef &quot;</font> ident <font color="#a0522d">&quot;\n&quot;</font>
<font color="#a0522d">&quot;#define &quot;</font> ident <font color="#a0522d">&quot;\n\n\n&quot;</font>
<font color="#a0522d">&quot;\n\n#endif /* &quot;</font> ident <font color="#a0522d">&quot; */\n&quot;</font>))))
</pre>
</td></tr></table>
<p> How does the autoinsertion work? Each time you open a file in Emacs, it
runs a special hook called <tt>find-file-hooks</tt>. This is where
things such as enabling syntactic highlighting or checking whether a
file is under a version control system (RCS or CVS) occur. The
<tt>add-hook</tt> line above latches the autoinsertion onto this hook.
<h2>Dmacro</h2>
<p> The <strong>Dynamic Macro</strong> package by Wayne Mesard allows you
to insert structured text at any time, not only at document creation
time. dmacro provides facilities such as prompting the user for input,
inserting the contents of a file or the output from a shell command,
and positioning the cursor or the mark after the insertion. One
particularly nice feature is the ability to indent autoinserted
contents according to the current mode. It could be used as a way of
enforcing (well, encouraging developers to adhere to) coding standards,
and can reduce development time by preventing typos in repetitive text.
dmacro is not distributed with Emacs; you will have to <a
href="ftp://ftp.sgi.com/other/dmacro/dmacro.tar.gz">download</a> and
install it (which is just a matter of saying <emph>make</emph>). It can
be activated by saying in your <tt>~/.emacs</tt> (where the
<tt>.dm</tt> file contains your personal macros; see below for some
examples): </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
(require 'dmacro) <font color="#ff0000">; dynamic macros</font>
(dmacro-load <font color="#a0522d">&quot;~/elisp/ecm.dm&quot;</font>)
</pre>
</td></tr></table>
<p> The dmacro package is very well documented, so I will only provide a
few motivating examples. Here is one which will insert the skeleton of
a <tt>for</tt> block in C-mode (macros can either be global, or
specific to a certain major mode): </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
# file ~/elisp/ecm.dm
# ================================== Stuff for C-derived modes =======
# MODE: c-mode c++-mode java-mode
ifor indent interactive for statement (prompts for variable name)
for (~(prompt var "Variable: ") = 0; ~prompt &lt; ~@; ~prompt++)
{
~mark
}
#
</pre>
</td></tr></table>
<p> You activate the macro by typing <tt>C-c d ifor</tt> (with tab
completion on the macro's name). It should prompt you for the name of
the variable:
<p> <img src="./gx/marsden/dmacro1.gif">
<p> and the result should look like <a href="./gx/marsden/dmacro2.gif">this</a>. The
next example demonstrates how to insert a timestamp of the form
<tt>-ecm1999-02-29</tt> in the current buffer (pet peeve: given the
value of a uniform, standardized external representation for dates, I
make a point of systematically using the <a
href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">ISO 8601</a>
format). You invoke this macro by typing <tt>C-c d dstamp</tt>. The
corresponding code (which also demonstrates the use of an alias to
factorize out commonly used definitions) is: </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
# ALIAS: iso-date (eval (format-time-string "%Y-%m-%d"))
# ================================= Stuff for all modes ============
# MODE: nil
dstamp expand user id and date
-~user-id~(iso-date)
#
</pre>
</td></tr></table>
<h2>Related packages</h2>
<p> There are several other packages which provide similar functionality to
dmacro. <tt>tempo.el</tt> (included with both GNU Emacs and XEmacs) was
originally written as an adjunct to html-helper-mode, providing
facilities for inserting balanced bits of HTML markup, but can be used
for other purposes. It is also possible to extend the standard abbrev
mechanism to insert dynamically generated text by hacking the
abbrev-mode-hook, as explained in the <a
href="http://www.dejanews.com/getdoc.xp?AN=340841733">following
message</a> posted anonymously to <a
href="news:gnu.emacs.help">gnu.emacs.help</a>. Finally, there is <a
href="http://www.fmi.uni-passau.de/~wedler/template/">template.el</a>
by <a href="mailto:wedler!@!fmi.uni-passau.de">Christoph Wedler</a>
which seems very comprehensive.
<h2>Feedback</h2>
<p> The January 1999 EMACSulation on abbreviation mechanisms had a
bootstrap problem: I indicated how to create abbreviations and how to
have them read in automatically when Emacs starts up, but the
instructions that I gave weren't sufficient to get Emacs to save
abbrevs automatically when quitting. Thanks to Nat Makarevitch and Dave
Bennet for pointing this out. Here is a revised version of the code
that I proposed (the last line is what was missing): </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
<font color="red">
;; if there is an abbrev file, read it in</font>
(if (file-exists-p abbrev-file-name)
(read-abbrev-file))
(setq-default save-abbrevs t)
</pre>
</td></tr></table>
<p> A few European readers also asked about abbreviations containing 8bit,
non-ASCII characters. In its default state Emacs won't take them into
account, since it assumes that characters with the 8th bit set are non
word-constituent. To modify this (to take into account accented
characters in the iso-8859-1 character map, for example) you need to do
something like </p>
<table border="0" bgColor="#E0E0E0" width="100%">
<tr><td>
<pre class="programlisting">
(set-language-environment 'Latin-1) <font color="red">; GNU Emacs 20.x</font>
(require 'iso-syntax) <font color="red">; GNU Emacs 19.x</font>
</pre>
</td></tr></table>
<p> (there are major differences between the way that GNU Emacs 19.x and
20.x handle different character encodings; recent versions can handle
multibyte characters, required for representing asian languages. Rather
than using <a href="http://www.unicode.org/">Unicode</a>, Emacs uses
adjustable width characters. For XEmacs this <a
href="http://www.etl.go.jp/~mule/MulePage.html">MULE</a> (MULtilingual
enhancements for Emacs) support is a compile-time option in recent
versions.)
<h2>Next time ...</h2>
<p> Next month we'll look at spell checking with Emacs. Thanks to <a
href="mailto:arnu!@!laas.fr">Jean-Christophe Arnu</a> for commenting on
a draft of this article. Don't hesitate to contact me with comments,
corrections or suggestions (what's <em>your</em> favorite
couldn't-do-without Emacs extension package?). <code>C-u 1000 M-x
hail-emacs</code> !
<p> <strong>PS</strong>: Emacs isn't in any way limited to Linux, since
implementations exist for many other operating systems (and some
systems which only halfway operate). However, as one of the leading
bits of free software, one of the most powerful, complex and
customizable, I feel it has its place in the <i>Linux Gazette</i>.
<!--===================================================================-->
<P> <HR> <P>
<A HREF="../issue25/marsden.html">EMACSulation #1: Handling Compressed Files, February 1998</A><BR>
<A HREF="../issue26/marsden.html">EMACSulation #2: Internet Ready, March 1998</A><BR>
<A HREF="../issue27/marsden.html">EMACSulation #3: Ediff, April 1998</A><BR>
<A HREF="../issue29/marsden.html">EMACSulation #4: Emacs as a Server, June 1998</A><BR>
<A HREF="../issue31/marsden.html">EMACSulation #5: Customizing Emacs, August 1998</A><BR>
<A HREF="../issue36/marsden.html">EMACSulation #6: Saving Time, January 1999</A>
<!--===================================================================-->
<P> <hr> <P>
<center><H5>Copyright &copy; 1999, Eric Marsden <BR>
Published in Issue 39 of <i>Linux Gazette</i>, April 1999</H5></center>
<!--===================================================================-->
<P> <hr> <P>
<A HREF="./index.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif"
ALT="[ TABLE OF CONTENTS ]"></A>
<A HREF="../index.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
ALT="[ FRONT PAGE ]"></A>
<A HREF="./sevenich.html"><IMG SRC="../gx/back2.gif"
ALT=" Back "></A>
<A HREF="./pollman.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
<P> <hr> <P>
<!--startcut ==========================================================-->
</BODY>
</HTML>
<!--endcut ============================================================-->