mercurial/formatter.py
author Sune Foldager <cryo@cyanite.org>
Wed, 04 Jul 2018 14:19:13 +0200
branchstable
changeset 37882 3a0f322af192
parent 37770 31750413f8d7
child 37887 395571419274
permissions -rw-r--r--
windows: fix incorrect detection of broken pipe when writing to pager Paging e.g. hg incoming on Windows and quitting the pager before the output is consumed will print 'abort: Invalid argument'. This is because the windows error 0xE8 (ERROR_NO_DATA) is mapped to EINVAL even though it is documented as 'The pipe is being closed'. Note that this fix assumes that Windows' last error code is still valid in the exception handler. It works correctly in all my tests. A simpler fix would be to just map EINVAL to EPIPE, like was done is flush previously, but that would be less precise. This error was not observed previously, when pager was an extension.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# formatter.py - generic output formatting for mercurial
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2012 Matt Mackall <mpm@selenic.com>
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
     8
"""Generic output formatting for Mercurial
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
     9
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    10
The formatter provides API to show data in various ways. The following
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    11
functions should be used in place of ui.write():
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    12
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    13
- fm.write() for unconditional output
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    14
- fm.condwrite() to show some extra data conditionally in plain output
31182
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31180
diff changeset
    15
- fm.context() to provide changectx to template output
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    16
- fm.data() to provide extra data to JSON or template output
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    17
- fm.plain() to show raw text that isn't provided to JSON or template output
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    18
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    19
To show structured data (e.g. date tuples, dicts, lists), apply fm.format*()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    20
beforehand so the data is converted to the appropriate data type. Use
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    21
fm.isplain() if you need to convert or format data conditionally which isn't
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    22
supported by the formatter API.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    23
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    24
To build nested structure (i.e. a list of dicts), use fm.nested().
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    25
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    26
See also https://www.mercurial-scm.org/wiki/GenericTemplatingPlan
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    27
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    28
fm.condwrite() vs 'if cond:':
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    29
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    30
In most cases, use fm.condwrite() so users can selectively show the data
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    31
in template output. If it's costly to build data, use plain 'if cond:' with
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    32
fm.write().
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    33
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    34
fm.nested() vs fm.formatdict() (or fm.formatlist()):
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    35
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    36
fm.nested() should be used to form a tree structure (a list of dicts of
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    37
lists of dicts...) which can be accessed through template keywords, e.g.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    38
"{foo % "{bar % {...}} {baz % {...}}"}". On the other hand, fm.formatdict()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    39
exports a dict-type object to template, which can be accessed by e.g.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    40
"{get(foo, key)}" function.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    41
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    42
Doctest helper:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    43
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    44
>>> def show(fn, verbose=False, **opts):
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    45
...     import sys
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    46
...     from . import ui as uimod
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    47
...     ui = uimod.ui()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    48
...     ui.verbose = verbose
34262
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
    49
...     ui.pushbuffer()
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
    50
...     try:
34263
ebe3d0095c69 py3: convert system strings to bytes in doctest of formatter.py
Yuya Nishihara <yuya@tcha.org>
parents: 34262
diff changeset
    51
...         return fn(ui, ui.formatter(pycompat.sysbytes(fn.__name__),
ebe3d0095c69 py3: convert system strings to bytes in doctest of formatter.py
Yuya Nishihara <yuya@tcha.org>
parents: 34262
diff changeset
    52
...                   pycompat.byteskwargs(opts)))
34262
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
    53
...     finally:
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
    54
...         print(pycompat.sysstr(ui.popbuffer()), end='')
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    55
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    56
Basic example:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    57
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    58
>>> def files(ui, fm):
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    59
...     files = [(b'foo', 123, (0, 0)), (b'bar', 456, (1, 0))]
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    60
...     for f in files:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    61
...         fm.startitem()
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    62
...         fm.write(b'path', b'%s', f[0])
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    63
...         fm.condwrite(ui.verbose, b'date', b'  %s',
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    64
...                      fm.formatdate(f[2], b'%Y-%m-%d %H:%M:%S'))
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    65
...         fm.data(size=f[1])
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    66
...         fm.plain(b'\\n')
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    67
...     fm.end()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    68
>>> show(files)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    69
foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    70
bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    71
>>> show(files, verbose=True)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    72
foo  1970-01-01 00:00:00
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    73
bar  1970-01-01 00:00:01
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    74
>>> show(files, template=b'json')
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    75
[
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    76
 {
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    77
  "date": [0, 0],
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    78
  "path": "foo",
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    79
  "size": 123
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    80
 },
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    81
 {
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    82
  "date": [1, 0],
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    83
  "path": "bar",
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    84
  "size": 456
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    85
 }
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    86
]
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33102
diff changeset
    87
>>> show(files, template=b'path: {path}\\ndate: {date|rfc3339date}\\n')
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    88
path: foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    89
date: 1970-01-01T00:00:00+00:00
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    90
path: bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    91
date: 1970-01-01T00:00:01+00:00
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    92
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    93
Nested example:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    94
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    95
>>> def subrepos(ui, fm):
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    96
...     fm.startitem()
35474
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35473
diff changeset
    97
...     fm.write(b'reponame', b'[%s]\\n', b'baz')
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
    98
...     files(ui, fm.nested(b'files', tmpl=b'{reponame}'))
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
    99
...     fm.end()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   100
>>> show(subrepos)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   101
[baz]
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   102
foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   103
bar
35474
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35473
diff changeset
   104
>>> show(subrepos, template=b'{reponame}: {join(files % "{path}", ", ")}\\n')
30565
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   105
baz: foo, bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   106
"""
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29953
diff changeset
   107
34262
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   108
from __future__ import absolute_import, print_function
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   109
32856
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32853
diff changeset
   110
import collections
32606
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   111
import contextlib
31807
e6eb86b154c5 templater: provide loop counter as "index" keyword
Yuya Nishihara <yuya@tcha.org>
parents: 31805
diff changeset
   112
import itertools
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   113
import os
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   114
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   115
from .i18n import _
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   116
from .node import (
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   117
    hex,
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   118
    short,
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   119
)
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   120
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   121
from . import (
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26373
diff changeset
   122
    error,
32208
0fd15522a848 py3: use pycompat.byteskwargs to converts kwargs to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31925
diff changeset
   123
    pycompat,
31785
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31405
diff changeset
   124
    templatefilters,
29690
c3a9cd78b151 formatter: add function to convert list to appropriate format (issue5217)
Yuya Nishihara <yuya@tcha.org>
parents: 29324
diff changeset
   125
    templatekw,
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   126
    templater,
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36663
diff changeset
   127
    templateutil,
29324
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   128
    util,
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   129
)
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36475
diff changeset
   130
from .utils import dateutil
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   131
29324
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   132
pickle = util.pickle
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   133
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   134
class _nullconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   135
    '''convert non-primitive data types to be processed by formatter'''
33102
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   136
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   137
    # set to True if context object should be stored as item
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   138
    storecontext = False
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   139
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   140
    @staticmethod
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   141
    def wrapnested(data, tmpl, sep):
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   142
        '''wrap nested data by appropriate type'''
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   143
        return data
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   144
    @staticmethod
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   145
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   146
        '''convert date tuple to appropriate format'''
37770
31750413f8d7 formatter: convert timestamp to int
Yuya Nishihara <yuya@tcha.org>
parents: 37597
diff changeset
   147
        # timestamp can be float, but the canonical form should be int
31750413f8d7 formatter: convert timestamp to int
Yuya Nishihara <yuya@tcha.org>
parents: 37597
diff changeset
   148
        ts, tz = date
31750413f8d7 formatter: convert timestamp to int
Yuya Nishihara <yuya@tcha.org>
parents: 37597
diff changeset
   149
        return (int(ts), tz)
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   150
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   151
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   152
        '''convert dict or key-value pairs to appropriate dict format'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   153
        # use plain dict instead of util.sortdict so that data can be
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   154
        # serialized as a builtin dict in pickle output
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   155
        return dict(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   156
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   157
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   158
        '''convert iterable to appropriate list format'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   159
        return list(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   160
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
class baseformatter(object):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   162
    def __init__(self, ui, topic, opts, converter):
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   163
        self._ui = ui
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   164
        self._topic = topic
37597
d110167610db formatter: carry opts to file-based formatters by basefm
Yuya Nishihara <yuya@tcha.org>
parents: 37596
diff changeset
   165
        self._opts = opts
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   166
        self._converter = converter
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   167
        self._item = None
22701
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   168
        # function to convert node to string suitable for this output
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   169
        self.hexfunc = hex
29886
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29848
diff changeset
   170
    def __enter__(self):
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29848
diff changeset
   171
        return self
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29848
diff changeset
   172
    def __exit__(self, exctype, excvalue, traceback):
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29848
diff changeset
   173
        if exctype is None:
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29848
diff changeset
   174
            self.end()
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
    def _showitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   176
        '''show a formatted item once all data is collected'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   177
    def startitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   178
        '''begin an item in the format list'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   179
        if self._item is not None:
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   180
            self._showitem()
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
        self._item = {}
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   182
    def formatdate(self, date, fmt='%a %b %d %H:%M:%S %Y %1%2'):
29692
2f3f18ad55a2 formatter: add function to convert date tuple to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29690
diff changeset
   183
        '''convert date tuple to appropriate format'''
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   184
        return self._converter.formatdate(date, fmt)
36662
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   185
    def formatdict(self, data, key='key', value='value', fmt=None, sep=' '):
29805
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   186
        '''convert dict or key-value pairs to appropriate dict format'''
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   187
        return self._converter.formatdict(data, key, value, fmt, sep)
36662
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   188
    def formatlist(self, data, name, fmt=None, sep=' '):
29690
c3a9cd78b151 formatter: add function to convert list to appropriate format (issue5217)
Yuya Nishihara <yuya@tcha.org>
parents: 29324
diff changeset
   189
        '''convert iterable to appropriate list format'''
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   190
        # name is mandatory argument for now, but it could be optional if
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   191
        # we have default template keyword, e.g. {item}
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   192
        return self._converter.formatlist(data, name, fmt, sep)
31182
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31180
diff changeset
   193
    def context(self, **ctxs):
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31180
diff changeset
   194
        '''insert context objects to be used to render template keywords'''
33102
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   195
        ctxs = pycompat.byteskwargs(ctxs)
36987
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   196
        assert all(k in {'ctx', 'fctx'} for k in ctxs)
33102
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   197
        if self._converter.storecontext:
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   198
            self._item.update(ctxs)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   199
    def data(self, **data):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   200
        '''insert data into item that's not shown in default output'''
32208
0fd15522a848 py3: use pycompat.byteskwargs to converts kwargs to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31925
diff changeset
   201
        data = pycompat.byteskwargs(data)
17630
ff5ed1ecd43a formatter: improve implementation of data method
David M. Carr <david@carrclan.us>
parents: 17597
diff changeset
   202
        self._item.update(data)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   203
    def write(self, fields, deftext, *fielddata, **opts):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   204
        '''do default text output while assigning data to item'''
26372
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   205
        fieldkeys = fields.split()
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   206
        assert len(fieldkeys) == len(fielddata)
26373
aa610ffad4e8 formatter: use dict.update() to set arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 26372
diff changeset
   207
        self._item.update(zip(fieldkeys, fielddata))
17909
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   208
    def condwrite(self, cond, fields, deftext, *fielddata, **opts):
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   209
        '''do conditional write (primarily for plain formatter)'''
26372
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   210
        fieldkeys = fields.split()
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   211
        assert len(fieldkeys) == len(fielddata)
26373
aa610ffad4e8 formatter: use dict.update() to set arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 26372
diff changeset
   212
        self._item.update(zip(fieldkeys, fielddata))
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   213
    def plain(self, text, **opts):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
        '''show raw text for non-templated mode'''
29953
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29886
diff changeset
   215
    def isplain(self):
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29886
diff changeset
   216
        '''check for plain formatter usage'''
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29886
diff changeset
   217
        return False
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   218
    def nested(self, field, tmpl=None, sep=''):
29848
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   219
        '''sub formatter to store nested data in the specified field'''
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   220
        data = []
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   221
        self._item[field] = self._converter.wrapnested(data, tmpl, sep)
29848
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   222
        return _nestedformatter(self._ui, self._converter, data)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   223
    def end(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   224
        '''end output for the formatter'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   225
        if self._item is not None:
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   226
            self._showitem()
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   227
37597
d110167610db formatter: carry opts to file-based formatters by basefm
Yuya Nishihara <yuya@tcha.org>
parents: 37596
diff changeset
   228
def nullformatter(ui, topic, opts):
32607
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32606
diff changeset
   229
    '''formatter that prints nothing'''
37597
d110167610db formatter: carry opts to file-based formatters by basefm
Yuya Nishihara <yuya@tcha.org>
parents: 37596
diff changeset
   230
    return baseformatter(ui, topic, opts, converter=_nullconverter)
32607
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32606
diff changeset
   231
29848
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   232
class _nestedformatter(baseformatter):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   233
    '''build sub items and store them in the parent formatter'''
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   234
    def __init__(self, ui, converter, data):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   235
        baseformatter.__init__(self, ui, topic='', opts={}, converter=converter)
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   236
        self._data = data
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   237
    def _showitem(self):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   238
        self._data.append(self._item)
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   239
29805
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   240
def _iteritems(data):
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   241
    '''iterate key-value pairs in stable order'''
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   242
    if isinstance(data, dict):
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   243
        return sorted(data.iteritems())
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   244
    return data
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29692
diff changeset
   245
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   246
class _plainconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   247
    '''convert non-primitive data types to text'''
33102
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   248
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   249
    storecontext = False
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   250
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   251
    @staticmethod
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   252
    def wrapnested(data, tmpl, sep):
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   253
        raise error.ProgrammingError('plainformatter should never be nested')
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   254
    @staticmethod
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   255
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   256
        '''stringify date tuple in the given format'''
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36475
diff changeset
   257
        return dateutil.datestr(date, fmt)
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   258
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   259
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   260
        '''stringify key-value pairs separated by sep'''
36663
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   261
        prefmt = pycompat.identity
36662
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   262
        if fmt is None:
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   263
            fmt = '%s=%s'
36663
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   264
            prefmt = pycompat.bytestr
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   265
        return sep.join(fmt % (prefmt(k), prefmt(v))
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   266
                        for k, v in _iteritems(data))
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   267
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   268
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   269
        '''stringify iterable separated by sep'''
36663
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   270
        prefmt = pycompat.identity
36662
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   271
        if fmt is None:
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   272
            fmt = '%s'
36663
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   273
            prefmt = pycompat.bytestr
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36662
diff changeset
   274
        return sep.join(fmt % prefmt(e) for e in data)
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   275
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   276
class plainformatter(baseformatter):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   277
    '''the default text output scheme'''
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   278
    def __init__(self, ui, out, topic, opts):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   279
        baseformatter.__init__(self, ui, topic, opts, _plainconverter)
22701
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   280
        if ui.debugflag:
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   281
            self.hexfunc = hex
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   282
        else:
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   283
            self.hexfunc = short
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   284
        if ui is out:
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   285
            self._write = ui.write
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   286
        else:
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   287
            self._write = lambda s, **opts: out.write(s)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   288
    def startitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   289
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   290
    def data(self, **data):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   291
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   292
    def write(self, fields, deftext, *fielddata, **opts):
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   293
        self._write(deftext % fielddata, **opts)
17909
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   294
    def condwrite(self, cond, fields, deftext, *fielddata, **opts):
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   295
        '''do conditional write'''
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   296
        if cond:
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   297
            self._write(deftext % fielddata, **opts)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   298
    def plain(self, text, **opts):
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   299
        self._write(text, **opts)
29953
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29886
diff changeset
   300
    def isplain(self):
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29886
diff changeset
   301
        return True
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   302
    def nested(self, field, tmpl=None, sep=''):
29848
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   303
        # nested data will be directly written to ui
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29847
diff changeset
   304
        return self
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   305
    def end(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   306
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   307
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   308
class debugformatter(baseformatter):
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   309
    def __init__(self, ui, out, topic, opts):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   310
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   311
        self._out = out
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   312
        self._out.write("%s = [\n" % self._topic)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   313
    def _showitem(self):
36298
b44fac3a49fb py3: factor out byterepr() which returns an asciified value on py3
Yuya Nishihara <yuya@tcha.org>
parents: 36078
diff changeset
   314
        self._out.write('    %s,\n' % pycompat.byterepr(self._item))
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   315
    def end(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   316
        baseformatter.end(self)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   317
        self._out.write("]\n")
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   318
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   319
class pickleformatter(baseformatter):
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   320
    def __init__(self, ui, out, topic, opts):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   321
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   322
        self._out = out
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   323
        self._data = []
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   324
    def _showitem(self):
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   325
        self._data.append(self._item)
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   326
    def end(self):
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   327
        baseformatter.end(self)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   328
        self._out.write(pickle.dumps(self._data))
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   329
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   330
class jsonformatter(baseformatter):
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   331
    def __init__(self, ui, out, topic, opts):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   332
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   333
        self._out = out
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   334
        self._out.write("[")
31307
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31192
diff changeset
   335
        self._first = True
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   336
    def _showitem(self):
31307
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31192
diff changeset
   337
        if self._first:
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31192
diff changeset
   338
            self._first = False
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   339
        else:
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   340
            self._out.write(",")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   341
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   342
        self._out.write("\n {\n")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   343
        first = True
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   344
        for k, v in sorted(self._item.items()):
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   345
            if first:
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   346
                first = False
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   347
            else:
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   348
                self._out.write(",\n")
31785
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31405
diff changeset
   349
            u = templatefilters.json(v, paranoid=False)
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31405
diff changeset
   350
            self._out.write('  "%s": %s' % (k, u))
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   351
        self._out.write("\n }")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   352
    def end(self):
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   353
        baseformatter.end(self)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   354
        self._out.write("\n]\n")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   355
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   356
class _templateconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   357
    '''convert non-primitive data types to be processed by templater'''
33102
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   358
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   359
    storecontext = True
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32970
diff changeset
   360
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   361
    @staticmethod
37500
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   362
    def wrapnested(data, tmpl, sep):
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   363
        '''wrap nested data by templatable type'''
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   364
        return templateutil.mappinglist(data, tmpl=tmpl, sep=sep)
8bb3899a0f47 formatter: make nested items somewhat readable in template output
Yuya Nishihara <yuya@tcha.org>
parents: 37108
diff changeset
   365
    @staticmethod
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   366
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   367
        '''return date tuple'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   368
        return date
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   369
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   370
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   371
        '''build object that can be evaluated as either plain string or dict'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   372
        data = util.sortdict(_iteritems(data))
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   373
        def f():
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   374
            yield _plainconverter.formatdict(data, key, value, fmt, sep)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   375
        return templateutil.hybriddict(data, key=key, value=value, fmt=fmt,
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   376
                                       gen=f)
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   377
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   378
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   379
        '''build object that can be evaluated as either plain string or list'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   380
        data = list(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   381
        def f():
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   382
            yield _plainconverter.formatlist(data, name, fmt, sep)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   383
        return templateutil.hybridlist(data, name=name, fmt=fmt, gen=f)
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   384
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   385
class templateformatter(baseformatter):
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   386
    def __init__(self, ui, out, topic, opts):
29847
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29805
diff changeset
   387
        baseformatter.__init__(self, ui, topic, opts, _templateconverter)
31192
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31182
diff changeset
   388
        self._out = out
32851
99df35499cae formatter: inline gettemplater()
Yuya Nishihara <yuya@tcha.org>
parents: 32850
diff changeset
   389
        spec = lookuptemplate(ui, topic, opts.get('template', ''))
32859
883adaea9e80 formatter: render template specified by templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32858
diff changeset
   390
        self._tref = spec.ref
35487
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   391
        self._t = loadtemplater(ui, spec, defaults=templatekw.keywords,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   392
                                resources=templateresources(ui),
35473
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35472
diff changeset
   393
                                cache=templatekw.defaulttempl)
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   394
        self._parts = templatepartsmap(spec, self._t,
32968
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32967
diff changeset
   395
                                       ['docheader', 'docfooter', 'separator'])
31807
e6eb86b154c5 templater: provide loop counter as "index" keyword
Yuya Nishihara <yuya@tcha.org>
parents: 31805
diff changeset
   396
        self._counter = itertools.count()
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   397
        self._renderitem('docheader', {})
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   398
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   399
    def _showitem(self):
32966
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32915
diff changeset
   400
        item = self._item.copy()
32968
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32967
diff changeset
   401
        item['index'] = index = next(self._counter)
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32967
diff changeset
   402
        if index > 0:
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32967
diff changeset
   403
            self._renderitem('separator', {})
32966
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32915
diff changeset
   404
        self._renderitem(self._tref, item)
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32915
diff changeset
   405
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   406
    def _renderitem(self, part, item):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   407
        if part not in self._parts:
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   408
            return
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   409
        ref = self._parts[part]
37106
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   410
        self._out.write(self._t.render(ref, item))
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   411
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   412
    def end(self):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   413
        baseformatter.end(self)
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   414
        self._renderitem('docfooter', {})
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   415
32856
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32853
diff changeset
   416
templatespec = collections.namedtuple(r'templatespec',
32858
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32856
diff changeset
   417
                                      r'ref tmpl mapfile')
32856
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32853
diff changeset
   418
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   419
def lookuptemplate(ui, topic, tmpl):
32853
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   420
    """Find the template matching the given -T/--template spec 'tmpl'
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   421
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   422
    'tmpl' can be any of the following:
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   423
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   424
     - a literal template (e.g. '{rev}')
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   425
     - a map-file name or path (e.g. 'changelog')
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   426
     - a reference to [templates] in config file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   427
     - a path to raw template file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   428
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   429
    A map file defines a stand-alone template environment. If a map file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   430
    selected, all templates defined in the file will be loaded, and the
34715
f17a0e18c47e templater: load aliases from [templatealias] section in map file
Yuya Nishihara <yuya@tcha.org>
parents: 34426
diff changeset
   431
    template matching the given topic will be rendered. Aliases won't be
f17a0e18c47e templater: load aliases from [templatealias] section in map file
Yuya Nishihara <yuya@tcha.org>
parents: 34426
diff changeset
   432
    loaded from user config, but from the map file.
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   433
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   434
    If no map file selected, all templates in [templates] section will be
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   435
    available as well as aliases in [templatealias].
32853
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   436
    """
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32851
diff changeset
   437
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   438
    # looks like a literal template?
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   439
    if '{' in tmpl:
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   440
        return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   441
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   442
    # perhaps a stock style?
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   443
    if not os.path.split(tmpl)[0]:
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   444
        mapname = (templater.templatepath('map-cmdline.' + tmpl)
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   445
                   or templater.templatepath(tmpl))
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   446
        if mapname and os.path.isfile(mapname):
32858
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32856
diff changeset
   447
            return templatespec(topic, None, mapname)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   448
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   449
    # perhaps it's a reference to [templates]
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   450
    if ui.config('templates', tmpl):
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   451
        return templatespec(tmpl, None, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   452
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   453
    if tmpl == 'list':
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   454
        ui.write(_("available styles: %s\n") % templater.stylelist())
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26373
diff changeset
   455
        raise error.Abort(_("specify a template"))
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   456
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   457
    # perhaps it's a path to a map or a template
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   458
    if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   459
        # is it a mapfile for a style?
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   460
        if os.path.basename(tmpl).startswith("map-"):
32858
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32856
diff changeset
   461
            return templatespec(topic, None, os.path.realpath(tmpl))
32848
470820c2418d formatter: open raw template file in posix semantics
Yuya Nishihara <yuya@tcha.org>
parents: 32847
diff changeset
   462
        with util.posixfile(tmpl, 'rb') as f:
32846
526f9f12f707 formatter: close raw template file explicitly
Yuya Nishihara <yuya@tcha.org>
parents: 32607
diff changeset
   463
            tmpl = f.read()
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   464
        return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   465
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   466
    # constant string?
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   467
    return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   468
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   469
def templatepartsmap(spec, t, partnames):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   470
    """Create a mapping of {part: ref}"""
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   471
    partsmap = {spec.ref: spec.ref}  # initial ref must exist in t
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   472
    if spec.mapfile:
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   473
        partsmap.update((p, p) for p in partnames if p in t)
32970
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32968
diff changeset
   474
    elif spec.ref:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32968
diff changeset
   475
        for part in partnames:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32968
diff changeset
   476
            ref = '%s:%s' % (spec.ref, part)  # select config sub-section
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32968
diff changeset
   477
            if ref in t:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32968
diff changeset
   478
                partsmap[part] = ref
32967
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   479
    return partsmap
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32966
diff changeset
   480
35487
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   481
def loadtemplater(ui, spec, defaults=None, resources=None, cache=None):
32850
11e667a8fcba formatter: factor out function to create templater from literal or map file
Yuya Nishihara <yuya@tcha.org>
parents: 32848
diff changeset
   482
    """Create a templater from either a literal template or loading from
11e667a8fcba formatter: factor out function to create templater from literal or map file
Yuya Nishihara <yuya@tcha.org>
parents: 32848
diff changeset
   483
    a map file"""
32856
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32853
diff changeset
   484
    assert not (spec.tmpl and spec.mapfile)
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32853
diff changeset
   485
    if spec.mapfile:
35472
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 34715
diff changeset
   486
        frommapfile = templater.templater.frommapfile
35487
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   487
        return frommapfile(spec.mapfile, defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   488
                           cache=cache)
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   489
    return maketemplater(ui, spec.tmpl, defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   490
                         cache=cache)
28955
78759f78a44e templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   491
35487
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   492
def maketemplater(ui, tmpl, defaults=None, resources=None, cache=None):
28955
78759f78a44e templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   493
    """Create a templater from a string template 'tmpl'"""
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28955
diff changeset
   494
    aliases = ui.configitems('templatealias')
35487
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   495
    t = templater.templater(defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35474
diff changeset
   496
                            cache=cache, aliases=aliases)
32893
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   497
    t.cache.update((k, templater.unquotestring(v))
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32891
diff changeset
   498
                   for k, v in ui.configitems('templates'))
25512
8463433c2689 formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents: 25511
diff changeset
   499
    if tmpl:
32894
8da65da039c3 formatter: always store a literal template unnamed
Yuya Nishihara <yuya@tcha.org>
parents: 32893
diff changeset
   500
        t.cache[''] = tmpl
25512
8463433c2689 formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents: 25511
diff changeset
   501
    return t
8463433c2689 formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents: 25511
diff changeset
   502
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   503
class templateresources(templater.resourcemapper):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   504
    """Resource mapper designed for the default templatekw and function"""
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   505
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   506
    def __init__(self, ui, repo=None):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   507
        self._resmap = {
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   508
            'cache': {},  # for templatekw/funcs to store reusable data
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   509
            'repo': repo,
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   510
            'ui': ui,
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   511
        }
35473
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35472
diff changeset
   512
37078
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   513
    def availablekeys(self, context, mapping):
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   514
        return {k for k, g in self._gettermap.iteritems()
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   515
                if g(self, context, mapping, k) is not None}
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   516
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   517
    def knownkeys(self):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   518
        return self._knownkeys
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   519
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   520
    def lookup(self, context, mapping, key):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   521
        get = self._gettermap.get(key)
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   522
        if not get:
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   523
            return None
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   524
        return get(self, context, mapping, key)
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   525
37105
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37078
diff changeset
   526
    def populatemap(self, context, origmapping, newmapping):
37106
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   527
        mapping = {}
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   528
        if self._hasctx(newmapping):
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   529
            mapping['revcache'] = {}  # per-ctx cache
37108
e7bc0667c521 formatter: make 'originalnode' a thing in log-like templates
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   530
        if (('node' in origmapping or self._hasctx(origmapping))
e7bc0667c521 formatter: make 'originalnode' a thing in log-like templates
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   531
            and ('node' in newmapping or self._hasctx(newmapping))):
e7bc0667c521 formatter: make 'originalnode' a thing in log-like templates
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   532
            orignode = templateutil.runsymbol(context, origmapping, 'node')
e7bc0667c521 formatter: make 'originalnode' a thing in log-like templates
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   533
            mapping['originalnode'] = orignode
37106
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   534
        return mapping
37105
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37078
diff changeset
   535
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   536
    def _getsome(self, context, mapping, key):
36986
036e4483d3a1 templater: process mapping dict by resource callables
Yuya Nishihara <yuya@tcha.org>
parents: 36985
diff changeset
   537
        v = mapping.get(key)
036e4483d3a1 templater: process mapping dict by resource callables
Yuya Nishihara <yuya@tcha.org>
parents: 36985
diff changeset
   538
        if v is not None:
036e4483d3a1 templater: process mapping dict by resource callables
Yuya Nishihara <yuya@tcha.org>
parents: 36985
diff changeset
   539
            return v
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   540
        return self._resmap.get(key)
36985
255f635c3204 templater: convert resources to a table of callables for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   541
37106
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   542
    def _hasctx(self, mapping):
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   543
        return 'ctx' in mapping or 'fctx' in mapping
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   544
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   545
    def _getctx(self, context, mapping, key):
36987
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   546
        ctx = mapping.get('ctx')
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   547
        if ctx is not None:
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   548
            return ctx
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   549
        fctx = mapping.get('fctx')
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   550
        if fctx is not None:
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   551
            return fctx.changectx()
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   552
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   553
    def _getrepo(self, context, mapping, key):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   554
        ctx = self._getctx(context, mapping, 'ctx')
36987
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   555
        if ctx is not None:
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   556
            return ctx.repo()
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   557
        return self._getsome(context, mapping, key)
36987
939e0983c1d9 formatter: unblock storing fctx as a template resource
Yuya Nishihara <yuya@tcha.org>
parents: 36986
diff changeset
   558
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   559
    _gettermap = {
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   560
        'cache': _getsome,
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   561
        'ctx': _getctx,
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   562
        'fctx': _getsome,
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   563
        'repo': _getrepo,
37106
be3f33f5e232 templater: switch 'revcache' based on new mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37105
diff changeset
   564
        'revcache': _getsome,
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   565
        'ui': _getsome,
36985
255f635c3204 templater: convert resources to a table of callables for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   566
    }
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 36992
diff changeset
   567
    _knownkeys = set(_gettermap.keys())
36985
255f635c3204 templater: convert resources to a table of callables for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   568
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   569
def formatter(ui, out, topic, opts):
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   570
    template = opts.get("template", "")
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   571
    if template == "json":
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   572
        return jsonformatter(ui, out, topic, opts)
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   573
    elif template == "pickle":
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   574
        return pickleformatter(ui, out, topic, opts)
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   575
    elif template == "debug":
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   576
        return debugformatter(ui, out, topic, opts)
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   577
    elif template != "":
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   578
        return templateformatter(ui, out, topic, opts)
25838
31137258ae8b formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents: 25513
diff changeset
   579
    # developer config: ui.formatdebug
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   580
    elif ui.configbool('ui', 'formatdebug'):
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   581
        return debugformatter(ui, out, topic, opts)
25838
31137258ae8b formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents: 25513
diff changeset
   582
    # deprecated config: ui.formatjson
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   583
    elif ui.configbool('ui', 'formatjson'):
32605
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   584
        return jsonformatter(ui, out, topic, opts)
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32208
diff changeset
   585
    return plainformatter(ui, out, topic, opts)
32606
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   586
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   587
@contextlib.contextmanager
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   588
def openformatter(ui, filename, topic, opts):
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   589
    """Create a formatter that writes outputs to the specified file
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   590
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   591
    Must be invoked using the 'with' statement.
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   592
    """
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   593
    with util.posixfile(filename, 'wb') as out:
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   594
        with formatter(ui, out, topic, opts) as fm:
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   595
            yield fm
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   596
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   597
@contextlib.contextmanager
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   598
def _neverending(fm):
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   599
    yield fm
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   600
37597
d110167610db formatter: carry opts to file-based formatters by basefm
Yuya Nishihara <yuya@tcha.org>
parents: 37596
diff changeset
   601
def maybereopen(fm, filename):
32606
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   602
    """Create a formatter backed by file if filename specified, else return
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   603
    the given formatter
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   604
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   605
    Must be invoked using the 'with' statement. This will never call fm.end()
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   606
    of the given formatter.
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   607
    """
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   608
    if filename:
37597
d110167610db formatter: carry opts to file-based formatters by basefm
Yuya Nishihara <yuya@tcha.org>
parents: 37596
diff changeset
   609
        return openformatter(fm._ui, filename, fm._topic, fm._opts)
32606
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   610
    else:
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32605
diff changeset
   611
        return _neverending(fm)