hgbook
diff en/ch11-template.xml @ 1113:613690ad6a9c
Merge with dongsheng
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Sat Jul 10 16:21:26 2010 +0100 (2010-07-10) |
parents | 9e33729cafae |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/en/ch11-template.xml Sat Jul 10 16:21:26 2010 +0100 1.3 @@ -0,0 +1,685 @@ 1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.5 + 1.6 +<chapter id="chap:template"> 1.7 + <?dbhtml filename="customizing-the-output-of-mercurial.html"?> 1.8 + <title>Customizing the output of Mercurial</title> 1.9 + 1.10 + <para id="x_578">Mercurial provides a powerful mechanism to let you control how 1.11 + it displays information. The mechanism is based on templates. 1.12 + You can use templates to generate specific output for a single 1.13 + command, or to customize the entire appearance of the built-in web 1.14 + interface.</para> 1.15 + 1.16 + <sect1 id="sec:style"> 1.17 + <title>Using precanned output styles</title> 1.18 + 1.19 + <para id="x_579">Packaged with Mercurial are some output styles that you can 1.20 + use immediately. A style is simply a precanned template that 1.21 + someone wrote and installed somewhere that Mercurial can 1.22 + find.</para> 1.23 + 1.24 + <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's 1.25 + review its normal output.</para> 1.26 + 1.27 + &interaction.template.simple.normal; 1.28 + 1.29 + <para id="x_57b">This is somewhat informative, but it takes up a lot of 1.30 + space&emdash;five lines of output per changeset. The 1.31 + <literal>compact</literal> style reduces this to three lines, 1.32 + presented in a sparse manner.</para> 1.33 + 1.34 + &interaction.template.simple.compact; 1.35 + 1.36 + <para id="x_57c">The <literal>changelog</literal> style hints at the 1.37 + expressive power of Mercurial's templating engine. This style 1.38 + attempts to follow the GNU Project's changelog 1.39 + guidelines<citation>web:changelog</citation>.</para> 1.40 + 1.41 + &interaction.template.simple.changelog; 1.42 + 1.43 + <para id="x_57d">You will not be shocked to learn that Mercurial's default 1.44 + output style is named <literal>default</literal>.</para> 1.45 + 1.46 + <sect2> 1.47 + <title>Setting a default style</title> 1.48 + 1.49 + <para id="x_57e">You can modify the output style that Mercurial will use 1.50 + for every command by editing your <filename 1.51 + role="special">~/.hgrc</filename> file, naming the style 1.52 + you would prefer to use.</para> 1.53 + 1.54 + <programlisting>[ui] 1.55 +style = compact</programlisting> 1.56 + 1.57 + <para id="x_57f">If you write a style of your own, you can use it by either 1.58 + providing the path to your style file, or copying your style 1.59 + file into a location where Mercurial can find it (typically 1.60 + the <literal>templates</literal> subdirectory of your 1.61 + Mercurial install directory).</para> 1.62 + </sect2> 1.63 + </sect1> 1.64 + 1.65 + <sect1> 1.66 + <title>Commands that support styles and templates</title> 1.67 + 1.68 + <para id="x_580">All of Mercurial's 1.69 + <quote><literal>log</literal>-like</quote> commands let you use 1.70 + styles and templates: <command role="hg-cmd">hg 1.71 + incoming</command>, <command role="hg-cmd">hg log</command>, 1.72 + <command role="hg-cmd">hg outgoing</command>, and <command 1.73 + role="hg-cmd">hg tip</command>.</para> 1.74 + 1.75 + <para id="x_581">As I write this manual, these are so far the only commands 1.76 + that support styles and templates. Since these are the most 1.77 + important commands that need customizable output, there has been 1.78 + little pressure from the Mercurial user community to add style 1.79 + and template support to other commands.</para> 1.80 + </sect1> 1.81 + 1.82 + <sect1> 1.83 + <title>The basics of templating</title> 1.84 + 1.85 + <para id="x_582">At its simplest, a Mercurial template is a piece of text. 1.86 + Some of the text never changes, while other parts are 1.87 + <emphasis>expanded</emphasis>, or replaced with new text, when 1.88 + necessary.</para> 1.89 + 1.90 + <para id="x_583">Before we continue, let's look again at a simple example of 1.91 + Mercurial's normal output.</para> 1.92 + 1.93 + &interaction.template.simple.normal; 1.94 + 1.95 + <para id="x_584">Now, let's run the same command, but using a template to 1.96 + change its output.</para> 1.97 + 1.98 + &interaction.template.simple.simplest; 1.99 + 1.100 + <para id="x_585">The example above illustrates the simplest possible 1.101 + template; it's just a piece of static text, printed once for 1.102 + each changeset. The <option 1.103 + role="hg-opt-log">--template</option> option to the <command 1.104 + role="hg-cmd">hg log</command> command tells Mercurial to use 1.105 + the given text as the template when printing each 1.106 + changeset.</para> 1.107 + 1.108 + <para id="x_586">Notice that the template string above ends with the text 1.109 + <quote><literal>\n</literal></quote>. This is an 1.110 + <emphasis>escape sequence</emphasis>, telling Mercurial to print 1.111 + a newline at the end of each template item. If you omit this 1.112 + newline, Mercurial will run each piece of output together. See 1.113 + <xref linkend="sec:template:escape"/> for more details 1.114 + of escape sequences.</para> 1.115 + 1.116 + <para id="x_587">A template that prints a fixed string of text all the time 1.117 + isn't very useful; let's try something a bit more 1.118 + complex.</para> 1.119 + 1.120 + &interaction.template.simple.simplesub; 1.121 + 1.122 + <para id="x_588">As you can see, the string 1.123 + <quote><literal>{desc}</literal></quote> in the template has 1.124 + been replaced in the output with the description of each 1.125 + changeset. Every time Mercurial finds text enclosed in curly 1.126 + braces (<quote><literal>{</literal></quote> and 1.127 + <quote><literal>}</literal></quote>), it will try to replace the 1.128 + braces and text with the expansion of whatever is inside. To 1.129 + print a literal curly brace, you must escape it, as described in 1.130 + <xref linkend="sec:template:escape"/>.</para> 1.131 + </sect1> 1.132 + 1.133 + <sect1 id="sec:template:keyword"> 1.134 + <title>Common template keywords</title> 1.135 + 1.136 + <para id="x_589">You can start writing simple templates immediately using the 1.137 + keywords below.</para> 1.138 + 1.139 + <itemizedlist> 1.140 + <listitem><para id="x_58a"><literal 1.141 + role="template-keyword">author</literal>: String. The 1.142 + unmodified author of the changeset.</para> 1.143 + </listitem> 1.144 + <listitem><para id="x_58b"><literal 1.145 + role="template-keyword">branches</literal>: String. The 1.146 + name of the branch on which the changeset was committed. 1.147 + Will be empty if the branch name was 1.148 + <literal>default</literal>.</para> 1.149 + </listitem> 1.150 + <listitem><para id="x_58c"><literal role="template-keyword">date</literal>: 1.151 + Date information. The date when the changeset was 1.152 + committed. This is <emphasis>not</emphasis> human-readable; 1.153 + you must pass it through a filter that will render it 1.154 + appropriately. See <xref 1.155 + linkend="sec:template:filter"/> for more information 1.156 + on filters. The date is expressed as a pair of numbers. The 1.157 + first number is a Unix UTC timestamp (seconds since January 1.158 + 1, 1970); the second is the offset of the committer's 1.159 + timezone from UTC, in seconds.</para> 1.160 + </listitem> 1.161 + <listitem><para id="x_58d"><literal role="template-keyword">desc</literal>: 1.162 + String. The text of the changeset description.</para> 1.163 + </listitem> 1.164 + <listitem><para id="x_58e"><literal 1.165 + role="template-keyword">files</literal>: List of strings. 1.166 + All files modified, added, or removed by this 1.167 + changeset.</para> 1.168 + </listitem> 1.169 + <listitem><para id="x_58f"><literal 1.170 + role="template-keyword">file_adds</literal>: List of 1.171 + strings. Files added by this changeset.</para> 1.172 + </listitem> 1.173 + <listitem><para id="x_590"><literal 1.174 + role="template-keyword">file_dels</literal>: List of 1.175 + strings. Files removed by this changeset.</para> 1.176 + </listitem> 1.177 + <listitem><para id="x_591"><literal role="template-keyword">node</literal>: 1.178 + String. The changeset identification hash, as a 1.179 + 40-character hexadecimal string.</para> 1.180 + </listitem> 1.181 + <listitem><para id="x_592"><literal 1.182 + role="template-keyword">parents</literal>: List of 1.183 + strings. The parents of the changeset.</para> 1.184 + </listitem> 1.185 + <listitem><para id="x_593"><literal role="template-keyword">rev</literal>: 1.186 + Integer. The repository-local changeset revision 1.187 + number.</para> 1.188 + </listitem> 1.189 + <listitem><para id="x_594"><literal role="template-keyword">tags</literal>: 1.190 + List of strings. Any tags associated with the 1.191 + changeset.</para> 1.192 + </listitem> 1.193 + </itemizedlist> 1.194 + 1.195 + <para id="x_595">A few simple experiments will show us what to expect when we 1.196 + use these keywords; you can see the results below.</para> 1.197 + 1.198 + &interaction.template.simple.keywords; 1.199 + 1.200 + <para id="x_596">As we noted above, the date keyword does not produce 1.201 + human-readable output, so we must treat it specially. This 1.202 + involves using a <emphasis>filter</emphasis>, about which more 1.203 + in <xref linkend="sec:template:filter"/>.</para> 1.204 + 1.205 + &interaction.template.simple.datekeyword; 1.206 + </sect1> 1.207 + 1.208 + <sect1 id="sec:template:escape"> 1.209 + <title>Escape sequences</title> 1.210 + 1.211 + <para id="x_597">Mercurial's templating engine recognises the most commonly 1.212 + used escape sequences in strings. When it sees a backslash 1.213 + (<quote><literal>\</literal></quote>) character, it looks at the 1.214 + following character and substitutes the two characters with a 1.215 + single replacement, as described below.</para> 1.216 + 1.217 + <itemizedlist> 1.218 + <listitem><para id="x_598"><literal>\</literal>: 1.219 + Backslash, <quote><literal>\</literal></quote>, ASCII 1.220 + 134.</para> 1.221 + </listitem> 1.222 + <listitem><para id="x_599"><literal>\n</literal>: Newline, 1.223 + ASCII 12.</para> 1.224 + </listitem> 1.225 + <listitem><para id="x_59a"><literal>\r</literal>: Carriage 1.226 + return, ASCII 15.</para> 1.227 + </listitem> 1.228 + <listitem><para id="x_59b"><literal>\t</literal>: Tab, ASCII 1.229 + 11.</para> 1.230 + </listitem> 1.231 + <listitem><para id="x_59c"><literal>\v</literal>: Vertical 1.232 + tab, ASCII 13.</para> 1.233 + </listitem> 1.234 + <listitem><para id="x_59d"><literal>\{</literal>: Open curly 1.235 + brace, <quote><literal>{</literal></quote>, ASCII 1.236 + 173.</para> 1.237 + </listitem> 1.238 + <listitem><para id="x_59e"><literal>\}</literal>: Close curly 1.239 + brace, <quote><literal>}</literal></quote>, ASCII 1.240 + 175.</para> 1.241 + </listitem></itemizedlist> 1.242 + 1.243 + <para id="x_59f">As indicated above, if you want the expansion of a template 1.244 + to contain a literal <quote><literal>\</literal></quote>, 1.245 + <quote><literal>{</literal></quote>, or 1.246 + <quote><literal>{</literal></quote> character, you must escape 1.247 + it.</para> 1.248 + </sect1> 1.249 + 1.250 + <sect1 id="sec:template:filter"> 1.251 + <title>Filtering keywords to change their results</title> 1.252 + 1.253 + <para id="x_5a0">Some of the results of template expansion are not 1.254 + immediately easy to use. Mercurial lets you specify an optional 1.255 + chain of <emphasis>filters</emphasis> to modify the result of 1.256 + expanding a keyword. You have already seen a common filter, 1.257 + <literal role="template-kw-filt-date">isodate</literal>, in 1.258 + action above, to make a date readable.</para> 1.259 + 1.260 + <para id="x_5a1">Below is a list of the most commonly used filters that 1.261 + Mercurial supports. While some filters can be applied to any 1.262 + text, others can only be used in specific circumstances. The 1.263 + name of each filter is followed first by an indication of where 1.264 + it can be used, then a description of its effect.</para> 1.265 + 1.266 + <itemizedlist> 1.267 + <listitem><para id="x_5a2"><literal 1.268 + role="template-filter">addbreaks</literal>: Any text. Add 1.269 + an XHTML <quote><literal><br/></literal></quote> tag 1.270 + before the end of every line except the last. For example, 1.271 + <quote><literal>foo\nbar</literal></quote> becomes 1.272 + <quote><literal>foo<br/>\nbar</literal></quote>.</para> 1.273 + </listitem> 1.274 + <listitem><para id="x_5a3"><literal 1.275 + role="template-kw-filt-date">age</literal>: <literal 1.276 + role="template-keyword">date</literal> keyword. Render 1.277 + the age of the date, relative to the current time. Yields a 1.278 + string like <quote><literal>10 1.279 + minutes</literal></quote>.</para> 1.280 + </listitem> 1.281 + <listitem><para id="x_5a4"><literal 1.282 + role="template-filter">basename</literal>: Any text, but 1.283 + most useful for the <literal 1.284 + role="template-keyword">files</literal> keyword and its 1.285 + relatives. Treat the text as a path, and return the 1.286 + basename. For example, 1.287 + <quote><literal>foo/bar/baz</literal></quote> becomes 1.288 + <quote><literal>baz</literal></quote>.</para> 1.289 + </listitem> 1.290 + <listitem><para id="x_5a5"><literal 1.291 + role="template-kw-filt-date">date</literal>: <literal 1.292 + role="template-keyword">date</literal> keyword. Render a 1.293 + date in a similar format to the Unix <literal 1.294 + role="template-keyword">date</literal> command, but with 1.295 + timezone included. Yields a string like <quote><literal>Mon 1.296 + Sep 04 15:13:13 2006 -0700</literal></quote>.</para> 1.297 + </listitem> 1.298 + <listitem><para id="x_5a6"><literal 1.299 + role="template-kw-filt-author">domain</literal>: Any text, 1.300 + but most useful for the <literal 1.301 + role="template-keyword">author</literal> keyword. Finds 1.302 + the first string that looks like an email address, and 1.303 + extract just the domain component. For example, 1.304 + <quote><literal>Bryan O'Sullivan 1.305 + <bos@serpentine.com></literal></quote> becomes 1.306 + <quote><literal>serpentine.com</literal></quote>.</para> 1.307 + </listitem> 1.308 + <listitem><para id="x_5a7"><literal 1.309 + role="template-kw-filt-author">email</literal>: Any text, 1.310 + but most useful for the <literal 1.311 + role="template-keyword">author</literal> keyword. Extract 1.312 + the first string that looks like an email address. For 1.313 + example, <quote><literal>Bryan O'Sullivan 1.314 + <bos@serpentine.com></literal></quote> becomes 1.315 + <quote><literal>bos@serpentine.com</literal></quote>.</para> 1.316 + </listitem> 1.317 + <listitem><para id="x_5a8"><literal 1.318 + role="template-filter">escape</literal>: Any text. 1.319 + Replace the special XML/XHTML characters 1.320 + <quote><literal>&</literal></quote>, 1.321 + <quote><literal><</literal></quote> and 1.322 + <quote><literal>></literal></quote> with XML 1.323 + entities.</para> 1.324 + </listitem> 1.325 + <listitem><para id="x_5a9"><literal 1.326 + role="template-filter">fill68</literal>: Any text. Wrap 1.327 + the text to fit in 68 columns. This is useful before you 1.328 + pass text through the <literal 1.329 + role="template-filter">tabindent</literal> filter, and 1.330 + still want it to fit in an 80-column fixed-font 1.331 + window.</para> 1.332 + </listitem> 1.333 + <listitem><para id="x_5aa"><literal 1.334 + role="template-filter">fill76</literal>: Any text. Wrap 1.335 + the text to fit in 76 columns.</para> 1.336 + </listitem> 1.337 + <listitem><para id="x_5ab"><literal 1.338 + role="template-filter">firstline</literal>: Any text. 1.339 + Yield the first line of text, without any trailing 1.340 + newlines.</para> 1.341 + </listitem> 1.342 + <listitem><para id="x_5ac"><literal 1.343 + role="template-kw-filt-date">hgdate</literal>: <literal 1.344 + role="template-keyword">date</literal> keyword. Render 1.345 + the date as a pair of readable numbers. Yields a string 1.346 + like <quote><literal>1157407993 1.347 + 25200</literal></quote>.</para> 1.348 + </listitem> 1.349 + <listitem><para id="x_5ad"><literal 1.350 + role="template-kw-filt-date">isodate</literal>: <literal 1.351 + role="template-keyword">date</literal> keyword. Render 1.352 + the date as a text string in ISO 8601 format. Yields a 1.353 + string like <quote><literal>2006-09-04 15:13:13 1.354 + -0700</literal></quote>.</para> 1.355 + </listitem> 1.356 + <listitem><para id="x_5ae"><literal 1.357 + role="template-filter">obfuscate</literal>: Any text, but 1.358 + most useful for the <literal 1.359 + role="template-keyword">author</literal> keyword. Yield 1.360 + the input text rendered as a sequence of XML entities. This 1.361 + helps to defeat some particularly stupid screen-scraping 1.362 + email harvesting spambots.</para> 1.363 + </listitem> 1.364 + <listitem><para id="x_5af"><literal 1.365 + role="template-kw-filt-author">person</literal>: Any text, 1.366 + but most useful for the <literal 1.367 + role="template-keyword">author</literal> keyword. Yield 1.368 + the text before an email address. For example, 1.369 + <quote><literal>Bryan O'Sullivan 1.370 + <bos@serpentine.com></literal></quote> becomes 1.371 + <quote><literal>Bryan O'Sullivan</literal></quote>.</para> 1.372 + </listitem> 1.373 + <listitem><para id="x_5b0"><literal 1.374 + role="template-kw-filt-date">rfc822date</literal>: 1.375 + <literal role="template-keyword">date</literal> keyword. 1.376 + Render a date using the same format used in email headers. 1.377 + Yields a string like <quote><literal>Mon, 04 Sep 2006 1.378 + 15:13:13 -0700</literal></quote>.</para> 1.379 + </listitem> 1.380 + <listitem><para id="x_5b1"><literal 1.381 + role="template-kw-filt-node">short</literal>: Changeset 1.382 + hash. Yield the short form of a changeset hash, i.e. a 1.383 + 12-character hexadecimal string.</para> 1.384 + </listitem> 1.385 + <listitem><para id="x_5b2"><literal 1.386 + role="template-kw-filt-date">shortdate</literal>: <literal 1.387 + role="template-keyword">date</literal> keyword. Render 1.388 + the year, month, and day of the date. Yields a string like 1.389 + <quote><literal>2006-09-04</literal></quote>.</para> 1.390 + </listitem> 1.391 + <listitem><para id="x_5b3"><literal role="template-filter">strip</literal>: 1.392 + Any text. Strip all leading and trailing whitespace from 1.393 + the string.</para> 1.394 + </listitem> 1.395 + <listitem><para id="x_5b4"><literal 1.396 + role="template-filter">tabindent</literal>: Any text. 1.397 + Yield the text, with every line except the first starting 1.398 + with a tab character.</para> 1.399 + </listitem> 1.400 + <listitem><para id="x_5b5"><literal 1.401 + role="template-filter">urlescape</literal>: Any text. 1.402 + Escape all characters that are considered 1.403 + <quote>special</quote> by URL parsers. For example, 1.404 + <literal>foo bar</literal> becomes 1.405 + <literal>foo%20bar</literal>.</para> 1.406 + </listitem> 1.407 + <listitem><para id="x_5b6"><literal 1.408 + role="template-kw-filt-author">user</literal>: Any text, 1.409 + but most useful for the <literal 1.410 + role="template-keyword">author</literal> keyword. Return 1.411 + the <quote>user</quote> portion of an email address. For 1.412 + example, <quote><literal>Bryan O'Sullivan 1.413 + <bos@serpentine.com></literal></quote> becomes 1.414 + <quote><literal>bos</literal></quote>.</para> 1.415 + </listitem> 1.416 + </itemizedlist> 1.417 + 1.418 + &interaction.template.simple.manyfilters; 1.419 + 1.420 + <note> 1.421 + <para id="x_5b7"> If you try to apply a filter to a piece of data that it 1.422 + cannot process, Mercurial will fail and print a Python 1.423 + exception. For example, trying to run the output of the 1.424 + <literal role="template-keyword">desc</literal> keyword into 1.425 + the <literal role="template-kw-filt-date">isodate</literal> 1.426 + filter is not a good idea.</para> 1.427 + </note> 1.428 + 1.429 + <sect2> 1.430 + <title>Combining filters</title> 1.431 + 1.432 + <para id="x_5b8">It is easy to combine filters to yield output in the form 1.433 + you would like. The following chain of filters tidies up a 1.434 + description, then makes sure that it fits cleanly into 68 1.435 + columns, then indents it by a further 8 characters (at least 1.436 + on Unix-like systems, where a tab is conventionally 8 1.437 + characters wide).</para> 1.438 + 1.439 + &interaction.template.simple.combine; 1.440 + 1.441 + <para id="x_5b9">Note the use of <quote><literal>\t</literal></quote> (a 1.442 + tab character) in the template to force the first line to be 1.443 + indented; this is necessary since <literal 1.444 + role="template-keyword">tabindent</literal> indents all 1.445 + lines <emphasis>except</emphasis> the first.</para> 1.446 + 1.447 + <para id="x_5ba">Keep in mind that the order of filters in a chain is 1.448 + significant. The first filter is applied to the result of the 1.449 + keyword; the second to the result of the first filter; and so 1.450 + on. For example, using <literal>fill68|tabindent</literal> 1.451 + gives very different results from 1.452 + <literal>tabindent|fill68</literal>.</para> 1.453 + </sect2> 1.454 + </sect1> 1.455 + 1.456 + <sect1> 1.457 + <title>From templates to styles</title> 1.458 + 1.459 + <para id="x_5bb">A command line template provides a quick and simple way to 1.460 + format some output. Templates can become verbose, though, and 1.461 + it's useful to be able to give a template a name. A style file 1.462 + is a template with a name, stored in a file.</para> 1.463 + 1.464 + <para id="x_5bc">More than that, using a style file unlocks the power of 1.465 + Mercurial's templating engine in ways that are not possible 1.466 + using the command line <option 1.467 + role="hg-opt-log">--template</option> option.</para> 1.468 + 1.469 + <sect2> 1.470 + <title>The simplest of style files</title> 1.471 + 1.472 + <para id="x_5bd">Our simple style file contains just one line:</para> 1.473 + 1.474 + &interaction.template.simple.rev; 1.475 + 1.476 + <para id="x_5be">This tells Mercurial, <quote>if you're printing a 1.477 + changeset, use the text on the right as the 1.478 + template</quote>.</para> 1.479 + </sect2> 1.480 + 1.481 + <sect2> 1.482 + <title>Style file syntax</title> 1.483 + 1.484 + <para id="x_5bf">The syntax rules for a style file are simple.</para> 1.485 + 1.486 + <itemizedlist> 1.487 + <listitem><para id="x_5c0">The file is processed one line at a 1.488 + time.</para> 1.489 + </listitem> 1.490 + <listitem><para id="x_5c1">Leading and trailing white space are 1.491 + ignored.</para> 1.492 + </listitem> 1.493 + <listitem><para id="x_5c2">Empty lines are skipped.</para> 1.494 + </listitem> 1.495 + <listitem><para id="x_5c3">If a line starts with either of the characters 1.496 + <quote><literal>#</literal></quote> or 1.497 + <quote><literal>;</literal></quote>, the entire line is 1.498 + treated as a comment, and skipped as if empty.</para> 1.499 + </listitem> 1.500 + <listitem><para id="x_5c4">A line starts with a keyword. This must start 1.501 + with an alphabetic character or underscore, and can 1.502 + subsequently contain any alphanumeric character or 1.503 + underscore. (In regexp notation, a keyword must match 1.504 + <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> 1.505 + </listitem> 1.506 + <listitem><para id="x_5c5">The next element must be an 1.507 + <quote><literal>=</literal></quote> character, which can 1.508 + be preceded or followed by an arbitrary amount of white 1.509 + space.</para> 1.510 + </listitem> 1.511 + <listitem><para id="x_5c6">If the rest of the line starts and ends with 1.512 + matching quote characters (either single or double quote), 1.513 + it is treated as a template body.</para> 1.514 + </listitem> 1.515 + <listitem><para id="x_5c7">If the rest of the line <emphasis>does 1.516 + not</emphasis> start with a quote character, it is 1.517 + treated as the name of a file; the contents of this file 1.518 + will be read and used as a template body.</para> 1.519 + </listitem></itemizedlist> 1.520 + </sect2> 1.521 + </sect1> 1.522 + 1.523 + <sect1> 1.524 + <title>Style files by example</title> 1.525 + 1.526 + <para id="x_5c8">To illustrate how to write a style file, we will construct a 1.527 + few by example. Rather than provide a complete style file and 1.528 + walk through it, we'll mirror the usual process of developing a 1.529 + style file by starting with something very simple, and walking 1.530 + through a series of successively more complete examples.</para> 1.531 + 1.532 + <sect2> 1.533 + <title>Identifying mistakes in style files</title> 1.534 + 1.535 + <para id="x_5c9">If Mercurial encounters a problem in a style file you are 1.536 + working on, it prints a terse error message that, once you 1.537 + figure out what it means, is actually quite useful.</para> 1.538 + 1.539 +&interaction.template.svnstyle.syntax.input; 1.540 + 1.541 + <para id="x_5ca">Notice that <filename>broken.style</filename> attempts to 1.542 + define a <literal>changeset</literal> keyword, but forgets to 1.543 + give any content for it. When instructed to use this style 1.544 + file, Mercurial promptly complains.</para> 1.545 + 1.546 + &interaction.template.svnstyle.syntax.error; 1.547 + 1.548 + <para id="x_5cb">This error message looks intimidating, but it is not too 1.549 + hard to follow.</para> 1.550 + 1.551 + <itemizedlist> 1.552 + <listitem><para id="x_5cc">The first component is simply Mercurial's way 1.553 + of saying <quote>I am giving up</quote>.</para> 1.554 + <programlisting>___abort___: broken.style:1: parse error</programlisting> 1.555 + </listitem> 1.556 + <listitem><para id="x_5cd">Next comes the name of the style file that 1.557 + contains the error.</para> 1.558 + <programlisting>abort: ___broken.style___:1: parse error</programlisting> 1.559 + </listitem> 1.560 + <listitem><para id="x_5ce">Following the file name is the line number 1.561 + where the error was encountered.</para> 1.562 + <programlisting>abort: broken.style:___1___: parse error</programlisting> 1.563 + </listitem> 1.564 + <listitem><para id="x_5cf">Finally, a description of what went 1.565 + wrong.</para> 1.566 + <programlisting>abort: broken.style:1: ___parse error___</programlisting> 1.567 + </listitem> 1.568 + <listitem><para id="x_5d0">The description of the problem is not always 1.569 + clear (as in this case), but even when it is cryptic, it 1.570 + is almost always trivial to visually inspect the offending 1.571 + line in the style file and see what is wrong.</para> 1.572 + </listitem> 1.573 + </itemizedlist> 1.574 + </sect2> 1.575 + 1.576 + <sect2> 1.577 + <title>Uniquely identifying a repository</title> 1.578 + 1.579 + <para id="x_5d1">If you would like to be able to identify a Mercurial 1.580 + repository <quote>fairly uniquely</quote> using a short string 1.581 + as an identifier, you can use the first revision in the 1.582 + repository.</para> 1.583 + 1.584 + &interaction.template.svnstyle.id; 1.585 + 1.586 + <para id="x_5d2">This is likely to be unique, and so it is 1.587 + useful in many cases. There are a few caveats.</para> 1.588 + <itemizedlist> 1.589 + <listitem><para id="x_5d3">It will not work in a completely empty 1.590 + repository, because such a repository does not have a 1.591 + revision zero.</para> 1.592 + </listitem> 1.593 + <listitem><para id="x_5d4">Neither will it work in the (extremely rare) 1.594 + case where a repository is a merge of two or more formerly 1.595 + independent repositories, and you still have those 1.596 + repositories around.</para> 1.597 + </listitem></itemizedlist> 1.598 + <para id="x_5d5">Here are some uses to which you could put this 1.599 + identifier:</para> 1.600 + <itemizedlist> 1.601 + <listitem><para id="x_5d6">As a key into a table for a database that 1.602 + manages repositories on a server.</para> 1.603 + </listitem> 1.604 + <listitem><para id="x_5d7">As half of a {<emphasis>repository 1.605 + ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 1.606 + Save this information away when you run an automated build 1.607 + or other activity, so that you can <quote>replay</quote> 1.608 + the build later if necessary.</para> 1.609 + </listitem> 1.610 + </itemizedlist> 1.611 + </sect2> 1.612 + 1.613 + <sect2> 1.614 + <title>Listing files on multiple lines</title> 1.615 + 1.616 + <para id="x_714">Suppose we want to list the files changed by a changeset, 1.617 + one per line, with a little indentation before each file 1.618 + name.</para> 1.619 + 1.620 + &interaction.ch10-multiline.go; 1.621 + </sect2> 1.622 + 1.623 + <sect2> 1.624 + <title>Mimicking Subversion's output</title> 1.625 + 1.626 + <para id="x_5d8">Let's try to emulate the default output format used by 1.627 + another revision control tool, Subversion.</para> 1.628 + 1.629 + &interaction.template.svnstyle.short; 1.630 + 1.631 + <para id="x_5d9">Since Subversion's output style is fairly simple, it is 1.632 + easy to copy-and-paste a hunk of its output into a file, and 1.633 + replace the text produced above by Subversion with the 1.634 + template values we'd like to see expanded.</para> 1.635 + 1.636 + &interaction.template.svnstyle.template; 1.637 + 1.638 + <para id="x_5da">There are a few small ways in which this template deviates 1.639 + from the output produced by Subversion.</para> 1.640 + <itemizedlist> 1.641 + <listitem><para id="x_5db">Subversion prints a <quote>readable</quote> 1.642 + date (the <quote><literal>Wed, 27 Sep 2006</literal></quote> in the 1.643 + example output above) in parentheses. Mercurial's 1.644 + templating engine does not provide a way to display a date 1.645 + in this format without also printing the time and time 1.646 + zone.</para> 1.647 + </listitem> 1.648 + <listitem><para id="x_5dc">We emulate Subversion's printing of 1.649 + <quote>separator</quote> lines full of 1.650 + <quote><literal>-</literal></quote> characters by ending 1.651 + the template with such a line. We use the templating 1.652 + engine's <literal role="template-keyword">header</literal> 1.653 + keyword to print a separator line as the first line of 1.654 + output (see below), thus achieving similar output to 1.655 + Subversion.</para> 1.656 + </listitem> 1.657 + <listitem><para id="x_5dd">Subversion's output includes a count in the 1.658 + header of the number of lines in the commit message. We 1.659 + cannot replicate this in Mercurial; the templating engine 1.660 + does not currently provide a filter that counts the number 1.661 + of lines the template generates.</para> 1.662 + </listitem></itemizedlist> 1.663 + <para id="x_5de">It took me no more than a minute or two of work to replace 1.664 + literal text from an example of Subversion's output with some 1.665 + keywords and filters to give the template above. The style 1.666 + file simply refers to the template.</para> 1.667 + 1.668 + &interaction.template.svnstyle.style; 1.669 + 1.670 + <para id="x_5df">We could have included the text of the template file 1.671 + directly in the style file by enclosing it in quotes and 1.672 + replacing the newlines with 1.673 + <quote><literal>\n</literal></quote> sequences, but it would 1.674 + have made the style file too difficult to read. Readability 1.675 + is a good guide when you're trying to decide whether some text 1.676 + belongs in a style file, or in a template file that the style 1.677 + file points to. If the style file will look too big or 1.678 + cluttered if you insert a literal piece of text, drop it into 1.679 + a template instead.</para> 1.680 + </sect2> 1.681 + </sect1> 1.682 +</chapter> 1.683 + 1.684 +<!-- 1.685 +local variables: 1.686 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.687 +end: 1.688 +-->