##// END OF EJS Templates
formatter: add a method to build a full templater from a -T option
Matt Mackall -
r25512:8463433c default
parent child Browse files
Show More
@@ -1,188 +1,195 b''
1 1 # formatter.py - generic output formatting for mercurial
2 2 #
3 3 # Copyright 2012 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 import cPickle
9 9 from node import hex, short
10 10 from i18n import _
11 11 import encoding, util
12 12 import templater
13 13 import os
14 14
15 15 class baseformatter(object):
16 16 def __init__(self, ui, topic, opts):
17 17 self._ui = ui
18 18 self._topic = topic
19 19 self._style = opts.get("style")
20 20 self._template = opts.get("template")
21 21 self._item = None
22 22 # function to convert node to string suitable for this output
23 23 self.hexfunc = hex
24 24 def __nonzero__(self):
25 25 '''return False if we're not doing real templating so we can
26 26 skip extra work'''
27 27 return True
28 28 def _showitem(self):
29 29 '''show a formatted item once all data is collected'''
30 30 pass
31 31 def startitem(self):
32 32 '''begin an item in the format list'''
33 33 if self._item is not None:
34 34 self._showitem()
35 35 self._item = {}
36 36 def data(self, **data):
37 37 '''insert data into item that's not shown in default output'''
38 38 self._item.update(data)
39 39 def write(self, fields, deftext, *fielddata, **opts):
40 40 '''do default text output while assigning data to item'''
41 41 for k, v in zip(fields.split(), fielddata):
42 42 self._item[k] = v
43 43 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
44 44 '''do conditional write (primarily for plain formatter)'''
45 45 for k, v in zip(fields.split(), fielddata):
46 46 self._item[k] = v
47 47 def plain(self, text, **opts):
48 48 '''show raw text for non-templated mode'''
49 49 pass
50 50 def end(self):
51 51 '''end output for the formatter'''
52 52 if self._item is not None:
53 53 self._showitem()
54 54
55 55 class plainformatter(baseformatter):
56 56 '''the default text output scheme'''
57 57 def __init__(self, ui, topic, opts):
58 58 baseformatter.__init__(self, ui, topic, opts)
59 59 if ui.debugflag:
60 60 self.hexfunc = hex
61 61 else:
62 62 self.hexfunc = short
63 63 def __nonzero__(self):
64 64 return False
65 65 def startitem(self):
66 66 pass
67 67 def data(self, **data):
68 68 pass
69 69 def write(self, fields, deftext, *fielddata, **opts):
70 70 self._ui.write(deftext % fielddata, **opts)
71 71 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
72 72 '''do conditional write'''
73 73 if cond:
74 74 self._ui.write(deftext % fielddata, **opts)
75 75 def plain(self, text, **opts):
76 76 self._ui.write(text, **opts)
77 77 def end(self):
78 78 pass
79 79
80 80 class debugformatter(baseformatter):
81 81 def __init__(self, ui, topic, opts):
82 82 baseformatter.__init__(self, ui, topic, opts)
83 83 self._ui.write("%s = [\n" % self._topic)
84 84 def _showitem(self):
85 85 self._ui.write(" " + repr(self._item) + ",\n")
86 86 def end(self):
87 87 baseformatter.end(self)
88 88 self._ui.write("]\n")
89 89
90 90 class pickleformatter(baseformatter):
91 91 def __init__(self, ui, topic, opts):
92 92 baseformatter.__init__(self, ui, topic, opts)
93 93 self._data = []
94 94 def _showitem(self):
95 95 self._data.append(self._item)
96 96 def end(self):
97 97 baseformatter.end(self)
98 98 self._ui.write(cPickle.dumps(self._data))
99 99
100 100 def _jsonifyobj(v):
101 101 if isinstance(v, tuple):
102 102 return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']'
103 103 elif v is None:
104 104 return 'null'
105 105 elif v is True:
106 106 return 'true'
107 107 elif v is False:
108 108 return 'false'
109 109 elif isinstance(v, (int, float)):
110 110 return str(v)
111 111 else:
112 112 return '"%s"' % encoding.jsonescape(v)
113 113
114 114 class jsonformatter(baseformatter):
115 115 def __init__(self, ui, topic, opts):
116 116 baseformatter.__init__(self, ui, topic, opts)
117 117 self._ui.write("[")
118 118 self._ui._first = True
119 119 def _showitem(self):
120 120 if self._ui._first:
121 121 self._ui._first = False
122 122 else:
123 123 self._ui.write(",")
124 124
125 125 self._ui.write("\n {\n")
126 126 first = True
127 127 for k, v in sorted(self._item.items()):
128 128 if first:
129 129 first = False
130 130 else:
131 131 self._ui.write(",\n")
132 132 self._ui.write(' "%s": %s' % (k, _jsonifyobj(v)))
133 133 self._ui.write("\n }")
134 134 def end(self):
135 135 baseformatter.end(self)
136 136 self._ui.write("\n]\n")
137 137
138 138 def lookuptemplate(ui, topic, tmpl):
139 139 # looks like a literal template?
140 140 if '{' in tmpl:
141 141 return tmpl, None
142 142
143 143 # perhaps a stock style?
144 144 if not os.path.split(tmpl)[0]:
145 145 mapname = (templater.templatepath('map-cmdline.' + tmpl)
146 146 or templater.templatepath(tmpl))
147 147 if mapname and os.path.isfile(mapname):
148 148 return None, mapname
149 149
150 150 # perhaps it's a reference to [templates]
151 151 t = ui.config('templates', tmpl)
152 152 if t:
153 153 try:
154 154 tmpl = templater.unquotestring(t)
155 155 except SyntaxError:
156 156 tmpl = t
157 157 return tmpl, None
158 158
159 159 if tmpl == 'list':
160 160 ui.write(_("available styles: %s\n") % templater.stylelist())
161 161 raise util.Abort(_("specify a template"))
162 162
163 163 # perhaps it's a path to a map or a template
164 164 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
165 165 # is it a mapfile for a style?
166 166 if os.path.basename(tmpl).startswith("map-"):
167 167 return None, os.path.realpath(tmpl)
168 168 tmpl = open(tmpl).read()
169 169 return tmpl, None
170 170
171 171 # constant string?
172 172 return tmpl, None
173 173
174 def gettemplater(ui, topic, spec):
175 tmpl, mapfile = lookuptemplate(ui, topic, spec)
176 t = templater.templater(mapfile, {})
177 if tmpl:
178 t.cache[topic] = tmpl
179 return t
180
174 181 def formatter(ui, topic, opts):
175 182 template = opts.get("template", "")
176 183 if template == "json":
177 184 return jsonformatter(ui, topic, opts)
178 185 elif template == "pickle":
179 186 return pickleformatter(ui, topic, opts)
180 187 elif template == "debug":
181 188 return debugformatter(ui, topic, opts)
182 189 elif template != "":
183 190 raise util.Abort(_("custom templates not yet supported"))
184 191 elif ui.configbool('ui', 'formatdebug'):
185 192 return debugformatter(ui, topic, opts)
186 193 elif ui.configbool('ui', 'formatjson'):
187 194 return jsonformatter(ui, topic, opts)
188 195 return plainformatter(ui, topic, opts)
General Comments 0
You need to be logged in to leave comments. Login now