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