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