hgbook

view fr/ch11-template.xml @ 981:64393e8da2ff

Some errors corrected in fr/ch00-preface.xml
author Frédéric Bouquet <youshe.jaalon@gmail.com>
date Tue Sep 08 15:30:26 2009 +0200 (2009-09-08)
parents
children 6f8c48362758
line source
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
3 <chapter>
4 <title>Customising the output of Mercurial</title>
5 <para>\label{chap:template}</para>
7 <para>Mercurial provides a powerful mechanism to let you control how it
8 displays information. The mechanism is based on templates. You can
9 use templates to generate specific output for a single command, or to
10 customise the entire appearance of the built-in web interface.</para>
12 <sect1>
13 <title>Using precanned output styles</title>
14 <para>\label{sec:style}</para>
16 <para>Packaged with Mercurial are some output styles that you can use
17 immediately. A style is simply a precanned template that someone
18 wrote and installed somewhere that Mercurial can find.</para>
20 <para>Before we take a look at Mercurial's bundled styles, let's review its
21 normal output.</para>
23 <para><!-- &interaction.template.simple.normal; --></para>
25 <para>This is somewhat informative, but it takes up a lot of space&emdash;five
26 lines of output per changeset. The <literal>compact</literal> style reduces
27 this to three lines, presented in a sparse manner.</para>
29 <para><!-- &interaction.template.simple.compact; --></para>
31 <para>The <literal>changelog</literal> style hints at the expressive power of
32 Mercurial's templating engine. This style attempts to follow the GNU
33 Project's changelog guidelines<citation>web:changelog</citation>.
34 </para>
36 <para><!-- &interaction.template.simple.changelog; -->
37 </para>
39 <para>You will not be shocked to learn that Mercurial's default output style
40 is named <literal>default</literal>.
41 </para>
43 <sect2>
44 <title>Setting a default style</title>
46 <para>You can modify the output style that Mercurial will use for every
47 command by editing your <filename role="special"> /.hgrc</filename>\ file, naming the style you would
48 prefer to use.
49 </para>
51 <programlisting>
52 <para> [ui]
53 style = compact
54 </para>
55 </programlisting>
57 <para>If you write a style of your own, you can use it by either providing
58 the path to your style file, or copying your style file into a
59 location where Mercurial can find it (typically the <literal>templates</literal>
60 subdirectory of your Mercurial install directory).
61 </para>
63 </sect2>
64 </sect1>
65 <sect1>
66 <title>Commands that support styles and templates</title>
68 <para>All of Mercurial's <quote><literal>log</literal>-like</quote> commands let you use styles
69 and templates: <command role="hg-cmd">hg incoming</command>, <command role="hg-cmd">hg log</command>, <command role="hg-cmd">hg outgoing</command>, and
70 <command role="hg-cmd">hg tip</command>.
71 </para>
73 <para>As I write this manual, these are so far the only commands that
74 support styles and templates. Since these are the most important
75 commands that need customisable output, there has been little pressure
76 from the Mercurial user community to add style and template support to
77 other commands.
78 </para>
80 </sect1>
81 <sect1>
82 <title>The basics of templating</title>
84 <para>At its simplest, a Mercurial template is a piece of text. Some of the
85 text never changes, while other parts are <emphasis>expanded</emphasis>, or replaced
86 with new text, when necessary.
87 </para>
89 <para>Before we continue, let's look again at a simple example of
90 Mercurial's normal output.
91 </para>
93 <para><!-- &interaction.template.simple.normal; -->
94 </para>
96 <para>Now, let's run the same command, but using a template to change its
97 output.
98 </para>
100 <para><!-- &interaction.template.simple.simplest; -->
101 </para>
103 <para>The example above illustrates the simplest possible template; it's
104 just a piece of static text, printed once for each changeset. The
105 <option role="hg-opt-log">--template</option> option to the <command role="hg-cmd">hg log</command> command tells
106 Mercurial to use the given text as the template when printing each
107 changeset.
108 </para>
110 <para>Notice that the template string above ends with the text
111 <quote><literal>\n</literal></quote>. This is an <emphasis>escape sequence</emphasis>, telling Mercurial
112 to print a newline at the end of each template item. If you omit this
113 newline, Mercurial will run each piece of output together. See
114 section <xref linkend="sec:template:escape"/> for more details of escape sequences.
115 </para>
117 <para>A template that prints a fixed string of text all the time isn't very
118 useful; let's try something a bit more complex.
119 </para>
121 <para><!-- &interaction.template.simple.simplesub; -->
122 </para>
124 <para>As you can see, the string <quote><literal>{desc}</literal></quote> in the template has been
125 replaced in the output with the description of each changeset. Every
126 time Mercurial finds text enclosed in curly braces (<quote><literal>{</literal></quote>
127 and <quote>\texttt{}}</quote>), it will try to replace the braces and text with
128 the expansion of whatever is inside. To print a literal curly brace,
129 you must escape it, as described in section <xref linkend="sec:template:escape"/>.
130 </para>
132 </sect1>
133 <sect1>
134 <title>Common template keywords</title>
135 <para>\label{sec:template:keyword}
136 </para>
138 <para>You can start writing simple templates immediately using the keywords
139 below.
140 </para>
142 <itemizedlist>
143 <listitem><para><literal role="template-keyword">author</literal>: String. The unmodified author of the changeset.
144 </para>
145 </listitem>
146 <listitem><para><literal role="template-keyword">branches</literal>: String. The name of the branch on which
147 the changeset was committed. Will be empty if the branch name was
148 <literal>default</literal>.
149 </para>
150 </listitem>
151 <listitem><para><literal role="template-keyword">date</literal>: Date information. The date when the changeset
152 was committed. This is <emphasis>not</emphasis> human-readable; you must pass it
153 through a filter that will render it appropriately. See
154 section <xref linkend="sec:template:filter"/> for more information on filters.
155 The date is expressed as a pair of numbers. The first number is a
156 Unix UTC timestamp (seconds since January 1, 1970); the second is
157 the offset of the committer's timezone from UTC, in seconds.
158 </para>
159 </listitem>
160 <listitem><para><literal role="template-keyword">desc</literal>: String. The text of the changeset description.
161 </para>
162 </listitem>
163 <listitem><para><literal role="template-keyword">files</literal>: List of strings. All files modified, added, or
164 removed by this changeset.
165 </para>
166 </listitem>
167 <listitem><para><literal role="template-keyword">file_adds</literal>: List of strings. Files added by this
168 changeset.
169 </para>
170 </listitem>
171 <listitem><para><literal role="template-keyword">file_dels</literal>: List of strings. Files removed by this
172 changeset.
173 </para>
174 </listitem>
175 <listitem><para><literal role="template-keyword">node</literal>: String. The changeset identification hash, as a
176 40-character hexadecimal string.
177 </para>
178 </listitem>
179 <listitem><para><literal role="template-keyword">parents</literal>: List of strings. The parents of the
180 changeset.
181 </para>
182 </listitem>
183 <listitem><para><literal role="template-keyword">rev</literal>: Integer. The repository-local changeset revision
184 number.
185 </para>
186 </listitem>
187 <listitem><para><literal role="template-keyword">tags</literal>: List of strings. Any tags associated with the
188 changeset.
189 </para>
190 </listitem></itemizedlist>
192 <para>A few simple experiments will show us what to expect when we use these
193 keywords; you can see the results in
194 figure <xref linkend="fig:template:keywords"/>.
195 </para>
197 <informalfigure>
198 <para> <!-- &interaction.template.simple.keywords; -->
199 <caption><para>Template keywords in use</para></caption>
200 \label{fig:template:keywords}
201 </para>
202 </informalfigure>
204 <para>As we noted above, the date keyword does not produce human-readable
205 output, so we must treat it specially. This involves using a
206 <emphasis>filter</emphasis>, about which more in section <xref linkend="sec:template:filter"/>.
207 </para>
209 <para><!-- &interaction.template.simple.datekeyword; -->
210 </para>
212 </sect1>
213 <sect1>
214 <title>Escape sequences</title>
215 <para>\label{sec:template:escape}
216 </para>
218 <para>Mercurial's templating engine recognises the most commonly used escape
219 sequences in strings. When it sees a backslash (<quote><literal>\</literal></quote>)
220 character, it looks at the following character and substitutes the two
221 characters with a single replacement, as described below.
222 </para>
224 <itemizedlist>
225 <listitem><para><literal>\textbackslash\textbackslash</literal>: Backslash, <quote><literal>\</literal></quote>,
226 ASCII 134.
227 </para>
228 </listitem>
229 <listitem><para><literal>\textbackslash n</literal>: Newline, ASCII 12.
230 </para>
231 </listitem>
232 <listitem><para><literal>\textbackslash r</literal>: Carriage return, ASCII 15.
233 </para>
234 </listitem>
235 <listitem><para><literal>\textbackslash t</literal>: Tab, ASCII 11.
236 </para>
237 </listitem>
238 <listitem><para><literal>\textbackslash v</literal>: Vertical tab, ASCII 13.
239 </para>
240 </listitem>
241 <listitem><para><literal>\textbackslash {</literal>: Open curly brace, <quote><literal>{</literal></quote>, ASCII 173.
242 </para>
243 </listitem>
244 <listitem><para><literal>\textbackslash }</literal>: Close curly brace, <quote><literal>}</literal></quote>, ASCII 175.
245 </para>
246 </listitem></itemizedlist>
248 <para>As indicated above, if you want the expansion of a template to contain
249 a literal <quote><literal>\</literal></quote>, <quote><literal>{</literal></quote>, or <quote><literal>{</literal></quote> character, you
250 must escape it.
251 </para>
253 </sect1>
254 <sect1>
255 <title>Filtering keywords to change their results</title>
256 <para>\label{sec:template:filter}
257 </para>
259 <para>Some of the results of template expansion are not immediately easy to
260 use. Mercurial lets you specify an optional chain of <emphasis>filters</emphasis>
261 to modify the result of expanding a keyword. You have already seen a
262 common filter, <literal role="template-kw-filt-date">isodate</literal>, in action above, to make a
263 date readable.
264 </para>
266 <para>Below is a list of the most commonly used filters that Mercurial
267 supports. While some filters can be applied to any text, others can
268 only be used in specific circumstances. The name of each filter is
269 followed first by an indication of where it can be used, then a
270 description of its effect.
271 </para>
273 <itemizedlist>
274 <listitem><para><literal role="template-filter">addbreaks</literal>: Any text. Add an XHTML <quote><literal>&lt;br/&gt;</literal></quote>
275 tag before the end of every line except the last. For example,
276 <quote><literal>foo\nbar</literal></quote> becomes <quote><literal>foo&lt;br/&gt;\nbar</literal></quote>.
277 </para>
278 </listitem>
279 <listitem><para><literal role="template-kw-filt-date">age</literal>: <literal role="template-keyword">date</literal> keyword. Render the
280 age of the date, relative to the current time. Yields a string like
281 <quote><literal>10 minutes</literal></quote>.
282 </para>
283 </listitem>
284 <listitem><para><literal role="template-filter">basename</literal>: Any text, but most useful for the
285 <literal role="template-keyword">files</literal> keyword and its relatives. Treat the text as a
286 path, and return the basename. For example, <quote><literal>foo/bar/baz</literal></quote>
287 becomes <quote><literal>baz</literal></quote>.
288 </para>
289 </listitem>
290 <listitem><para><literal role="template-kw-filt-date">date</literal>: <literal role="template-keyword">date</literal> keyword. Render a date
291 in a similar format to the Unix <literal role="template-keyword">date</literal> command, but with
292 timezone included. Yields a string like
293 <quote><literal>Mon Sep 04 15:13:13 2006 -0700</literal></quote>.
294 </para>
295 </listitem>
296 <listitem><para><literal role="template-kw-filt-author">domain</literal>: Any text, but most useful for the
297 <literal role="template-keyword">author</literal> keyword. Finds the first string that looks like
298 an email address, and extract just the domain component. For
299 example, <quote><literal>Bryan O'Sullivan &lt;bos@serpentine.com&gt;</literal></quote> becomes
300 <quote><literal>serpentine.com</literal></quote>.
301 </para>
302 </listitem>
303 <listitem><para><literal role="template-kw-filt-author">email</literal>: Any text, but most useful for the
304 <literal role="template-keyword">author</literal> keyword. Extract the first string that looks like
305 an email address. For example,
306 <quote><literal>Bryan O'Sullivan &lt;bos@serpentine.com&gt;</literal></quote> becomes
307 <quote><literal>bos@serpentine.com</literal></quote>.
308 </para>
309 </listitem>
310 <listitem><para><literal role="template-filter">escape</literal>: Any text. Replace the special XML/XHTML
311 characters <quote><literal>&amp;</literal></quote>, <quote><literal>&lt;</literal></quote> and <quote><literal>&gt;</literal></quote> with
312 XML entities.
313 </para>
314 </listitem>
315 <listitem><para><literal role="template-filter">fill68</literal>: Any text. Wrap the text to fit in 68
316 columns. This is useful before you pass text through the
317 <literal role="template-filter">tabindent</literal> filter, and still want it to fit in an
318 80-column fixed-font window.
319 </para>
320 </listitem>
321 <listitem><para><literal role="template-filter">fill76</literal>: Any text. Wrap the text to fit in 76
322 columns.
323 </para>
324 </listitem>
325 <listitem><para><literal role="template-filter">firstline</literal>: Any text. Yield the first line of text,
326 without any trailing newlines.
327 </para>
328 </listitem>
329 <listitem><para><literal role="template-kw-filt-date">hgdate</literal>: <literal role="template-keyword">date</literal> keyword. Render the
330 date as a pair of readable numbers. Yields a string like
331 <quote><literal>1157407993 25200</literal></quote>.
332 </para>
333 </listitem>
334 <listitem><para><literal role="template-kw-filt-date">isodate</literal>: <literal role="template-keyword">date</literal> keyword. Render the
335 date as a text string in ISO 8601 format. Yields a string like
336 <quote><literal>2006-09-04 15:13:13 -0700</literal></quote>.
337 </para>
338 </listitem>
339 <listitem><para><literal role="template-filter">obfuscate</literal>: Any text, but most useful for the
340 <literal role="template-keyword">author</literal> keyword. Yield the input text rendered as a
341 sequence of XML entities. This helps to defeat some particularly
342 stupid screen-scraping email harvesting spambots.
343 </para>
344 </listitem>
345 <listitem><para><literal role="template-kw-filt-author">person</literal>: Any text, but most useful for the
346 <literal role="template-keyword">author</literal> keyword. Yield the text before an email address.
347 For example, <quote><literal>Bryan O'Sullivan &lt;bos@serpentine.com&gt;</literal></quote>
348 becomes <quote><literal>Bryan O'Sullivan</literal></quote>.
349 </para>
350 </listitem>
351 <listitem><para><literal role="template-kw-filt-date">rfc822date</literal>: <literal role="template-keyword">date</literal> keyword. Render a
352 date using the same format used in email headers. Yields a string
353 like <quote><literal>Mon, 04 Sep 2006 15:13:13 -0700</literal></quote>.
354 </para>
355 </listitem>
356 <listitem><para><literal role="template-kw-filt-node">short</literal>: Changeset hash. Yield the short form
357 of a changeset hash, i.e. a 12-character hexadecimal string.
358 </para>
359 </listitem>
360 <listitem><para><literal role="template-kw-filt-date">shortdate</literal>: <literal role="template-keyword">date</literal> keyword. Render
361 the year, month, and day of the date. Yields a string like
362 <quote><literal>2006-09-04</literal></quote>.
363 </para>
364 </listitem>
365 <listitem><para><literal role="template-filter">strip</literal>: Any text. Strip all leading and trailing
366 whitespace from the string.
367 </para>
368 </listitem>
369 <listitem><para><literal role="template-filter">tabindent</literal>: Any text. Yield the text, with every line
370 except the first starting with a tab character.
371 </para>
372 </listitem>
373 <listitem><para><literal role="template-filter">urlescape</literal>: Any text. Escape all characters that are
374 considered <quote>special</quote> by URL parsers. For example, <literal>foo bar</literal>
375 becomes <literal>foo%20bar</literal>.
376 </para>
377 </listitem>
378 <listitem><para><literal role="template-kw-filt-author">user</literal>: Any text, but most useful for the
379 <literal role="template-keyword">author</literal> keyword. Return the <quote>user</quote> portion of an email
380 address. For example,
381 <quote><literal>Bryan O'Sullivan &lt;bos@serpentine.com&gt;</literal></quote> becomes
382 <quote><literal>bos</literal></quote>.
383 </para>
384 </listitem></itemizedlist>
386 <informalfigure>
387 <para> <!-- &interaction.template.simple.manyfilters; -->
388 <caption><para>Template filters in action</para></caption>
389 \label{fig:template:filters}
390 </para>
391 </informalfigure>
393 <note>
394 <para> If you try to apply a filter to a piece of data that it cannot
395 process, Mercurial will fail and print a Python exception. For
396 example, trying to run the output of the <literal role="template-keyword">desc</literal> keyword
397 into the <literal role="template-kw-filt-date">isodate</literal> filter is not a good idea.
398 </para>
399 </note>
401 <sect2>
402 <title>Combining filters</title>
404 <para>It is easy to combine filters to yield output in the form you would
405 like. The following chain of filters tidies up a description, then
406 makes sure that it fits cleanly into 68 columns, then indents it by a
407 further 8 characters (at least on Unix-like systems, where a tab is
408 conventionally 8 characters wide).
409 </para>
411 <para><!-- &interaction.template.simple.combine; -->
412 </para>
414 <para>Note the use of <quote><literal>\t</literal></quote> (a tab character) in the template to
415 force the first line to be indented; this is necessary since
416 <literal role="template-keyword">tabindent</literal> indents all lines <emphasis>except</emphasis> the first.
417 </para>
419 <para>Keep in mind that the order of filters in a chain is significant. The
420 first filter is applied to the result of the keyword; the second to
421 the result of the first filter; and so on. For example, using
422 <literal>fill68|tabindent</literal> gives very different results from
423 <literal>tabindent|fill68</literal>.
424 </para>
427 </sect2>
428 </sect1>
429 <sect1>
430 <title>From templates to styles</title>
432 <para>A command line template provides a quick and simple way to format some
433 output. Templates can become verbose, though, and it's useful to be
434 able to give a template a name. A style file is a template with a
435 name, stored in a file.
436 </para>
438 <para>More than that, using a style file unlocks the power of Mercurial's
439 templating engine in ways that are not possible using the command line
440 <option role="hg-opt-log">--template</option> option.
441 </para>
443 <sect2>
444 <title>The simplest of style files</title>
446 <para>Our simple style file contains just one line:
447 </para>
449 <para><!-- &interaction.template.simple.rev; -->
450 </para>
452 <para>This tells Mercurial, <quote>if you're printing a changeset, use the text
453 on the right as the template</quote>.
454 </para>
456 </sect2>
457 <sect2>
458 <title>Style file syntax</title>
460 <para>The syntax rules for a style file are simple.
461 </para>
463 <itemizedlist>
464 <listitem><para>The file is processed one line at a time.
465 </para>
466 </listitem>
467 </para>
468 </listitem>
469 <listitem><para>Leading and trailing white space are ignored.
470 </para>
471 </listitem>
472 </para>
473 </listitem>
474 <listitem><para>Empty lines are skipped.
475 </para>
476 </listitem>
477 </para>
478 </listitem>
479 <listitem><para>If a line starts with either of the characters <quote><literal>#</literal></quote> or
480 <quote><literal>;</literal></quote>, the entire line is treated as a comment, and skipped
481 as if empty.
482 </para>
483 </listitem>
484 </para>
485 </listitem>
486 <listitem><para>A line starts with a keyword. This must start with an
487 alphabetic character or underscore, and can subsequently contain any
488 alphanumeric character or underscore. (In regexp notation, a
489 keyword must match <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)
490 </para>
491 </listitem>
492 </para>
493 </listitem>
494 <listitem><para>The next element must be an <quote><literal>=</literal></quote> character, which can
495 be preceded or followed by an arbitrary amount of white space.
496 </para>
497 </listitem>
498 </para>
499 </listitem>
500 <listitem><para>If the rest of the line starts and ends with matching quote
501 characters (either single or double quote), it is treated as a
502 template body.
503 </para>
504 </listitem>
505 </para>
506 </listitem>
507 <listitem><para>If the rest of the line <emphasis>does not</emphasis> start with a quote
508 character, it is treated as the name of a file; the contents of this
509 file will be read and used as a template body.
510 </para>
511 </listitem></itemizedlist>
513 </sect2>
514 </sect1>
515 <sect1>
516 <title>Style files by example</title>
518 <para>To illustrate how to write a style file, we will construct a few by
519 example. Rather than provide a complete style file and walk through
520 it, we'll mirror the usual process of developing a style file by
521 starting with something very simple, and walking through a series of
522 successively more complete examples.
523 </para>
525 <sect2>
526 <title>Identifying mistakes in style files</title>
528 <para>If Mercurial encounters a problem in a style file you are working on,
529 it prints a terse error message that, once you figure out what it
530 means, is actually quite useful.
531 </para>
533 <para><!-- &interaction.template.svnstyle.syntax.input; -->
534 </para>
536 <para>Notice that <filename>broken.style</filename> attempts to define a
537 <literal>changeset</literal> keyword, but forgets to give any content for it.
538 When instructed to use this style file, Mercurial promptly complains.
539 </para>
541 <para><!-- &interaction.template.svnstyle.syntax.error; -->
542 </para>
544 <para>This error message looks intimidating, but it is not too hard to
545 follow.
546 </para>
548 <itemizedlist>
549 <listitem><para>The first component is simply Mercurial's way of saying <quote>I am
550 giving up</quote>.
551 </para>
552 </listitem><programlisting>
553 <listitem><para> <emphasis role="bold">abort:</emphasis> broken.style:1: parse error
554 </para>
555 </listitem></programlisting>
557 </para>
558 </listitem>
559 <listitem><para>Next comes the name of the style file that contains the error.
560 </para>
561 </listitem><programlisting>
562 <listitem><para> abort: <emphasis role="bold">broken.style</emphasis>:1: parse error
563 </para>
564 </listitem></programlisting>
566 </para>
567 </listitem>
568 <listitem><para>Following the file name is the line number where the error was
569 encountered.
570 </para>
571 </listitem><programlisting>
572 <listitem><para> abort: broken.style:<emphasis role="bold">1</emphasis>: parse error
573 </para>
574 </listitem></programlisting>
576 </para>
577 </listitem>
578 <listitem><para>Finally, a description of what went wrong.
579 </para>
580 </listitem><programlisting>
581 <listitem><para> abort: broken.style:1: <emphasis role="bold">parse error</emphasis>
582 </para>
583 </listitem></programlisting>
584 <listitem><para> The description of the problem is not always clear (as in this
585 case), but even when it is cryptic, it is almost always trivial to
586 visually inspect the offending line in the style file and see what
587 is wrong.
588 </para>
589 </listitem></itemizedlist>
591 </sect2>
592 <sect2>
593 <title>Uniquely identifying a repository</title>
595 <para>If you would like to be able to identify a Mercurial repository
596 <quote>fairly uniquely</quote> using a short string as an identifier, you can
597 use the first revision in the repository.
598 <!-- &interaction.template.svnstyle.id; -->
599 This is not guaranteed to be unique, but it is nevertheless useful in
600 many cases.
601 </para>
602 <itemizedlist>
603 <listitem><para>It will not work in a completely empty repository, because such
604 a repository does not have a revision zero.
605 </para>
606 </listitem>
607 <listitem><para>Neither will it work in the (extremely rare) case where a
608 repository is a merge of two or more formerly independent
609 repositories, and you still have those repositories around.
610 </para>
611 </listitem></itemizedlist>
612 <para>Here are some uses to which you could put this identifier:
613 </para>
614 <itemizedlist>
615 <listitem><para>As a key into a table for a database that manages repositories
616 on a server.
617 </para>
618 </listitem>
619 <listitem><para>As half of a {<emphasis>repository ID</emphasis>, <emphasis>revision ID</emphasis>} tuple.
620 Save this information away when you run an automated build or other
621 activity, so that you can <quote>replay</quote> the build later if necessary.
622 </para>
623 </listitem></itemizedlist>
625 </sect2>
626 <sect2>
627 <title>Mimicking Subversion's output</title>
629 <para>Let's try to emulate the default output format used by another
630 revision control tool, Subversion.
631 <!-- &interaction.template.svnstyle.short; -->
632 </para>
634 <para>Since Subversion's output style is fairly simple, it is easy to
635 copy-and-paste a hunk of its output into a file, and replace the text
636 produced above by Subversion with the template values we'd like to see
637 expanded.
638 <!-- &interaction.template.svnstyle.template; -->
639 </para>
641 <para>There are a few small ways in which this template deviates from the
642 output produced by Subversion.
643 </para>
644 <itemizedlist>
645 <listitem><para>Subversion prints a <quote>readable</quote> date (the <quote>\texttt{Wed, 27 Sep
646 2006}</quote> in the example output above) in parentheses. Mercurial's
647 templating engine does not provide a way to display a date in this
648 format without also printing the time and time zone.
649 </para>
650 </listitem>
651 <listitem><para>We emulate Subversion's printing of <quote>separator</quote> lines full of
652 <quote><literal>-</literal></quote> characters by ending the template with such a line.
653 We use the templating engine's <literal role="template-keyword">header</literal> keyword to print a
654 separator line as the first line of output (see below), thus
655 achieving similar output to Subversion.
656 </para>
657 </listitem>
658 <listitem><para>Subversion's output includes a count in the header of the number
659 of lines in the commit message. We cannot replicate this in
660 Mercurial; the templating engine does not currently provide a filter
661 that counts the number of lines the template generates.
662 </para>
663 </listitem></itemizedlist>
664 <para>It took me no more than a minute or two of work to replace literal
665 text from an example of Subversion's output with some keywords and
666 filters to give the template above. The style file simply refers to
667 the template.
668 <!-- &interaction.template.svnstyle.style; -->
669 </para>
671 <para>We could have included the text of the template file directly in the
672 style file by enclosing it in quotes and replacing the newlines with
673 <quote><literal>\n</literal></quote> sequences, but it would have made the style file too
674 difficult to read. Readability is a good guide when you're trying to
675 decide whether some text belongs in a style file, or in a template
676 file that the style file points to. If the style file will look too
677 big or cluttered if you insert a literal piece of text, drop it into a
678 template instead.
679 </para>
681 </sect2>
682 </sect1>
683 </chapter>
685 <!--
686 local variables:
687 sgml-parent-document: ("00book.xml" "book" "chapter")
688 end:
689 -->