Mercurial > public > mercurial-scm > hg
comparison mercurial/formatter.py @ 31172:16272d8c24f6
formatter: add support for changeset templating
Some formatter-based commands provide fields that are identical to the ones
defined in templatekw, but we had to specify them manually to support all
changeset-based template keywords.
This patch adds fm.context() that populates all templatekw. These keywords
are available only in template output, so we still need to set important
keywords via fm.data() if they should be available in e.g. JSON output.
Currently fm.context() takes only 'ctx' argument. It will eventually be
extended to take 'fctx' to support file-based keywords (e.g. {path}) seen
in hgweb.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 25 Feb 2017 17:00:07 +0900 |
parents | e64b70c96338 |
children | 5660c45ecba6 |
comparison
equal
deleted
inserted
replaced
31171:1ec89cf0ea49 | 31172:16272d8c24f6 |
---|---|
10 The formatter provides API to show data in various ways. The following | 10 The formatter provides API to show data in various ways. The following |
11 functions should be used in place of ui.write(): | 11 functions should be used in place of ui.write(): |
12 | 12 |
13 - fm.write() for unconditional output | 13 - fm.write() for unconditional output |
14 - fm.condwrite() to show some extra data conditionally in plain output | 14 - fm.condwrite() to show some extra data conditionally in plain output |
15 - fm.context() to provide changectx to template output | |
15 - fm.data() to provide extra data to JSON or template output | 16 - 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 - fm.plain() to show raw text that isn't provided to JSON or template output |
17 | 18 |
18 To show structured data (e.g. date tuples, dicts, lists), apply fm.format*() | 19 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 beforehand so the data is converted to the appropriate data type. Use |
169 def formatlist(self, data, name, fmt='%s', sep=' '): | 170 def formatlist(self, data, name, fmt='%s', sep=' '): |
170 '''convert iterable to appropriate list format''' | 171 '''convert iterable to appropriate list format''' |
171 # name is mandatory argument for now, but it could be optional if | 172 # name is mandatory argument for now, but it could be optional if |
172 # we have default template keyword, e.g. {item} | 173 # we have default template keyword, e.g. {item} |
173 return self._converter.formatlist(data, name, fmt, sep) | 174 return self._converter.formatlist(data, name, fmt, sep) |
175 def context(self, **ctxs): | |
176 '''insert context objects to be used to render template keywords''' | |
177 pass | |
174 def data(self, **data): | 178 def data(self, **data): |
175 '''insert data into item that's not shown in default output''' | 179 '''insert data into item that's not shown in default output''' |
176 self._item.update(data) | 180 self._item.update(data) |
177 def write(self, fields, deftext, *fielddata, **opts): | 181 def write(self, fields, deftext, *fielddata, **opts): |
178 '''do default text output while assigning data to item''' | 182 '''do default text output while assigning data to item''' |
343 | 347 |
344 class templateformatter(baseformatter): | 348 class templateformatter(baseformatter): |
345 def __init__(self, ui, topic, opts): | 349 def __init__(self, ui, topic, opts): |
346 baseformatter.__init__(self, ui, topic, opts, _templateconverter) | 350 baseformatter.__init__(self, ui, topic, opts, _templateconverter) |
347 self._topic = topic | 351 self._topic = topic |
348 self._t = gettemplater(ui, topic, opts.get('template', '')) | 352 self._t = gettemplater(ui, topic, opts.get('template', ''), |
349 def _showitem(self): | 353 cache=templatekw.defaulttempl) |
350 g = self._t(self._topic, ui=self._ui, **self._item) | 354 self._cache = {} # for templatekw/funcs to store reusable data |
355 def context(self, **ctxs): | |
356 '''insert context objects to be used to render template keywords''' | |
357 assert all(k == 'ctx' for k in ctxs) | |
358 self._item.update(ctxs) | |
359 def _showitem(self): | |
360 # TODO: add support for filectx. probably each template keyword or | |
361 # function will have to declare dependent resources. e.g. | |
362 # @templatekeyword(..., requires=('ctx',)) | |
363 if 'ctx' in self._item: | |
364 props = templatekw.keywords.copy() | |
365 # explicitly-defined fields precede templatekw | |
366 props.update(self._item) | |
367 # but template resources must be always available | |
368 props['templ'] = self._t | |
369 props['repo'] = props['ctx'].repo() | |
370 props['revcache'] = {} | |
371 else: | |
372 props = self._item | |
373 g = self._t(self._topic, ui=self._ui, cache=self._cache, **props) | |
351 self._ui.write(templater.stringify(g)) | 374 self._ui.write(templater.stringify(g)) |
352 | 375 |
353 def lookuptemplate(ui, topic, tmpl): | 376 def lookuptemplate(ui, topic, tmpl): |
354 # looks like a literal template? | 377 # looks like a literal template? |
355 if '{' in tmpl: | 378 if '{' in tmpl: |
380 return tmpl, None | 403 return tmpl, None |
381 | 404 |
382 # constant string? | 405 # constant string? |
383 return tmpl, None | 406 return tmpl, None |
384 | 407 |
385 def gettemplater(ui, topic, spec): | 408 def gettemplater(ui, topic, spec, cache=None): |
386 tmpl, mapfile = lookuptemplate(ui, topic, spec) | 409 tmpl, mapfile = lookuptemplate(ui, topic, spec) |
387 assert not (tmpl and mapfile) | 410 assert not (tmpl and mapfile) |
388 if mapfile: | 411 if mapfile: |
389 return templater.templater.frommapfile(mapfile) | 412 return templater.templater.frommapfile(mapfile, cache=cache) |
390 return maketemplater(ui, topic, tmpl) | 413 return maketemplater(ui, topic, tmpl, cache=cache) |
391 | 414 |
392 def maketemplater(ui, topic, tmpl, cache=None): | 415 def maketemplater(ui, topic, tmpl, cache=None): |
393 """Create a templater from a string template 'tmpl'""" | 416 """Create a templater from a string template 'tmpl'""" |
394 aliases = ui.configitems('templatealias') | 417 aliases = ui.configitems('templatealias') |
395 t = templater.templater(cache=cache, aliases=aliases) | 418 t = templater.templater(cache=cache, aliases=aliases) |