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