comparison en/ch10-template.xml @ 683:c838b3975bc6

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