##// END OF EJS Templates
formatter: add overview of API and example as doctest
Yuya Nishihara -
r30560:78301600 default
parent child Browse files
Show More
@@ -5,6 +5,101 b''
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """Generic output formatting for Mercurial
9
10 The formatter provides API to show data in various ways. The following
11 functions should be used in place of ui.write():
12
13 - fm.write() for unconditional output
14 - fm.condwrite() to show some extra data conditionally in plain output
15 - fm.data() to provide extra data to JSON or template output
16 - fm.plain() to show raw text that isn't provided to JSON or template output
17
18 To show structured data (e.g. date tuples, dicts, lists), apply fm.format*()
19 beforehand so the data is converted to the appropriate data type. Use
20 fm.isplain() if you need to convert or format data conditionally which isn't
21 supported by the formatter API.
22
23 To build nested structure (i.e. a list of dicts), use fm.nested().
24
25 See also https://www.mercurial-scm.org/wiki/GenericTemplatingPlan
26
27 fm.condwrite() vs 'if cond:':
28
29 In most cases, use fm.condwrite() so users can selectively show the data
30 in template output. If it's costly to build data, use plain 'if cond:' with
31 fm.write().
32
33 fm.nested() vs fm.formatdict() (or fm.formatlist()):
34
35 fm.nested() should be used to form a tree structure (a list of dicts of
36 lists of dicts...) which can be accessed through template keywords, e.g.
37 "{foo % "{bar % {...}} {baz % {...}}"}". On the other hand, fm.formatdict()
38 exports a dict-type object to template, which can be accessed by e.g.
39 "{get(foo, key)}" function.
40
41 Doctest helper:
42
43 >>> def show(fn, verbose=False, **opts):
44 ... import sys
45 ... from . import ui as uimod
46 ... ui = uimod.ui()
47 ... ui.fout = sys.stdout # redirect to doctest
48 ... ui.verbose = verbose
49 ... return fn(ui, ui.formatter(fn.__name__, opts))
50
51 Basic example:
52
53 >>> def files(ui, fm):
54 ... files = [('foo', 123, (0, 0)), ('bar', 456, (1, 0))]
55 ... for f in files:
56 ... fm.startitem()
57 ... fm.write('path', '%s', f[0])
58 ... fm.condwrite(ui.verbose, 'date', ' %s',
59 ... fm.formatdate(f[2], '%Y-%m-%d %H:%M:%S'))
60 ... fm.data(size=f[1])
61 ... fm.plain('\\n')
62 ... fm.end()
63 >>> show(files)
64 foo
65 bar
66 >>> show(files, verbose=True)
67 foo 1970-01-01 00:00:00
68 bar 1970-01-01 00:00:01
69 >>> show(files, template='json')
70 [
71 {
72 "date": [0, 0],
73 "path": "foo",
74 "size": 123
75 },
76 {
77 "date": [1, 0],
78 "path": "bar",
79 "size": 456
80 }
81 ]
82 >>> show(files, template='path: {path}\\ndate: {date|rfc3339date}\\n')
83 path: foo
84 date: 1970-01-01T00:00:00+00:00
85 path: bar
86 date: 1970-01-01T00:00:01+00:00
87
88 Nested example:
89
90 >>> def subrepos(ui, fm):
91 ... fm.startitem()
92 ... fm.write('repo', '[%s]\\n', 'baz')
93 ... files(ui, fm.nested('files'))
94 ... fm.end()
95 >>> show(subrepos)
96 [baz]
97 foo
98 bar
99 >>> show(subrepos, template='{repo}: {join(files % "{path}", ", ")}\\n')
100 baz: foo, bar
101 """
102
8 from __future__ import absolute_import
103 from __future__ import absolute_import
9
104
10 import os
105 import os
@@ -20,6 +20,7 b" testmod('mercurial.changelog')"
20 testmod('mercurial.dagparser', optionflags=doctest.NORMALIZE_WHITESPACE)
20 testmod('mercurial.dagparser', optionflags=doctest.NORMALIZE_WHITESPACE)
21 testmod('mercurial.dispatch')
21 testmod('mercurial.dispatch')
22 testmod('mercurial.encoding')
22 testmod('mercurial.encoding')
23 testmod('mercurial.formatter')
23 testmod('mercurial.hg')
24 testmod('mercurial.hg')
24 testmod('mercurial.hgweb.hgwebdir_mod')
25 testmod('mercurial.hgweb.hgwebdir_mod')
25 testmod('mercurial.match')
26 testmod('mercurial.match')
General Comments 0
You need to be logged in to leave comments. Login now