Mercurial > hg
annotate mercurial/formatter.py @ 30832:da5fa0f13a41
ui: introduce an experimental dict of exportable environment variables
Care needs to be taken to prevent leaking potentially sensitive environment
variables through hgweb, if template support for environment variables is to be
introduced. There are a few ideas about the API for preventing accidental
leaking [1]. Option 3 seems best from the POV of not needing to configure
anything in the normal case. I couldn't figure out how to do that, so guard it
with an experimental option for now.
[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-January/092383.html
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Tue, 17 Jan 2017 23:05:12 -0500 |
parents | 783016005122 |
children | e64b70c96338 |
rev | line source |
---|---|
16134 | 1 # formatter.py - generic output formatting for mercurial |
2 # | |
3 # Copyright 2012 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2 or any later version. | |
7 | |
30560
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
8 """Generic output formatting for Mercurial |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
9 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
10 The formatter provides API to show data in various ways. The following |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
11 functions should be used in place of ui.write(): |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
12 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
13 - fm.write() for unconditional output |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
14 - fm.condwrite() to show some extra data conditionally in plain output |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
15 - fm.data() to provide extra data to JSON or template output |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
16 - fm.plain() to show raw text that isn't provided to JSON or template output |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
17 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
18 To show structured data (e.g. date tuples, dicts, lists), apply fm.format*() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
19 beforehand so the data is converted to the appropriate data type. Use |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
20 fm.isplain() if you need to convert or format data conditionally which isn't |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
21 supported by the formatter API. |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
22 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
23 To build nested structure (i.e. a list of dicts), use fm.nested(). |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
24 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
25 See also https://www.mercurial-scm.org/wiki/GenericTemplatingPlan |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
26 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
27 fm.condwrite() vs 'if cond:': |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
28 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
29 In most cases, use fm.condwrite() so users can selectively show the data |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
30 in template output. If it's costly to build data, use plain 'if cond:' with |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
31 fm.write(). |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
32 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
33 fm.nested() vs fm.formatdict() (or fm.formatlist()): |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
34 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
35 fm.nested() should be used to form a tree structure (a list of dicts of |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
36 lists of dicts...) which can be accessed through template keywords, e.g. |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
37 "{foo % "{bar % {...}} {baz % {...}}"}". On the other hand, fm.formatdict() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
38 exports a dict-type object to template, which can be accessed by e.g. |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
39 "{get(foo, key)}" function. |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
40 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
41 Doctest helper: |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
42 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
43 >>> def show(fn, verbose=False, **opts): |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
44 ... import sys |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
45 ... from . import ui as uimod |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
46 ... ui = uimod.ui() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
47 ... ui.fout = sys.stdout # redirect to doctest |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
48 ... ui.verbose = verbose |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
49 ... return fn(ui, ui.formatter(fn.__name__, opts)) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
50 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
51 Basic example: |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
52 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
53 >>> def files(ui, fm): |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
54 ... files = [('foo', 123, (0, 0)), ('bar', 456, (1, 0))] |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
55 ... for f in files: |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
56 ... fm.startitem() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
57 ... fm.write('path', '%s', f[0]) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
58 ... fm.condwrite(ui.verbose, 'date', ' %s', |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
59 ... fm.formatdate(f[2], '%Y-%m-%d %H:%M:%S')) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
60 ... fm.data(size=f[1]) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
61 ... fm.plain('\\n') |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
62 ... fm.end() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
63 >>> show(files) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
64 foo |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
65 bar |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
66 >>> show(files, verbose=True) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
67 foo 1970-01-01 00:00:00 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
68 bar 1970-01-01 00:00:01 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
69 >>> show(files, template='json') |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
70 [ |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
71 { |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
72 "date": [0, 0], |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
73 "path": "foo", |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
74 "size": 123 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
75 }, |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
76 { |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
77 "date": [1, 0], |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
78 "path": "bar", |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
79 "size": 456 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
80 } |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
81 ] |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
82 >>> show(files, template='path: {path}\\ndate: {date|rfc3339date}\\n') |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
83 path: foo |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
84 date: 1970-01-01T00:00:00+00:00 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
85 path: bar |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
86 date: 1970-01-01T00:00:01+00:00 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
87 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
88 Nested example: |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
89 |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
90 >>> def subrepos(ui, fm): |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
91 ... fm.startitem() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
92 ... fm.write('repo', '[%s]\\n', 'baz') |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
93 ... files(ui, fm.nested('files')) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
94 ... fm.end() |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
95 >>> show(subrepos) |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
96 [baz] |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
97 foo |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
98 bar |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
99 >>> show(subrepos, template='{repo}: {join(files % "{path}", ", ")}\\n') |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
100 baz: foo, bar |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
101 """ |
783016005122
formatter: add overview of API and example as doctest
Yuya Nishihara <yuya@tcha.org>
parents:
29949
diff
changeset
|
102 |
25950
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
103 from __future__ import absolute_import |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
104 |
25511
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
105 import os |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
106 |
25950
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
107 from .i18n import _ |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
108 from .node import ( |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
109 hex, |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
110 short, |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
111 ) |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
112 |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
113 from . import ( |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
114 encoding, |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26373
diff
changeset
|
115 error, |
29676
c3a9cd78b151
formatter: add function to convert list to appropriate format (issue5217)
Yuya Nishihara <yuya@tcha.org>
parents:
29324
diff
changeset
|
116 templatekw, |
25950
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
117 templater, |
29324
b501579147f1
py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents:
28957
diff
changeset
|
118 util, |
25950
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
119 ) |
175873e36d03
formatter: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25838
diff
changeset
|
120 |
29324
b501579147f1
py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents:
28957
diff
changeset
|
121 pickle = util.pickle |
b501579147f1
py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents:
28957
diff
changeset
|
122 |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
123 class _nullconverter(object): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
124 '''convert non-primitive data types to be processed by formatter''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
125 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
126 def formatdate(date, fmt): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
127 '''convert date tuple to appropriate format''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
128 return date |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
129 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
130 def formatdict(data, key, value, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
131 '''convert dict or key-value pairs to appropriate dict format''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
132 # use plain dict instead of util.sortdict so that data can be |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
133 # serialized as a builtin dict in pickle output |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
134 return dict(data) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
135 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
136 def formatlist(data, name, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
137 '''convert iterable to appropriate list format''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
138 return list(data) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
139 |
16134 | 140 class baseformatter(object): |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
141 def __init__(self, ui, topic, opts, converter): |
16134 | 142 self._ui = ui |
143 self._topic = topic | |
144 self._style = opts.get("style") | |
145 self._template = opts.get("template") | |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
146 self._converter = converter |
16134 | 147 self._item = None |
22701
cb28d2b3db0b
formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents:
22674
diff
changeset
|
148 # 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
|
149 self.hexfunc = hex |
29882
307b20e5e505
formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents:
29837
diff
changeset
|
150 def __enter__(self): |
307b20e5e505
formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents:
29837
diff
changeset
|
151 return self |
307b20e5e505
formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents:
29837
diff
changeset
|
152 def __exit__(self, exctype, excvalue, traceback): |
307b20e5e505
formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents:
29837
diff
changeset
|
153 if exctype is None: |
307b20e5e505
formatter: add context manager interface for convenience
Yuya Nishihara <yuya@tcha.org>
parents:
29837
diff
changeset
|
154 self.end() |
16134 | 155 def _showitem(self): |
156 '''show a formatted item once all data is collected''' | |
157 pass | |
158 def startitem(self): | |
159 '''begin an item in the format list''' | |
160 if self._item is not None: | |
161 self._showitem() | |
162 self._item = {} | |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
163 def formatdate(self, date, fmt='%a %b %d %H:%M:%S %Y %1%2'): |
29678
2f3f18ad55a2
formatter: add function to convert date tuple to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29676
diff
changeset
|
164 '''convert date tuple to appropriate format''' |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
165 return self._converter.formatdate(date, fmt) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
166 def formatdict(self, data, key='key', value='value', fmt='%s=%s', sep=' '): |
29794
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
167 '''convert dict or key-value pairs to appropriate dict format''' |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
168 return self._converter.formatdict(data, key, value, fmt, sep) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
169 def formatlist(self, data, name, fmt='%s', sep=' '): |
29676
c3a9cd78b151
formatter: add function to convert list to appropriate format (issue5217)
Yuya Nishihara <yuya@tcha.org>
parents:
29324
diff
changeset
|
170 '''convert iterable to appropriate list format''' |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
171 # name is mandatory argument for now, but it could be optional if |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
172 # we have default template keyword, e.g. {item} |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
173 return self._converter.formatlist(data, name, fmt, sep) |
16134 | 174 def data(self, **data): |
175 '''insert data into item that's not shown in default output''' | |
17630
ff5ed1ecd43a
formatter: improve implementation of data method
David M. Carr <david@carrclan.us>
parents:
17597
diff
changeset
|
176 self._item.update(data) |
16134 | 177 def write(self, fields, deftext, *fielddata, **opts): |
178 '''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
|
179 fieldkeys = fields.split() |
55de800937e0
formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents:
25950
diff
changeset
|
180 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
|
181 self._item.update(zip(fieldkeys, fielddata)) |
17909
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
182 def condwrite(self, cond, fields, deftext, *fielddata, **opts): |
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
183 '''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
|
184 fieldkeys = fields.split() |
55de800937e0
formatter: verify number of arguments passed to write functions
Yuya Nishihara <yuya@tcha.org>
parents:
25950
diff
changeset
|
185 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
|
186 self._item.update(zip(fieldkeys, fielddata)) |
16134 | 187 def plain(self, text, **opts): |
188 '''show raw text for non-templated mode''' | |
189 pass | |
29949
e7cacb45c4be
formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents:
29882
diff
changeset
|
190 def isplain(self): |
e7cacb45c4be
formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents:
29882
diff
changeset
|
191 '''check for plain formatter usage''' |
e7cacb45c4be
formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents:
29882
diff
changeset
|
192 return False |
29837
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
193 def nested(self, field): |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
194 '''sub formatter to store nested data in the specified field''' |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
195 self._item[field] = data = [] |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
196 return _nestedformatter(self._ui, self._converter, data) |
16134 | 197 def end(self): |
198 '''end output for the formatter''' | |
199 if self._item is not None: | |
200 self._showitem() | |
201 | |
29837
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
202 class _nestedformatter(baseformatter): |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
203 '''build sub items and store them in the parent formatter''' |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
204 def __init__(self, ui, converter, data): |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
205 baseformatter.__init__(self, ui, topic='', opts={}, converter=converter) |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
206 self._data = data |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
207 def _showitem(self): |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
208 self._data.append(self._item) |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
209 |
29794
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
210 def _iteritems(data): |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
211 '''iterate key-value pairs in stable order''' |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
212 if isinstance(data, dict): |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
213 return sorted(data.iteritems()) |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
214 return data |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
215 |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
216 class _plainconverter(object): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
217 '''convert non-primitive data types to text''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
218 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
219 def formatdate(date, fmt): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
220 '''stringify date tuple in the given format''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
221 return util.datestr(date, fmt) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
222 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
223 def formatdict(data, key, value, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
224 '''stringify key-value pairs separated by sep''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
225 return sep.join(fmt % (k, v) for k, v in _iteritems(data)) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
226 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
227 def formatlist(data, name, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
228 '''stringify iterable separated by sep''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
229 return sep.join(fmt % e for e in data) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
230 |
16134 | 231 class plainformatter(baseformatter): |
232 '''the default text output scheme''' | |
233 def __init__(self, ui, topic, opts): | |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
234 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
|
235 if ui.debugflag: |
cb28d2b3db0b
formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents:
22674
diff
changeset
|
236 self.hexfunc = hex |
cb28d2b3db0b
formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents:
22674
diff
changeset
|
237 else: |
cb28d2b3db0b
formatter: add general way to switch hex/short functions
Yuya Nishihara <yuya@tcha.org>
parents:
22674
diff
changeset
|
238 self.hexfunc = short |
16134 | 239 def startitem(self): |
240 pass | |
241 def data(self, **data): | |
242 pass | |
243 def write(self, fields, deftext, *fielddata, **opts): | |
244 self._ui.write(deftext % fielddata, **opts) | |
17909
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
245 def condwrite(self, cond, fields, deftext, *fielddata, **opts): |
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
246 '''do conditional write''' |
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
247 if cond: |
3326fd05eb1f
formatter: add condwrite method
Matt Mackall <mpm@selenic.com>
parents:
17630
diff
changeset
|
248 self._ui.write(deftext % fielddata, **opts) |
16134 | 249 def plain(self, text, **opts): |
250 self._ui.write(text, **opts) | |
29949
e7cacb45c4be
formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents:
29882
diff
changeset
|
251 def isplain(self): |
e7cacb45c4be
formatter: introduce isplain() to replace (the inverse of) __nonzero__() (API)
Mathias De Maré <mathias.demare@gmail.com>
parents:
29882
diff
changeset
|
252 return True |
29837
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
253 def nested(self, field): |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
254 # nested data will be directly written to ui |
5b886289a1ca
formatter: add fm.nested(field) to either write or build sub items
Yuya Nishihara <yuya@tcha.org>
parents:
29836
diff
changeset
|
255 return self |
16134 | 256 def end(self): |
257 pass | |
258 | |
259 class debugformatter(baseformatter): | |
260 def __init__(self, ui, topic, opts): | |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
261 baseformatter.__init__(self, ui, topic, opts, _nullconverter) |
22424
1f72226064b8
formatter: make debug style match Python syntax
Matt Mackall <mpm@selenic.com>
parents:
17909
diff
changeset
|
262 self._ui.write("%s = [\n" % self._topic) |
16134 | 263 def _showitem(self): |
264 self._ui.write(" " + repr(self._item) + ",\n") | |
265 def end(self): | |
266 baseformatter.end(self) | |
22424
1f72226064b8
formatter: make debug style match Python syntax
Matt Mackall <mpm@selenic.com>
parents:
17909
diff
changeset
|
267 self._ui.write("]\n") |
16134 | 268 |
22430
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
269 class pickleformatter(baseformatter): |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
270 def __init__(self, ui, topic, opts): |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
271 baseformatter.__init__(self, ui, topic, opts, _nullconverter) |
22430
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
272 self._data = [] |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
273 def _showitem(self): |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
274 self._data.append(self._item) |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
275 def end(self): |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
276 baseformatter.end(self) |
29324
b501579147f1
py3: conditionalize cPickle import by adding in util
Pulkit Goyal <7895pulkit@gmail.com>
parents:
28957
diff
changeset
|
277 self._ui.write(pickle.dumps(self._data)) |
22430
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
278 |
22474
9da0ef363861
formatter: extract function that encode values to json string
Yuya Nishihara <yuya@tcha.org>
parents:
22447
diff
changeset
|
279 def _jsonifyobj(v): |
29794
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
280 if isinstance(v, dict): |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
281 xs = ['"%s": %s' % (encoding.jsonescape(k), _jsonifyobj(u)) |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
282 for k, u in sorted(v.iteritems())] |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
283 return '{' + ', '.join(xs) + '}' |
4891f3b93182
formatter: add function to convert dict to appropriate format
Yuya Nishihara <yuya@tcha.org>
parents:
29678
diff
changeset
|
284 elif isinstance(v, (list, tuple)): |
22475
17eeda31e52b
formatter: have jsonformatter accept tuple as value
Yuya Nishihara <yuya@tcha.org>
parents:
22474
diff
changeset
|
285 return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']' |
24321
0a714a1f7d5c
formatter: convert None to json null
Yuya Nishihara <yuya@tcha.org>
parents:
22701
diff
changeset
|
286 elif v is None: |
0a714a1f7d5c
formatter: convert None to json null
Yuya Nishihara <yuya@tcha.org>
parents:
22701
diff
changeset
|
287 return 'null' |
22674
06c8b58647b9
formatter: convert booleans to json
Yuya Nishihara <yuya@tcha.org>
parents:
22476
diff
changeset
|
288 elif v is True: |
06c8b58647b9
formatter: convert booleans to json
Yuya Nishihara <yuya@tcha.org>
parents:
22476
diff
changeset
|
289 return 'true' |
06c8b58647b9
formatter: convert booleans to json
Yuya Nishihara <yuya@tcha.org>
parents:
22476
diff
changeset
|
290 elif v is False: |
06c8b58647b9
formatter: convert booleans to json
Yuya Nishihara <yuya@tcha.org>
parents:
22476
diff
changeset
|
291 return 'false' |
22476
a0829ec34dbd
formatter: convert float value to json
Yuya Nishihara <yuya@tcha.org>
parents:
22475
diff
changeset
|
292 elif isinstance(v, (int, float)): |
a0829ec34dbd
formatter: convert float value to json
Yuya Nishihara <yuya@tcha.org>
parents:
22475
diff
changeset
|
293 return str(v) |
22474
9da0ef363861
formatter: extract function that encode values to json string
Yuya Nishihara <yuya@tcha.org>
parents:
22447
diff
changeset
|
294 else: |
9da0ef363861
formatter: extract function that encode values to json string
Yuya Nishihara <yuya@tcha.org>
parents:
22447
diff
changeset
|
295 return '"%s"' % encoding.jsonescape(v) |
9da0ef363861
formatter: extract function that encode values to json string
Yuya Nishihara <yuya@tcha.org>
parents:
22447
diff
changeset
|
296 |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
297 class jsonformatter(baseformatter): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
298 def __init__(self, ui, topic, opts): |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
299 baseformatter.__init__(self, ui, topic, opts, _nullconverter) |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
300 self._ui.write("[") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
301 self._ui._first = True |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
302 def _showitem(self): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
303 if self._ui._first: |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
304 self._ui._first = False |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
305 else: |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
306 self._ui.write(",") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
307 |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
308 self._ui.write("\n {\n") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
309 first = True |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
310 for k, v in sorted(self._item.items()): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
311 if first: |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
312 first = False |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
313 else: |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
314 self._ui.write(",\n") |
22474
9da0ef363861
formatter: extract function that encode values to json string
Yuya Nishihara <yuya@tcha.org>
parents:
22447
diff
changeset
|
315 self._ui.write(' "%s": %s' % (k, _jsonifyobj(v))) |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
316 self._ui.write("\n }") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
317 def end(self): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
318 baseformatter.end(self) |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
319 self._ui.write("\n]\n") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
320 |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
321 class _templateconverter(object): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
322 '''convert non-primitive data types to be processed by templater''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
323 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
324 def formatdate(date, fmt): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
325 '''return date tuple''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
326 return date |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
327 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
328 def formatdict(data, key, value, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
329 '''build object that can be evaluated as either plain string or dict''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
330 data = util.sortdict(_iteritems(data)) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
331 def f(): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
332 yield _plainconverter.formatdict(data, key, value, fmt, sep) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
333 return templatekw._hybrid(f(), data, lambda k: {key: k, value: data[k]}, |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
334 lambda d: fmt % (d[key], d[value])) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
335 @staticmethod |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
336 def formatlist(data, name, fmt, sep): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
337 '''build object that can be evaluated as either plain string or list''' |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
338 data = list(data) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
339 def f(): |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
340 yield _plainconverter.formatlist(data, name, fmt, sep) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
341 return templatekw._hybrid(f(), data, lambda x: {name: x}, |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
342 lambda d: fmt % d[name]) |
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
343 |
25513
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
344 class templateformatter(baseformatter): |
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
345 def __init__(self, ui, topic, opts): |
29836
18bac830eef3
formatter: factor out format*() functions to separate classes
Yuya Nishihara <yuya@tcha.org>
parents:
29794
diff
changeset
|
346 baseformatter.__init__(self, ui, topic, opts, _templateconverter) |
25513
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
347 self._topic = topic |
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
348 self._t = gettemplater(ui, topic, opts.get('template', '')) |
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
349 def _showitem(self): |
28384
3356bf61fa25
formatter: make labels work with templated output
Kostia Balytskyi <ikostia@fb.com>
parents:
26587
diff
changeset
|
350 g = self._t(self._topic, ui=self._ui, **self._item) |
25513
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
351 self._ui.write(templater.stringify(g)) |
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
352 |
25511
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
353 def lookuptemplate(ui, topic, tmpl): |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
354 # looks like a literal template? |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
355 if '{' in tmpl: |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
356 return tmpl, None |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
357 |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
358 # perhaps a stock style? |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
359 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
|
360 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
|
361 or templater.templatepath(tmpl)) |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
362 if mapname and os.path.isfile(mapname): |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
363 return None, mapname |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
364 |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
365 # perhaps it's a reference to [templates] |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
366 t = ui.config('templates', tmpl) |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
367 if t: |
28630
bf35644b9f3a
templater: relax unquotestring() to fall back to bare string
Yuya Nishihara <yuya@tcha.org>
parents:
28384
diff
changeset
|
368 return templater.unquotestring(t), None |
25511
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
369 |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
370 if tmpl == 'list': |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
371 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
|
372 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
|
373 |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
374 # 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
|
375 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
|
376 # 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
|
377 if os.path.basename(tmpl).startswith("map-"): |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
378 return None, os.path.realpath(tmpl) |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
379 tmpl = open(tmpl).read() |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
380 return tmpl, None |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
381 |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
382 # constant string? |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
383 return tmpl, None |
c2a4dfe2a336
formatter: move most of template option helper to formatter
Matt Mackall <mpm@selenic.com>
parents:
24321
diff
changeset
|
384 |
25512
8463433c2689
formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents:
25511
diff
changeset
|
385 def gettemplater(ui, topic, spec): |
8463433c2689
formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents:
25511
diff
changeset
|
386 tmpl, mapfile = lookuptemplate(ui, topic, spec) |
28954
f97a0bcfd7a1
templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents:
28630
diff
changeset
|
387 assert not (tmpl and mapfile) |
f97a0bcfd7a1
templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents:
28630
diff
changeset
|
388 if mapfile: |
f97a0bcfd7a1
templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents:
28630
diff
changeset
|
389 return templater.templater.frommapfile(mapfile) |
28955
78759f78a44e
templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents:
28954
diff
changeset
|
390 return maketemplater(ui, topic, tmpl) |
78759f78a44e
templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents:
28954
diff
changeset
|
391 |
78759f78a44e
templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents:
28954
diff
changeset
|
392 def maketemplater(ui, topic, tmpl, filters=None, cache=None): |
78759f78a44e
templater: factor out function that creates templater from string template
Yuya Nishihara <yuya@tcha.org>
parents:
28954
diff
changeset
|
393 """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
|
394 aliases = ui.configitems('templatealias') |
d813132ea361
templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents:
28955
diff
changeset
|
395 t = templater.templater(filters=filters, cache=cache, aliases=aliases) |
25512
8463433c2689
formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents:
25511
diff
changeset
|
396 if tmpl: |
8463433c2689
formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents:
25511
diff
changeset
|
397 t.cache[topic] = tmpl |
8463433c2689
formatter: add a method to build a full templater from a -T option
Matt Mackall <mpm@selenic.com>
parents:
25511
diff
changeset
|
398 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
|
399 |
16134 | 400 def formatter(ui, topic, opts): |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
401 template = opts.get("template", "") |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
402 if template == "json": |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
403 return jsonformatter(ui, topic, opts) |
22430
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
404 elif template == "pickle": |
968247e8f4ac
formatter: add pickle format
Matt Mackall <mpm@selenic.com>
parents:
22428
diff
changeset
|
405 return pickleformatter(ui, topic, opts) |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
406 elif template == "debug": |
16134 | 407 return debugformatter(ui, topic, opts) |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
408 elif template != "": |
25513
0c6f98398f8a
formatter: add template support
Matt Mackall <mpm@selenic.com>
parents:
25512
diff
changeset
|
409 return templateformatter(ui, topic, opts) |
25838
31137258ae8b
formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents:
25513
diff
changeset
|
410 # developer config: ui.formatdebug |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
411 elif ui.configbool('ui', 'formatdebug'): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
412 return debugformatter(ui, topic, opts) |
25838
31137258ae8b
formatter: mark developer options
Matt Mackall <mpm@selenic.com>
parents:
25513
diff
changeset
|
413 # deprecated config: ui.formatjson |
22428
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
414 elif ui.configbool('ui', 'formatjson'): |
427e80a18ef8
formatter: add json formatter
Matt Mackall <mpm@selenic.com>
parents:
22424
diff
changeset
|
415 return jsonformatter(ui, topic, opts) |
16134 | 416 return plainformatter(ui, topic, opts) |