hgbook/read/customizing-the-output-of-m...

491 lines
47 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 11. Customizing the output of Mercurial</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks"><link rel="next" href="managing-change-with-mercurial-queues.html" title="Chapter 12. Managing change with Mercurial Queues"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 11. Customizing the output of Mercurial</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="handling-repository-events-with-hooks.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="managing-change-with-mercurial-queues.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:template"><div class="titlepage"><div><div><h2 class="title">Chapter 11. Customizing the output of Mercurial</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:style">Using precanned output styles</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id414837">Setting a default style</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id414882">Commands that support styles and templates</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id414947">The basics of templating</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:keyword">Common template keywords</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:escape">Escape sequences</a></span></dt><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#sec:template:filter">Filtering keywords to change their results</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417290">Combining filters</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id417618">From templates to styles</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417353">The simplest of style files</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417428">Style file syntax</a></span></dt></dl></dd><dt><span class="sect1"><a href="customizing-the-output-of-mercurial.html#id417656">Style files by example</a></span></dt><dd><dl><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417669">Identifying mistakes in style files</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417853">Uniquely identifying a repository</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id417978">Listing files on multiple lines</a></span></dt><dt><span class="sect2"><a href="customizing-the-output-of-mercurial.html#id418118">Mimicking Subversion's output</a></span></dt></dl></dd></dl></div><p id="x_578"><a name="x_578"></a>Mercurial provides a powerful mechanism to let you control how
it displays information. The mechanism is based on templates.
You can use templates to generate specific output for a single
command, or to customize the entire appearance of the built-in web
interface.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:style">Using precanned output styles</h2></div></div></div><p id="x_579"><a name="x_579"></a>Packaged with Mercurial are some output styles that you can
use immediately. A style is simply a precanned template that
someone wrote and installed somewhere that Mercurial can
find.</p><p id="x_57a"><a name="x_57a"></a>Before we take a look at Mercurial's bundled styles, let's
review its normal output.</p><pre id="id415040" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1</code></strong>
changeset: 1:107e439be01c
tag: mytag
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:46 2009 +0000
summary: added line to end of &lt;&lt;hello&gt;&gt; file.
</pre><p id="x_57b"><a name="x_57b"></a>This is somewhat informative, but it takes up a lot of
space—five lines of output per changeset. The
<code class="literal">compact</code> style reduces this to three lines,
presented in a sparse manner.</p><pre id="id415023" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
3[tip] 65efccbd2729 2009-05-05 06:55 +0000 bos
Added tag v0.1 for changeset 59abc8be7140
2[v0.1] 59abc8be7140 2009-05-05 06:55 +0000 bos
Added tag mytag for changeset 107e439be01c
1[mytag] 107e439be01c 2009-05-05 06:55 +0000 bos
added line to end of &lt;&lt;hello&gt;&gt; file.
0 5ce2a492c569 2009-05-05 06:55 +0000 bos
added hello
</pre><p id="x_57c"><a name="x_57c"></a>The <code class="literal">changelog</code> style hints at the
expressive power of Mercurial's templating engine. This style
attempts to follow the GNU Project's changelog
guidelines[<span class="citation">web:changelog</span>].</p><pre id="id414997" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style changelog</code></strong>
2009-05-05 Bryan O'Sullivan &lt;bos@serpentine.com&gt;
* .hgtags:
Added tag v0.1 for changeset 59abc8be7140
[65efccbd2729] [tip]
* .hgtags:
Added tag mytag for changeset 107e439be01c
[59abc8be7140] [v0.1]
* goodbye, hello:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
[107e439be01c] [mytag]
* hello:
added hello
[5ce2a492c569]
</pre><p id="x_57d"><a name="x_57d"></a>You will not be shocked to learn that Mercurial's default
output style is named <code class="literal">default</code>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id414837">Setting a default style</h3></div></div></div><p id="x_57e"><a name="x_57e"></a>You can modify the output style that Mercurial will use
for every command by editing your <code class="filename">~/.hgrc</code> file, naming the style
you would prefer to use.</p><pre id="id414859" class="programlisting">[ui]
style = compact</pre><p id="x_57f"><a name="x_57f"></a>If you write a style of your own, you can use it by either
providing the path to your style file, or copying your style
file into a location where Mercurial can find it (typically
the <code class="literal">templates</code> subdirectory of your
Mercurial install directory).</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id414882">Commands that support styles and templates</h2></div></div></div><p id="x_580"><a name="x_580"></a>All of Mercurial's
<span class="quote"><code class="literal">log</code>-like</span>” commands let you use
styles and templates: <span class="command"><strong>hg
incoming</strong></span>, <span class="command"><strong>hg log</strong></span>,
<span class="command"><strong>hg outgoing</strong></span>, and <span class="command"><strong>hg tip</strong></span>.</p><p id="x_581"><a name="x_581"></a>As I write this manual, these are so far the only commands
that support styles and templates. Since these are the most
important commands that need customizable output, there has been
little pressure from the Mercurial user community to add style
and template support to other commands.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id414947">The basics of templating</h2></div></div></div><p id="x_582"><a name="x_582"></a>At its simplest, a Mercurial template is a piece of text.
Some of the text never changes, while other parts are
<span class="emphasis"><em>expanded</em></span>, or replaced with new text, when
necessary.</p><p id="x_583"><a name="x_583"></a>Before we continue, let's look again at a simple example of
Mercurial's normal output.</p><pre id="id415038" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1</code></strong>
changeset: 1:107e439be01c
tag: mytag
user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
date: Tue May 05 06:55:46 2009 +0000
summary: added line to end of &lt;&lt;hello&gt;&gt; file.
</pre><p id="x_584"><a name="x_584"></a>Now, let's run the same command, but using a template to
change its output.</p><pre id="id415404" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'i saw a changeset\n'</code></strong>
i saw a changeset
</pre><p id="x_585"><a name="x_585"></a>The example above illustrates the simplest possible
template; it's just a piece of static text, printed once for
each changeset. The <code class="option">--template</code> option to the <span class="command"><strong>hg log</strong></span> command tells Mercurial to use
the given text as the template when printing each
changeset.</p><p id="x_586"><a name="x_586"></a>Notice that the template string above ends with the text
<span class="quote"><code class="literal">\n</code></span>”. This is an
<span class="emphasis"><em>escape sequence</em></span>, telling Mercurial to print
a newline at the end of each template item. If you omit this
newline, Mercurial will run each piece of output together. See
<a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:escape" title="Escape sequences">the section called “Escape sequences”</a> for more details
of escape sequences.</p><p id="x_587"><a name="x_587"></a>A template that prints a fixed string of text all the time
isn't very useful; let's try something a bit more
complex.</p><pre id="id415110" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --template 'i saw a changeset: {desc}\n'</code></strong>
i saw a changeset: Added tag v0.1 for changeset 59abc8be7140
i saw a changeset: Added tag mytag for changeset 107e439be01c
i saw a changeset: added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
i saw a changeset: added hello
</pre><p id="x_588"><a name="x_588"></a>As you can see, the string
<span class="quote"><code class="literal">{desc}</code></span>” in the template has
been replaced in the output with the description of each
changeset. Every time Mercurial finds text enclosed in curly
braces (“<span class="quote"><code class="literal">{</code></span>” and
<span class="quote"><code class="literal">}</code></span>”), it will try to replace the
braces and text with the expansion of whatever is inside. To
print a literal curly brace, you must escape it, as described in
<a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:escape" title="Escape sequences">the section called “Escape sequences”</a>.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:keyword">Common template keywords</h2></div></div></div><p id="x_589"><a name="x_589"></a>You can start writing simple templates immediately using the
keywords below.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_58a"><a name="x_58a"></a><code class="literal">author</code>: String. The
unmodified author of the changeset.</p></li><li><p id="x_58b"><a name="x_58b"></a><code class="literal">branches</code>: String. The
name of the branch on which the changeset was committed.
Will be empty if the branch name was
<code class="literal">default</code>.</p></li><li><p id="x_58c"><a name="x_58c"></a><code class="literal">date</code>:
Date information. The date when the changeset was
committed. This is <span class="emphasis"><em>not</em></span> human-readable;
you must pass it through a filter that will render it
appropriately. See <a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:filter" title="Filtering keywords to change their results">the section called “Filtering keywords to change their results”</a> for more information
on filters. The date is expressed as a pair of numbers. The
first number is a Unix UTC timestamp (seconds since January
1, 1970); the second is the offset of the committer's
timezone from UTC, in seconds.</p></li><li><p id="x_58d"><a name="x_58d"></a><code class="literal">desc</code>:
String. The text of the changeset description.</p></li><li><p id="x_58e"><a name="x_58e"></a><code class="literal">files</code>: List of strings.
All files modified, added, or removed by this
changeset.</p></li><li><p id="x_58f"><a name="x_58f"></a><code class="literal">file_adds</code>: List of
strings. Files added by this changeset.</p></li><li><p id="x_590"><a name="x_590"></a><code class="literal">file_dels</code>: List of
strings. Files removed by this changeset.</p></li><li><p id="x_591"><a name="x_591"></a><code class="literal">node</code>:
String. The changeset identification hash, as a
40-character hexadecimal string.</p></li><li><p id="x_592"><a name="x_592"></a><code class="literal">parents</code>: List of
strings. The parents of the changeset.</p></li><li><p id="x_593"><a name="x_593"></a><code class="literal">rev</code>:
Integer. The repository-local changeset revision
number.</p></li><li><p id="x_594"><a name="x_594"></a><code class="literal">tags</code>:
List of strings. Any tags associated with the
changeset.</p></li></ul></div><p id="x_595"><a name="x_595"></a>A few simple experiments will show us what to expect when we
use these keywords; you can see the results below.</p><pre id="id415826" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'author: {author}\n'</code></strong>
author: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'desc:\n{desc}\n'</code></strong>
desc:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'files: {files}\n'</code></strong>
files: goodbye hello
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'file_adds: {file_adds}\n'</code></strong>
file_adds: goodbye
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'file_dels: {file_dels}\n'</code></strong>
file_dels:
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'node: {node}\n'</code></strong>
node: 107e439be01c456e8e32f719558cb7ea693b60fd
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'parents: {parents}\n'</code></strong>
parents:
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'rev: {rev}\n'</code></strong>
rev: 1
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'tags: {tags}\n'</code></strong>
tags: mytag
</pre><p id="x_596"><a name="x_596"></a>As we noted above, the date keyword does not produce
human-readable output, so we must treat it specially. This
involves using a <span class="emphasis"><em>filter</em></span>, about which more
in <a class="xref" href="customizing-the-output-of-mercurial.html#sec:template:filter" title="Filtering keywords to change their results">the section called “Filtering keywords to change their results”</a>.</p><pre id="id415717" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'date: {date}\n'</code></strong>
date: 1241506546.00
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'date: {date|isodate}\n'</code></strong>
date: 2009-05-05 06:55 +0000
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:escape">Escape sequences</h2></div></div></div><p id="x_597"><a name="x_597"></a>Mercurial's templating engine recognises the most commonly
used escape sequences in strings. When it sees a backslash
(“<span class="quote"><code class="literal">\</code></span>”) character, it looks at the
following character and substitutes the two characters with a
single replacement, as described below.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_598"><a name="x_598"></a><code class="literal">\</code>:
Backslash, “<span class="quote"><code class="literal">\</code></span>”, ASCII
134.</p></li><li><p id="x_599"><a name="x_599"></a><code class="literal">\n</code>: Newline,
ASCII 12.</p></li><li><p id="x_59a"><a name="x_59a"></a><code class="literal">\r</code>: Carriage
return, ASCII 15.</p></li><li><p id="x_59b"><a name="x_59b"></a><code class="literal">\t</code>: Tab, ASCII
11.</p></li><li><p id="x_59c"><a name="x_59c"></a><code class="literal">\v</code>: Vertical
tab, ASCII 13.</p></li><li><p id="x_59d"><a name="x_59d"></a><code class="literal">\{</code>: Open curly
brace, “<span class="quote"><code class="literal">{</code></span>”, ASCII
173.</p></li><li><p id="x_59e"><a name="x_59e"></a><code class="literal">\}</code>: Close curly
brace, “<span class="quote"><code class="literal">}</code></span>”, ASCII
175.</p></li></ul></div><p id="x_59f"><a name="x_59f"></a>As indicated above, if you want the expansion of a template
to contain a literal “<span class="quote"><code class="literal">\</code></span>”,
<span class="quote"><code class="literal">{</code></span>”, or
<span class="quote"><code class="literal">{</code></span>” character, you must escape
it.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:template:filter">Filtering keywords to change their results</h2></div></div></div><p id="x_5a0"><a name="x_5a0"></a>Some of the results of template expansion are not
immediately easy to use. Mercurial lets you specify an optional
chain of <span class="emphasis"><em>filters</em></span> to modify the result of
expanding a keyword. You have already seen a common filter,
<code class="literal">isodate</code>, in
action above, to make a date readable.</p><p id="x_5a1"><a name="x_5a1"></a>Below is a list of the most commonly used filters that
Mercurial supports. While some filters can be applied to any
text, others can only be used in specific circumstances. The
name of each filter is followed first by an indication of where
it can be used, then a description of its effect.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5a2"><a name="x_5a2"></a><code class="literal">addbreaks</code>: Any text. Add
an XHTML “<span class="quote"><code class="literal">&lt;br/&gt;</code></span>” tag
before the end of every line except the last. For example,
<span class="quote"><code class="literal">foo\nbar</code></span>” becomes
<span class="quote"><code class="literal">foo&lt;br/&gt;\nbar</code></span>”.</p></li><li><p id="x_5a3"><a name="x_5a3"></a><code class="literal">age</code>: <code class="literal">date</code> keyword. Render
the age of the date, relative to the current time. Yields a
string like “<span class="quote"><code class="literal">10
minutes</code></span>”.</p></li><li><p id="x_5a4"><a name="x_5a4"></a><code class="literal">basename</code>: Any text, but
most useful for the <code class="literal">files</code> keyword and its
relatives. Treat the text as a path, and return the
basename. For example,
<span class="quote"><code class="literal">foo/bar/baz</code></span>” becomes
<span class="quote"><code class="literal">baz</code></span>”.</p></li><li><p id="x_5a5"><a name="x_5a5"></a><code class="literal">date</code>: <code class="literal">date</code> keyword. Render a
date in a similar format to the Unix <code class="literal">date</code> command, but with
timezone included. Yields a string like “<span class="quote"><code class="literal">Mon
Sep 04 15:13:13 2006 -0700</code></span>”.</p></li><li><p id="x_5a6"><a name="x_5a6"></a><code class="literal">domain</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Finds
the first string that looks like an email address, and
extract just the domain component. For example,
<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">serpentine.com</code></span>”.</p></li><li><p id="x_5a7"><a name="x_5a7"></a><code class="literal">email</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Extract
the first string that looks like an email address. For
example, “<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">bos@serpentine.com</code></span>”.</p></li><li><p id="x_5a8"><a name="x_5a8"></a><code class="literal">escape</code>: Any text.
Replace the special XML/XHTML characters
<span class="quote"><code class="literal">&amp;</code></span>”,
<span class="quote"><code class="literal">&lt;</code></span>” and
<span class="quote"><code class="literal">&gt;</code></span>” with XML
entities.</p></li><li><p id="x_5a9"><a name="x_5a9"></a><code class="literal">fill68</code>: Any text. Wrap
the text to fit in 68 columns. This is useful before you
pass text through the <code class="literal">tabindent</code> filter, and
still want it to fit in an 80-column fixed-font
window.</p></li><li><p id="x_5aa"><a name="x_5aa"></a><code class="literal">fill76</code>: Any text. Wrap
the text to fit in 76 columns.</p></li><li><p id="x_5ab"><a name="x_5ab"></a><code class="literal">firstline</code>: Any text.
Yield the first line of text, without any trailing
newlines.</p></li><li><p id="x_5ac"><a name="x_5ac"></a><code class="literal">hgdate</code>: <code class="literal">date</code> keyword. Render
the date as a pair of readable numbers. Yields a string
like “<span class="quote"><code class="literal">1157407993
25200</code></span>”.</p></li><li><p id="x_5ad"><a name="x_5ad"></a><code class="literal">isodate</code>: <code class="literal">date</code> keyword. Render
the date as a text string in ISO 8601 format. Yields a
string like “<span class="quote"><code class="literal">2006-09-04 15:13:13
-0700</code></span>”.</p></li><li><p id="x_5ae"><a name="x_5ae"></a><code class="literal">obfuscate</code>: Any text, but
most useful for the <code class="literal">author</code> keyword. Yield
the input text rendered as a sequence of XML entities. This
helps to defeat some particularly stupid screen-scraping
email harvesting spambots.</p></li><li><p id="x_5af"><a name="x_5af"></a><code class="literal">person</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Yield
the text before an email address. For example,
<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">Bryan O'Sullivan</code></span>”.</p></li><li><p id="x_5b0"><a name="x_5b0"></a><code class="literal">rfc822date</code>:
<code class="literal">date</code> keyword.
Render a date using the same format used in email headers.
Yields a string like “<span class="quote"><code class="literal">Mon, 04 Sep 2006
15:13:13 -0700</code></span>”.</p></li><li><p id="x_5b1"><a name="x_5b1"></a><code class="literal">short</code>: Changeset
hash. Yield the short form of a changeset hash, i.e. a
12-character hexadecimal string.</p></li><li><p id="x_5b2"><a name="x_5b2"></a><code class="literal">shortdate</code>: <code class="literal">date</code> keyword. Render
the year, month, and day of the date. Yields a string like
<span class="quote"><code class="literal">2006-09-04</code></span>”.</p></li><li><p id="x_5b3"><a name="x_5b3"></a><code class="literal">strip</code>:
Any text. Strip all leading and trailing whitespace from
the string.</p></li><li><p id="x_5b4"><a name="x_5b4"></a><code class="literal">tabindent</code>: Any text.
Yield the text, with every line except the first starting
with a tab character.</p></li><li><p id="x_5b5"><a name="x_5b5"></a><code class="literal">urlescape</code>: Any text.
Escape all characters that are considered
<span class="quote">special</span>” by URL parsers. For example,
<code class="literal">foo bar</code> becomes
<code class="literal">foo%20bar</code>.</p></li><li><p id="x_5b6"><a name="x_5b6"></a><code class="literal">user</code>: Any text,
but most useful for the <code class="literal">author</code> keyword. Return
the “<span class="quote">user</span>” portion of an email address. For
example, “<span class="quote"><code class="literal">Bryan O'Sullivan
&lt;bos@serpentine.com&gt;</code></span>” becomes
<span class="quote"><code class="literal">bos</code></span>”.</p></li></ul></div><pre id="id417012" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author}\n'</code></strong>
Bryan O'Sullivan &lt;bos@serpentine.com&gt;
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|domain}\n'</code></strong>
serpentine.com
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|email}\n'</code></strong>
bos@serpentine.com
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</code></strong>
&amp;#66;&amp;#114;&amp;#121;&amp;#97;&amp;#110;&amp;#32;&amp;#79;&amp;#39;&amp;#83;&amp;#117;&amp;#108;&amp;#108;&amp;#105;&amp;#11
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|person}\n'</code></strong>
Bryan O'Sullivan
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{author|user}\n'</code></strong>
bos
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</code></strong>
looks almost right, but actually garbage: 1241506546.00
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|age}\n'</code></strong>
2 seconds
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|date}\n'</code></strong>
Tue May 05 06:55:46 2009 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|hgdate}\n'</code></strong>
1241506546 0
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|isodate}\n'</code></strong>
2009-05-05 06:55 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|rfc822date}\n'</code></strong>
Tue, 05 May 2009 06:55:46 +0000
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{date|shortdate}\n'</code></strong>
2009-05-05
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.&lt;br/&gt;
&lt;br/&gt;
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|escape}\n' | cut -c-76</code></strong>
added line to end of &amp;lt;&amp;lt;hello&amp;gt;&amp;gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|fill68}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|fill76}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some
might consider it so) of goodbye.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|firstline}\n'</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|strip}\n' | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope that some m
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</code></strong>
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope tha
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{node}\n'</code></strong>
107e439be01c456e8e32f719558cb7ea693b60fd
<code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template '{node|short}\n'</code></strong>
107e439be01c
</pre><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_5b7"><a name="x_5b7"></a> If you try to apply a filter to a piece of data that it
cannot process, Mercurial will fail and print a Python
exception. For example, trying to run the output of the
<code class="literal">desc</code> keyword into
the <code class="literal">isodate</code>
filter is not a good idea.</p></td></tr></table></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417290">Combining filters</h3></div></div></div><p id="x_5b8"><a name="x_5b8"></a>It is easy to combine filters to yield output in the form
you would like. The following chain of filters tidies up a
description, then makes sure that it fits cleanly into 68
columns, then indents it by a further 8 characters (at least
on Unix-like systems, where a tab is conventionally 8
characters wide).</p><pre id="id417653" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</code></strong>
description:
added line to end of &lt;&lt;hello&gt;&gt; file.
in addition, added a file with the helpful name (at least i hope
that some might consider it so) of goodbye.
</pre><p id="x_5b9"><a name="x_5b9"></a>Note the use of “<span class="quote"><code class="literal">\t</code></span>” (a
tab character) in the template to force the first line to be
indented; this is necessary since <code class="literal">tabindent</code> indents all
lines <span class="emphasis"><em>except</em></span> the first.</p><p id="x_5ba"><a name="x_5ba"></a>Keep in mind that the order of filters in a chain is
significant. The first filter is applied to the result of the
keyword; the second to the result of the first filter; and so
on. For example, using <code class="literal">fill68|tabindent</code>
gives very different results from
<code class="literal">tabindent|fill68</code>.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id417618">From templates to styles</h2></div></div></div><p id="x_5bb"><a name="x_5bb"></a>A command line template provides a quick and simple way to
format some output. Templates can become verbose, though, and
it's useful to be able to give a template a name. A style file
is a template with a name, stored in a file.</p><p id="x_5bc"><a name="x_5bc"></a>More than that, using a style file unlocks the power of
Mercurial's templating engine in ways that are not possible
using the command line <code class="option">--template</code> option.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417353">The simplest of style files</h3></div></div></div><p id="x_5bd"><a name="x_5bd"></a>Our simple style file contains just one line:</p><pre id="id417560" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo 'changeset = "rev: {rev}\n"' &gt; rev</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg log -l1 --style ./rev</code></strong>
rev: 3
</pre><p id="x_5be"><a name="x_5be"></a>This tells Mercurial, “<span class="quote">if you're printing a
changeset, use the text on the right as the
template</span>”.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417428">Style file syntax</h3></div></div></div><p id="x_5bf"><a name="x_5bf"></a>The syntax rules for a style file are simple.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5c0"><a name="x_5c0"></a>The file is processed one line at a
time.</p></li><li><p id="x_5c1"><a name="x_5c1"></a>Leading and trailing white space are
ignored.</p></li><li><p id="x_5c2"><a name="x_5c2"></a>Empty lines are skipped.</p></li><li><p id="x_5c3"><a name="x_5c3"></a>If a line starts with either of the characters
<span class="quote"><code class="literal">#</code></span>” or
<span class="quote"><code class="literal">;</code></span>”, the entire line is
treated as a comment, and skipped as if empty.</p></li><li><p id="x_5c4"><a name="x_5c4"></a>A line starts with a keyword. This must start
with an alphabetic character or underscore, and can
subsequently contain any alphanumeric character or
underscore. (In regexp notation, a keyword must match
<code class="literal">[A-Za-z_][A-Za-z0-9_]*</code>.)</p></li><li><p id="x_5c5"><a name="x_5c5"></a>The next element must be an
<span class="quote"><code class="literal">=</code></span>” character, which can
be preceded or followed by an arbitrary amount of white
space.</p></li><li><p id="x_5c6"><a name="x_5c6"></a>If the rest of the line starts and ends with
matching quote characters (either single or double quote),
it is treated as a template body.</p></li><li><p id="x_5c7"><a name="x_5c7"></a>If the rest of the line <span class="emphasis"><em>does
not</em></span> start with a quote character, it is
treated as the name of a file; the contents of this file
will be read and used as a template body.</p></li></ul></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id417656">Style files by example</h2></div></div></div><p id="x_5c8"><a name="x_5c8"></a>To illustrate how to write a style file, we will construct a
few by example. Rather than provide a complete style file and
walk through it, we'll mirror the usual process of developing a
style file by starting with something very simple, and walking
through a series of successively more complete examples.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417669">Identifying mistakes in style files</h3></div></div></div><p id="x_5c9"><a name="x_5c9"></a>If Mercurial encounters a problem in a style file you are
working on, it prints a terse error message that, once you
figure out what it means, is actually quite useful.</p><pre id="id418030" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat broken.style</code></strong>
changeset =
</pre><p id="x_5ca"><a name="x_5ca"></a>Notice that <code class="filename">broken.style</code> attempts to
define a <code class="literal">changeset</code> keyword, but forgets to
give any content for it. When instructed to use this style
file, Mercurial promptly complains.</p><pre id="id418015" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r1 --style broken.style</code></strong>
abort: broken.style:1: parse error
</pre><p id="x_5cb"><a name="x_5cb"></a>This error message looks intimidating, but it is not too
hard to follow.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5cc"><a name="x_5cc"></a>The first component is simply Mercurial's way
of saying “<span class="quote">I am giving up</span>”.</p><pre id="id417787" class="programlisting">___abort___: broken.style:1: parse error</pre></li><li><p id="x_5cd"><a name="x_5cd"></a>Next comes the name of the style file that
contains the error.</p><pre id="id417803" class="programlisting">abort: ___broken.style___:1: parse error</pre></li><li><p id="x_5ce"><a name="x_5ce"></a>Following the file name is the line number
where the error was encountered.</p><pre id="id417818" class="programlisting">abort: broken.style:___1___: parse error</pre></li><li><p id="x_5cf"><a name="x_5cf"></a>Finally, a description of what went
wrong.</p><pre id="id417834" class="programlisting">abort: broken.style:1: ___parse error___</pre></li><li><p id="x_5d0"><a name="x_5d0"></a>The description of the problem is not always
clear (as in this case), but even when it is cryptic, it
is almost always trivial to visually inspect the offending
line in the style file and see what is wrong.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417853">Uniquely identifying a repository</h3></div></div></div><p id="x_5d1"><a name="x_5d1"></a>If you would like to be able to identify a Mercurial
repository “<span class="quote">fairly uniquely</span>” using a short string
as an identifier, you can use the first revision in the
repository.</p><pre id="id418246" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log -r0 --template '{node}'</code></strong>
189e736977c29ea3835dfc7e332794a24f479c51</pre><p id="x_5d2"><a name="x_5d2"></a>This is likely to be unique, and so it is
useful in many cases. There are a few caveats.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5d3"><a name="x_5d3"></a>It will not work in a completely empty
repository, because such a repository does not have a
revision zero.</p></li><li><p id="x_5d4"><a name="x_5d4"></a>Neither will it work in the (extremely rare)
case where a repository is a merge of two or more formerly
independent repositories, and you still have those
repositories around.</p></li></ul></div><p id="x_5d5"><a name="x_5d5"></a>Here are some uses to which you could put this
identifier:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5d6"><a name="x_5d6"></a>As a key into a table for a database that
manages repositories on a server.</p></li><li><p id="x_5d7"><a name="x_5d7"></a>As half of a {<span class="emphasis"><em>repository
ID</em></span>, <span class="emphasis"><em>revision ID</em></span>} tuple.
Save this information away when you run an automated build
or other activity, so that you can “<span class="quote">replay</span>
the build later if necessary.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id417978">Listing files on multiple lines</h3></div></div></div><p id="x_714"><a name="x_714"></a>Suppose we want to list the files changed by a changeset,
one per line, with a little indentation before each file
name.</p><pre id="id418218" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat &gt; multiline &lt;&lt; EOF</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>changeset = "Changed in {node|short}:\n{files}"</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>file = " {file}\n"</code></strong>
<code class="prompt">&gt;</code> <strong class="userinput"><code>EOF</code></strong>
<code class="prompt">$</code> <strong class="userinput"><code>hg log --style multiline</code></strong>
Changed in ae47487e0fed:
.bashrc
.hgrc
test.c
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id418118">Mimicking Subversion's output</h3></div></div></div><p id="x_5d8"><a name="x_5d8"></a>Let's try to emulate the default output format used by
another revision control tool, Subversion.</p><pre id="id418182" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>svn log -r9653</code></strong>
------------------------------------------------------------------------
r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
On reporting a route error, also include the status for the error,
rather than indicating a status of 0 when an error has occurred.
Signed-off-by: Sean Hefty &lt;sean.hefty@intel.com&gt;
------------------------------------------------------------------------
</pre><p id="x_5d9"><a name="x_5d9"></a>Since Subversion's output style is fairly simple, it is
easy to copy-and-paste a hunk of its output into a file, and
replace the text produced above by Subversion with the
template values we'd like to see expanded.</p><pre id="id418368" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat svn.template</code></strong>
r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
{desc|strip|fill76}
------------------------------------------------------------------------
</pre><p id="x_5da"><a name="x_5da"></a>There are a few small ways in which this template deviates
from the output produced by Subversion.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_5db"><a name="x_5db"></a>Subversion prints a “<span class="quote">readable</span>
date (the “<span class="quote"><code class="literal">Wed, 27 Sep 2006</code></span>” in the
example output above) in parentheses. Mercurial's
templating engine does not provide a way to display a date
in this format without also printing the time and time
zone.</p></li><li><p id="x_5dc"><a name="x_5dc"></a>We emulate Subversion's printing of
<span class="quote">separator</span>” lines full of
<span class="quote"><code class="literal">-</code></span>” characters by ending
the template with such a line. We use the templating
engine's <code class="literal">header</code>
keyword to print a separator line as the first line of
output (see below), thus achieving similar output to
Subversion.</p></li><li><p id="x_5dd"><a name="x_5dd"></a>Subversion's output includes a count in the
header of the number of lines in the commit message. We
cannot replicate this in Mercurial; the templating engine
does not currently provide a filter that counts the number
of lines the template generates.</p></li></ul></div><p id="x_5de"><a name="x_5de"></a>It took me no more than a minute or two of work to replace
literal text from an example of Subversion's output with some
keywords and filters to give the template above. The style
file simply refers to the template.</p><pre id="id418351" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat svn.style</code></strong>
header = '------------------------------------------------------------------------\n\n'
changeset = svn.template
</pre><p id="x_5df"><a name="x_5df"></a>We could have included the text of the template file
directly in the style file by enclosing it in quotes and
replacing the newlines with
<span class="quote"><code class="literal">\n</code></span>” sequences, but it would
have made the style file too difficult to read. Readability
is a good guide when you're trying to decide whether some text
belongs in a style file, or in a template file that the style
file points to. If the style file will look too big or
cluttered if you insert a literal piece of text, drop it into
a template instead.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="handling-repository-events-with-hooks.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="managing-change-with-mercurial-queues.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 10. Handling repository events with hooks </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 12. Managing change with Mercurial Queues</td></tr></table></div><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-1805907-5");
pageTracker._trackPageview();
} catch(err) {}</script></body></html>