mercurial/formatter.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sat, 10 Mar 2018 11:03:45 -0800
changeset 36855 2cdf47e14c30
parent 36634 cafd0586876b
child 36920 6ff6e1d6b5b8
permissions -rw-r--r--
hgweb: refactor the request draining code The previous code for draining was only invoked in a few places in the wire protocol. Behavior wasn't consist. Furthermore, it was difficult to reason about. With us converting the input stream to a capped reader, it is now safe to always drain the input stream when its size is known because we can never overrun the input and read into the next HTTP request. The only question is "should we?" This commit changes the draining code so every request is examined. Draining now kicks in for a few requests where it wouldn't before. But I think the code is sufficiently restricted so the behavior is safe. Possibly the most dangerous part of this code is the issuing of Connection: close for POST and PUT requests that don't have a Content-Length. I don't think there are any such uses in our WSGI application, so this should be safe. In the near future, I plan to significantly refactor the WSGI response handling. I anticipate this code evolving a bit. So any minor regressions around draining or connection closing behavior might be fixed as a result of that work. All tests pass with this change. That scares me a bit because it means we are lacking low-level tests for the HTTP protocol. Differential Revision: https://phab.mercurial-scm.org/D2769
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
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
     8
"""Generic output formatting for Mercurial
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
     9
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
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: 29949
diff changeset
    12
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    13
- fm.write() for unconditional output
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    14
- fm.condwrite() to show some extra data conditionally in plain output
31172
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
    15
- fm.context() to provide changectx to template output
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
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: 29949
diff changeset
    18
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
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: 29949
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: 29949
diff changeset
    22
supported by the formatter API.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    23
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    25
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    27
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    28
fm.condwrite() vs 'if cond:':
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    29
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
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: 29949
diff changeset
    32
fm.write().
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    33
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    35
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
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: 29949
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: 29949
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: 29949
diff changeset
    40
"{get(foo, key)}" function.
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    41
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    42
Doctest helper:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    43
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    45
...     import sys
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    46
...     from . import ui as uimod
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    47
...     ui = uimod.ui()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    48
...     ui.verbose = verbose
34255
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
    49
...     ui.pushbuffer()
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
    50
...     try:
34256
ebe3d0095c69 py3: convert system strings to bytes in doctest of formatter.py
Yuya Nishihara <yuya@tcha.org>
parents: 34255
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: 34255
diff changeset
    52
...                   pycompat.byteskwargs(opts)))
34255
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
    53
...     finally:
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
    54
...         print(pycompat.sysstr(ui.popbuffer()), end='')
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    55
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    56
Basic example:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    57
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    58
>>> def files(ui, fm):
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
diff changeset
    59
...     files = [(b'foo', 123, (0, 0)), (b'bar', 456, (1, 0))]
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    60
...     for f in files:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    61
...         fm.startitem()
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
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: 33090
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: 33090
diff changeset
    64
...                      fm.formatdate(f[2], b'%Y-%m-%d %H:%M:%S'))
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    65
...         fm.data(size=f[1])
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
diff changeset
    66
...         fm.plain(b'\\n')
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    67
...     fm.end()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    68
>>> show(files)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    69
foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    70
bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    71
>>> show(files, verbose=True)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    73
bar  1970-01-01 00:00:01
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
diff changeset
    74
>>> show(files, template=b'json')
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    75
[
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    76
 {
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    77
  "date": [0, 0],
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    78
  "path": "foo",
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    79
  "size": 123
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    80
 },
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    81
 {
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    82
  "date": [1, 0],
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    83
  "path": "bar",
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    84
  "size": 456
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    85
 }
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    86
]
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
diff changeset
    87
>>> show(files, template=b'path: {path}\\ndate: {date|rfc3339date}\\n')
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    88
path: foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    90
path: bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
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: 29949
diff changeset
    92
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    93
Nested example:
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    94
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    95
>>> def subrepos(ui, fm):
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    96
...     fm.startitem()
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35469
diff changeset
    97
...     fm.write(b'reponame', b'[%s]\\n', b'baz')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33090
diff changeset
    98
...     files(ui, fm.nested(b'files'))
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
    99
...     fm.end()
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   100
>>> show(subrepos)
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   101
[baz]
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   102
foo
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   103
bar
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35469
diff changeset
   104
>>> show(subrepos, template=b'{reponame}: {join(files % "{path}", ", ")}\\n')
30560
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   105
baz: foo, bar
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   106
"""
783016005122 formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents: 29949
diff changeset
   107
34255
d6af8da4a3b8 py3: rewrite stdout hack of doctest by using ui.pushbuffer()
Yuya Nishihara <yuya@tcha.org>
parents: 34131
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
32838
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32835
diff changeset
   110
import collections
32580
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
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,
32159
0fd15522a848 py3: use pycompat.byteskwargs to converts kwargs to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31925
diff changeset
   123
    pycompat,
31782
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31396
diff changeset
   124
    templatefilters,
29676
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,
29324
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   127
    util,
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   128
)
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36445
diff changeset
   129
from .utils import dateutil
25950
175873e36d03 formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25838
diff changeset
   130
29324
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   131
pickle = util.pickle
b501579147f1 py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28957
diff changeset
   132
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   133
class _nullconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   134
    '''convert non-primitive data types to be processed by formatter'''
33090
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   135
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   136
    # set to True if context object should be stored as item
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   137
    storecontext = False
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   138
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   139
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   140
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   141
        '''convert date tuple to appropriate format'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   142
        return date
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   143
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   144
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   145
        '''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: 29794
diff changeset
   146
        # 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: 29794
diff changeset
   147
        # serialized as a builtin dict in pickle output
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   148
        return dict(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   149
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   150
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   151
        '''convert iterable to appropriate list format'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   152
        return list(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   153
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
class baseformatter(object):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   155
    def __init__(self, ui, topic, opts, converter):
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
        self._ui = ui
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   157
        self._topic = topic
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   158
        self._style = opts.get("style")
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   159
        self._template = opts.get("template")
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   160
        self._converter = converter
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
        self._item = None
22701
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   162
        # 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
   163
        self.hexfunc = hex
29882
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29837
diff changeset
   164
    def __enter__(self):
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29837
diff changeset
   165
        return self
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29837
diff changeset
   166
    def __exit__(self, exctype, excvalue, traceback):
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29837
diff changeset
   167
        if exctype is None:
307b20e5e505 formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 29837
diff changeset
   168
            self.end()
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
    def _showitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
        '''show a formatted item once all data is collected'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   171
    def startitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   172
        '''begin an item in the format list'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   173
        if self._item is not None:
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   174
            self._showitem()
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
        self._item = {}
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   176
    def formatdate(self, date, fmt='%a %b %d %H:%M:%S %Y %1%2'):
29678
2f3f18ad55a2 formatter: add function to convert date tuple to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29676
diff changeset
   177
        '''convert date tuple to appropriate format'''
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   178
        return self._converter.formatdate(date, fmt)
36633
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   179
    def formatdict(self, data, key='key', value='value', fmt=None, sep=' '):
29794
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   180
        '''convert dict or key-value pairs to appropriate dict format'''
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   181
        return self._converter.formatdict(data, key, value, fmt, sep)
36633
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   182
    def formatlist(self, data, name, fmt=None, sep=' '):
29676
c3a9cd78b151 formatter: add function to convert list to appropriate format (issue5217)
Yuya Nishihara <yuya@tcha.org>
parents: 29324
diff changeset
   183
        '''convert iterable to appropriate list format'''
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   184
        # 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: 29794
diff changeset
   185
        # we have default template keyword, e.g. {item}
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   186
        return self._converter.formatlist(data, name, fmt, sep)
31172
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
   187
    def context(self, **ctxs):
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
   188
        '''insert context objects to be used to render template keywords'''
33090
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   189
        ctxs = pycompat.byteskwargs(ctxs)
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   190
        assert all(k == 'ctx' for k in ctxs)
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   191
        if self._converter.storecontext:
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   192
            self._item.update(ctxs)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
    def data(self, **data):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   194
        '''insert data into item that's not shown in default output'''
32159
0fd15522a848 py3: use pycompat.byteskwargs to converts kwargs to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31925
diff changeset
   195
        data = pycompat.byteskwargs(data)
17630
ff5ed1ecd43a formatter: improve implementation of data method
David M. Carr <david@carrclan.us>
parents: 17597
diff changeset
   196
        self._item.update(data)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   197
    def write(self, fields, deftext, *fielddata, **opts):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   198
        '''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
   199
        fieldkeys = fields.split()
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   200
        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
   201
        self._item.update(zip(fieldkeys, fielddata))
17909
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   202
    def condwrite(self, cond, fields, deftext, *fielddata, **opts):
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   203
        '''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
   204
        fieldkeys = fields.split()
55de800937e0 formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents: 25950
diff changeset
   205
        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
   206
        self._item.update(zip(fieldkeys, fielddata))
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
    def plain(self, text, **opts):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
        '''show raw text for non-templated mode'''
29949
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29882
diff changeset
   209
    def isplain(self):
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29882
diff changeset
   210
        '''check for plain formatter usage'''
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29882
diff changeset
   211
        return False
29837
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   212
    def nested(self, field):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   213
        '''sub formatter to store nested data in the specified field'''
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   214
        self._item[field] = data = []
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   215
        return _nestedformatter(self._ui, self._converter, data)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   216
    def end(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
        '''end output for the formatter'''
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
        if self._item is not None:
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
            self._showitem()
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   220
32581
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32580
diff changeset
   221
def nullformatter(ui, topic):
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32580
diff changeset
   222
    '''formatter that prints nothing'''
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32580
diff changeset
   223
    return baseformatter(ui, topic, opts={}, converter=_nullconverter)
e9bf3e132ea9 formatter: add nullformatter
Yuya Nishihara <yuya@tcha.org>
parents: 32580
diff changeset
   224
29837
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   225
class _nestedformatter(baseformatter):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   226
    '''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: 29836
diff changeset
   227
    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: 29836
diff changeset
   228
        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: 29836
diff changeset
   229
        self._data = data
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   230
    def _showitem(self):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   231
        self._data.append(self._item)
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   232
29794
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   233
def _iteritems(data):
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   234
    '''iterate key-value pairs in stable order'''
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   235
    if isinstance(data, dict):
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   236
        return sorted(data.iteritems())
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   237
    return data
4891f3b93182 formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents: 29678
diff changeset
   238
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   239
class _plainconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   240
    '''convert non-primitive data types to text'''
33090
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   241
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   242
    storecontext = False
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   243
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   244
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   245
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   246
        '''stringify date tuple in the given format'''
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36445
diff changeset
   247
        return dateutil.datestr(date, fmt)
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   248
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   249
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   250
        '''stringify key-value pairs separated by sep'''
36634
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   251
        prefmt = pycompat.identity
36633
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   252
        if fmt is None:
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   253
            fmt = '%s=%s'
36634
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   254
            prefmt = pycompat.bytestr
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   255
        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: 36633
diff changeset
   256
                        for k, v in _iteritems(data))
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   257
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   258
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   259
        '''stringify iterable separated by sep'''
36634
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   260
        prefmt = pycompat.identity
36633
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   261
        if fmt is None:
034a07e60e98 templater: allow dynamically switching the default dict/list formatting
Yuya Nishihara <yuya@tcha.org>
parents: 36607
diff changeset
   262
            fmt = '%s'
36634
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   263
            prefmt = pycompat.bytestr
cafd0586876b templater: byte-stringify dict/list values before passing to default format
Yuya Nishihara <yuya@tcha.org>
parents: 36633
diff changeset
   264
        return sep.join(fmt % prefmt(e) for e in data)
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   265
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
class plainformatter(baseformatter):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   267
    '''the default text output scheme'''
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   268
    def __init__(self, ui, out, topic, opts):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   269
        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
   270
        if ui.debugflag:
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   271
            self.hexfunc = hex
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   272
        else:
cb28d2b3db0b formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents: 22674
diff changeset
   273
            self.hexfunc = short
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   274
        if ui is out:
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   275
            self._write = ui.write
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   276
        else:
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   277
            self._write = lambda s, **opts: out.write(s)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   278
    def startitem(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   279
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   280
    def data(self, **data):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   281
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   282
    def write(self, fields, deftext, *fielddata, **opts):
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   283
        self._write(deftext % fielddata, **opts)
17909
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   284
    def condwrite(self, cond, fields, deftext, *fielddata, **opts):
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   285
        '''do conditional write'''
3326fd05eb1f formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents: 17630
diff changeset
   286
        if cond:
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   287
            self._write(deftext % fielddata, **opts)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   288
    def plain(self, text, **opts):
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   289
        self._write(text, **opts)
29949
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29882
diff changeset
   290
    def isplain(self):
e7cacb45c4be formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents: 29882
diff changeset
   291
        return True
29837
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   292
    def nested(self, field):
5b886289a1ca formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents: 29836
diff changeset
   293
        # 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: 29836
diff changeset
   294
        return self
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   295
    def end(self):
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   296
        pass
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   297
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   298
class debugformatter(baseformatter):
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   299
    def __init__(self, ui, out, topic, opts):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   300
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   301
        self._out = out
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   302
        self._out.write("%s = [\n" % self._topic)
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   303
    def _showitem(self):
36265
b44fac3a49fb py3: factor out byterepr() which returns an asciified value on py3
Yuya Nishihara <yuya@tcha.org>
parents: 36040
diff changeset
   304
        self._out.write('    %s,\n' % pycompat.byterepr(self._item))
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
        baseformatter.end(self)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   307
        self._out.write("]\n")
16134
3c0327ea20c0 formatter: add basic formatters
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   308
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   309
class pickleformatter(baseformatter):
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   310
    def __init__(self, ui, out, topic, opts):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   311
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   312
        self._out = out
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   313
        self._data = []
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   314
    def _showitem(self):
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   315
        self._data.append(self._item)
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   316
    def end(self):
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   317
        baseformatter.end(self)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   318
        self._out.write(pickle.dumps(self._data))
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   319
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   320
class jsonformatter(baseformatter):
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   321
    def __init__(self, ui, out, topic, opts):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   322
        baseformatter.__init__(self, ui, topic, opts, _nullconverter)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   323
        self._out = out
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   324
        self._out.write("[")
31298
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31182
diff changeset
   325
        self._first = True
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   326
    def _showitem(self):
31298
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31182
diff changeset
   327
        if self._first:
59d09565ac77 formatter: set _first on formatter, not ui
Martin von Zweigbergk <martinvonz@google.com>
parents: 31182
diff changeset
   328
            self._first = False
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   329
        else:
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   330
            self._out.write(",")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   331
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   332
        self._out.write("\n {\n")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   333
        first = True
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   334
        for k, v in sorted(self._item.items()):
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   335
            if first:
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   336
                first = False
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   337
            else:
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   338
                self._out.write(",\n")
31782
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31396
diff changeset
   339
            u = templatefilters.json(v, paranoid=False)
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31396
diff changeset
   340
            self._out.write('  "%s": %s' % (k, u))
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   341
        self._out.write("\n }")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   342
    def end(self):
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   343
        baseformatter.end(self)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   344
        self._out.write("\n]\n")
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   345
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   346
class _templateconverter(object):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   347
    '''convert non-primitive data types to be processed by templater'''
33090
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   348
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   349
    storecontext = True
04b3743c1d7c formatter: proxy fm.context() through converter
Yuya Nishihara <yuya@tcha.org>
parents: 32952
diff changeset
   350
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   351
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   352
    def formatdate(date, fmt):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   353
        '''return date tuple'''
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   354
        return date
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   355
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   356
    def formatdict(data, key, value, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   357
        '''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: 29794
diff changeset
   358
        data = util.sortdict(_iteritems(data))
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   359
        def f():
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   360
            yield _plainconverter.formatdict(data, key, value, fmt, sep)
34425
12bfecd0ffe6 formatter: fix default list/dict generator to be evaluated more than once
Yuya Nishihara <yuya@tcha.org>
parents: 34375
diff changeset
   361
        return templatekw.hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   362
    @staticmethod
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   363
    def formatlist(data, name, fmt, sep):
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   364
        '''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: 29794
diff changeset
   365
        data = list(data)
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   366
        def f():
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   367
            yield _plainconverter.formatlist(data, name, fmt, sep)
34425
12bfecd0ffe6 formatter: fix default list/dict generator to be evaluated more than once
Yuya Nishihara <yuya@tcha.org>
parents: 34375
diff changeset
   368
        return templatekw.hybridlist(data, name=name, fmt=fmt, gen=f)
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   369
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   370
class templateformatter(baseformatter):
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   371
    def __init__(self, ui, out, topic, opts):
29836
18bac830eef3 formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents: 29794
diff changeset
   372
        baseformatter.__init__(self, ui, topic, opts, _templateconverter)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   373
        self._out = out
32833
99df35499cae formatter: inline gettemplater()
Yuya Nishihara <yuya@tcha.org>
parents: 32832
diff changeset
   374
        spec = lookuptemplate(ui, topic, opts.get('template', ''))
32841
883adaea9e80 formatter: render template specified by templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32840
diff changeset
   375
        self._tref = spec.ref
35483
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   376
        self._t = loadtemplater(ui, spec, defaults=templatekw.keywords,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   377
                                resources=templateresources(ui),
35469
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   378
                                cache=templatekw.defaulttempl)
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   379
        self._parts = templatepartsmap(spec, self._t,
32950
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32949
diff changeset
   380
                                       ['docheader', 'docfooter', 'separator'])
31807
e6eb86b154c5 templater: provide loop counter as "index" keyword
Yuya Nishihara <yuya@tcha.org>
parents: 31805
diff changeset
   381
        self._counter = itertools.count()
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   382
        self._renderitem('docheader', {})
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   383
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   384
    def _showitem(self):
32948
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32897
diff changeset
   385
        item = self._item.copy()
32950
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32949
diff changeset
   386
        item['index'] = index = next(self._counter)
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32949
diff changeset
   387
        if index > 0:
5100ce217dfa formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org>
parents: 32949
diff changeset
   388
            self._renderitem('separator', {})
32948
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32897
diff changeset
   389
        self._renderitem(self._tref, item)
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32897
diff changeset
   390
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   391
    def _renderitem(self, part, item):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   392
        if part not in self._parts:
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   393
            return
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   394
        ref = self._parts[part]
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   395
36445
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36265
diff changeset
   396
        # TODO: add support for filectx
31805
dca9b6922514 formatter: reorder code that builds template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   397
        props = {}
dca9b6922514 formatter: reorder code that builds template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   398
        # explicitly-defined fields precede templatekw
32948
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32897
diff changeset
   399
        props.update(item)
12a0794fa2e3 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org>
parents: 32897
diff changeset
   400
        if 'ctx' in item:
31172
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
   401
            # but template resources must be always available
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
   402
            props['repo'] = props['ctx'].repo()
16272d8c24f6 formatter: add support for changeset templating
Yuya Nishihara <yuya@tcha.org>
parents: 31170
diff changeset
   403
            props['revcache'] = {}
32896
e14484e7f562 py3: use pycompat.strkwargs() to convert kwargs keys to str before passing
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32876
diff changeset
   404
        props = pycompat.strkwargs(props)
35469
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   405
        g = self._t(ref, **props)
31182
5660c45ecba6 formatter: add argument to change output file of non-plain formatter
Yuya Nishihara <yuya@tcha.org>
parents: 31172
diff changeset
   406
        self._out.write(templater.stringify(g))
25513
0c6f98398f8a formatter: add template support
Matt Mackall <mpm@selenic.com>
parents: 25512
diff changeset
   407
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   408
    def end(self):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   409
        baseformatter.end(self)
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   410
        self._renderitem('docfooter', {})
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   411
32838
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32835
diff changeset
   412
templatespec = collections.namedtuple(r'templatespec',
32840
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32838
diff changeset
   413
                                      r'ref tmpl mapfile')
32838
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32835
diff changeset
   414
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   415
def lookuptemplate(ui, topic, tmpl):
32835
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   416
    """Find the template matching the given -T/--template spec 'tmpl'
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   417
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   418
    'tmpl' can be any of the following:
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   419
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   420
     - a literal template (e.g. '{rev}')
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   421
     - a map-file name or path (e.g. 'changelog')
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   422
     - a reference to [templates] in config file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   423
     - a path to raw template file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   424
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   425
    A map file defines a stand-alone template environment. If a map file
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   426
    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: 34425
diff changeset
   427
    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: 34425
diff changeset
   428
    loaded from user config, but from the map file.
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   429
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   430
    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: 32873
diff changeset
   431
    available as well as aliases in [templatealias].
32835
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   432
    """
9d76812f9b0b formatter: document lookuptemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 32833
diff changeset
   433
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   434
    # looks like a literal template?
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   435
    if '{' in tmpl:
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   436
        return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   437
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   438
    # perhaps a stock style?
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   439
    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
   440
        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
   441
                   or templater.templatepath(tmpl))
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   442
        if mapname and os.path.isfile(mapname):
32840
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32838
diff changeset
   443
            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
   444
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   445
    # perhaps it's a reference to [templates]
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   446
    if ui.config('templates', tmpl):
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   447
        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
   448
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   449
    if tmpl == 'list':
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   450
        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
   451
        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
   452
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   453
    # 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
   454
    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
   455
        # 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
   456
        if os.path.basename(tmpl).startswith("map-"):
32840
57c13c0d1cde formatter: put topic in templatespec tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32838
diff changeset
   457
            return templatespec(topic, None, os.path.realpath(tmpl))
32830
470820c2418d formatter: open raw template file in posix semantics
Yuya Nishihara <yuya@tcha.org>
parents: 32829
diff changeset
   458
        with util.posixfile(tmpl, 'rb') as f:
32828
526f9f12f707 formatter: close raw template file explicitly
Yuya Nishihara <yuya@tcha.org>
parents: 32581
diff changeset
   459
            tmpl = f.read()
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   460
        return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   461
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   462
    # constant string?
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   463
    return templatespec('', tmpl, None)
25511
c2a4dfe2a336 formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents: 24321
diff changeset
   464
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   465
def templatepartsmap(spec, t, partnames):
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   466
    """Create a mapping of {part: ref}"""
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   467
    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: 32948
diff changeset
   468
    if spec.mapfile:
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   469
        partsmap.update((p, p) for p in partnames if p in t)
32952
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32950
diff changeset
   470
    elif spec.ref:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32950
diff changeset
   471
        for part in partnames:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32950
diff changeset
   472
            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: 32950
diff changeset
   473
            if ref in t:
61b60b28c381 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org>
parents: 32950
diff changeset
   474
                partsmap[part] = ref
32949
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   475
    return partsmap
13eebc189ff3 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org>
parents: 32948
diff changeset
   476
35483
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   477
def loadtemplater(ui, spec, defaults=None, resources=None, cache=None):
32832
11e667a8fcba formatter: factor out function to create templater from literal or map file
Yuya Nishihara <yuya@tcha.org>
parents: 32830
diff changeset
   478
    """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: 32830
diff changeset
   479
    a map file"""
32838
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32835
diff changeset
   480
    assert not (spec.tmpl and spec.mapfile)
615ec3f14aa9 formatter: wrap (tmpl, mapfile) by named tuple
Yuya Nishihara <yuya@tcha.org>
parents: 32835
diff changeset
   481
    if spec.mapfile:
35468
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 34715
diff changeset
   482
        frommapfile = templater.templater.frommapfile
35483
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   483
        return frommapfile(spec.mapfile, defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   484
                           cache=cache)
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   485
    return maketemplater(ui, spec.tmpl, defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   486
                         cache=cache)
28955
78759f78a44e templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   487
35483
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   488
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
   489
    """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
   490
    aliases = ui.configitems('templatealias')
35483
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   491
    t = templater.templater(defaults=defaults, resources=resources,
817a3d20dd01 templater: register keywords to defaults table
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   492
                            cache=cache, aliases=aliases)
32875
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   493
    t.cache.update((k, templater.unquotestring(v))
c8f2cf18b82e formatter: load templates section like a map file
Yuya Nishihara <yuya@tcha.org>
parents: 32873
diff changeset
   494
                   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
   495
    if tmpl:
32876
8da65da039c3 formatter: always store a literal template unnamed
Yuya Nishihara <yuya@tcha.org>
parents: 32875
diff changeset
   496
        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
   497
    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
   498
35469
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   499
def templateresources(ui, repo=None):
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   500
    """Create a dict of template resources designed for the default templatekw
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   501
    and function"""
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   502
    return {
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   503
        'cache': {},  # for templatekw/funcs to store reusable data
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35469
diff changeset
   504
        'ctx': None,
35469
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   505
        'repo': repo,
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35469
diff changeset
   506
        'revcache': None,  # per-ctx cache; set later
35469
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   507
        'ui': ui,
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   508
    }
f1c54d003327 templater: move repo, ui and cache to per-engine resources
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   509
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   510
def formatter(ui, out, topic, opts):
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   511
    template = opts.get("template", "")
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   512
    if template == "json":
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   513
        return jsonformatter(ui, out, topic, opts)
22430
968247e8f4ac formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents: 22428
diff changeset
   514
    elif template == "pickle":
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   515
        return pickleformatter(ui, out, topic, opts)
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   516
    elif template == "debug":
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   517
        return debugformatter(ui, out, topic, opts)
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   518
    elif template != "":
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   519
        return templateformatter(ui, out, topic, opts)
25838
31137258ae8b formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents: 25513
diff changeset
   520
    # developer config: ui.formatdebug
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   521
    elif ui.configbool('ui', 'formatdebug'):
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   522
        return debugformatter(ui, out, topic, opts)
25838
31137258ae8b formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents: 25513
diff changeset
   523
    # deprecated config: ui.formatjson
22428
427e80a18ef8 formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents: 22424
diff changeset
   524
    elif ui.configbool('ui', 'formatjson'):
32579
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   525
        return jsonformatter(ui, out, topic, opts)
012e0da5b759 formatter: add option to redirect output to file object
Yuya Nishihara <yuya@tcha.org>
parents: 32159
diff changeset
   526
    return plainformatter(ui, out, topic, opts)
32580
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   527
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   528
@contextlib.contextmanager
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   529
def openformatter(ui, filename, topic, opts):
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   530
    """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: 32579
diff changeset
   531
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   532
    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: 32579
diff changeset
   533
    """
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   534
    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: 32579
diff changeset
   535
        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: 32579
diff changeset
   536
            yield fm
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   537
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   538
@contextlib.contextmanager
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   539
def _neverending(fm):
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   540
    yield fm
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   541
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   542
def maybereopen(fm, filename, opts):
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   543
    """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: 32579
diff changeset
   544
    the given formatter
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   545
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   546
    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: 32579
diff changeset
   547
    of the given formatter.
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   548
    """
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   549
    if filename:
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   550
        return openformatter(fm._ui, filename, fm._topic, opts)
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   551
    else:
35985d407d49 formatter: add helper to create a formatter optionally backed by file
Yuya Nishihara <yuya@tcha.org>
parents: 32579
diff changeset
   552
        return _neverending(fm)