Commit Graph

85 Commits

Author SHA1 Message Date
Yuya Nishihara
02022fc3c5 util: wrap s.encode('string_escape') call for future py3 compatibility 2017-03-15 23:06:50 +09:00
timeless
109fcbc79e pycompat: switch to util.urlreq/util.urlerr for py3 compat 2016-04-06 23:22:12 +00:00
FUJIWARA Katsunori
15ff9ca52f templatefilters: use templatefilter to mark a function as template filter
Using decorator can localize changes for adding (or removing) a
template filter function in source code.

This patch also removes leading ":FILTER:" part in help document of
each filters, because using templatefilter makes it useless.

This patch uses not 'filter' but 'templatefilter' as a decorator name,
because the former name hides Python built-in one, even though the
latter is a little redundant in 'templatefilters.py'.
2016-03-30 02:10:44 +09:00
FUJIWARA Katsunori
098aa2f5a6 registrar: add templatefilter to mark a function as template filter (API)
This patch also adds loadfilter() to templatefilters, because this
combination helps to figure out how they cooperate with each other.

Listing up loadfilter() in dispatch.extraloaders causes implicit
loading template filter functions at loading (3rd party) extension.

This change requires that "templatefilter" attribute of (3rd party)
extension is registrar.templatefilter or so.
2016-03-30 02:10:44 +09:00
Yuya Nishihara
088b5128e7 templatefilters: drop old jsonescape() function
It's been superseded by encoding.jsonescape(paranoid=True).
2015-12-27 18:50:03 +09:00
Yuya Nishihara
2e33bbee20 templatefilters: make json filter be byte-transparent (BC) (issue4926)
This is necessary to preserve filename encoding over JSON. Instead, this
patch inserts "|utf8" where non-ascii local-encoding texts can be passed
to "|json".

See also the commit that introduced "utf8" filter.
2015-12-27 17:59:57 +09:00
Yuya Nishihara
5236f2a921 templatefilters: add "utf8" to get utf-8 bytes from local-encoding text
This will be applied prior to "|json" filter. This sounds like odd, but it
is necessary to handle local-encoding text as well as raw filename bytes.

Because filenames are bytes in Mercurial and Unix world, {filename|json} should
preserve the original byte sequence, which implies

  {x|json} -> '"' toutf8b(x) '"'

On the other hand, most template strings are in local encoding. Because
"|json" filter have to be byte-transparent to filenames, we need something to
annotate an input as a local string, that's what "|utf8" will do.

  {x|utf8|json} -> '"' toutf8b(fromlocal(x)) '"'

"|utf8" is an explicit call, so aborts if input bytes can't be converted to
UTF-8.
2015-12-27 17:45:05 +09:00
Yuya Nishihara
064b729470 templatefilters: drop broken "jsonescape" from filters table (BC)
It's been unused, undocumented and flawed in that it expects a unicode input,
never works correctly if an input has non-ascii character. We should use "json"
filter instead.
2015-12-27 17:16:45 +09:00
Matt Mackall
61d5d53d27 merge with stable 2015-11-04 15:17:52 -06:00
Yuya Nishihara
dda890d7ab templatefilters: try round-trip utf-8 conversion by json filter (issue4933)
As JSON string is known to be a unicode, we should try round-trip conversion
for localstr type. This patch tests localstr type explicitly because
encoding.fromlocal() may raise Abort for undecodable str, which is probably
not what we want. Maybe we can refactor json filter to use encoding module
more later.

Still "{desc|json}" can't round-trip because showdescription() modifies a
localstr object.
2015-11-04 23:48:15 +09:00
Pierre-Yves David
4258ec762f uescape: also encode non-printable char under 128
We were assuming everything under 128 was printable ascii, but there are a lot
of control characters in that range that can't simply be included in json and
other targets. We forcibly encode everything under 32, because they are either
control char or oddly printable (like tab or line ending).

We also add the hypothesis-powered test that caught this.
2015-11-02 11:56:59 +00:00
Yuya Nishihara
246636f6db templater: port localdate filter to a function
It will be extended to accept a timezone argument.
2015-09-01 19:15:16 +09:00
Yuya Nishihara
4377cc9e4b templatefilters: remove redundant 'date' and 'strip' filters
These filters are defined as 'date()' and 'strip()' functions. Help messages
are moved to the corresponding functions.
2015-07-04 16:07:42 +09:00
Gregory Szorc
edfcac720c templatefilters: use absolute_import 2015-08-08 20:08:52 -07:00
Anton Shestakov
939c576f07 templates: introduce revescape filter for escaping symbolic revisions
There needs to be a way to escape symbolic revisions containing forward
slashes, but urlescape filter doesn't escape slashes at all (in fact, it is
used in places where forward slashes must be preserved).

The filter considers @ to be safe just for bookmarks like @ and @default to
look good in urls.
2015-07-12 16:47:56 +08:00
Jordi Gutiérrez Hermoso
0618dc68e3 templatefilters: don't stringify None into "None"
A few template keywords can in fact return None, such as {bisect}. In
some contexts, these get stringified into None instead of "". This is
leaking Python details into the UI.
2015-05-10 13:33:51 -04:00
Yuya Nishihara
97a7438eb1 templatefilters: add "upper" and "lower" for case conversion
Typically it will be used in patchbomb's flag template, which will be
implemented by future patches.
2015-03-30 23:54:29 +09:00
Gregory Szorc
0103ac9a7b templatefilters.json: stabilize output
The json filter was previously iterating over keys in an object in an
undefined order. Let's throw a sorted() in there so output is
consistent.

It's somewhat frightening that there are no tests for the json filter.
Subsequent commits will add them, so we pass on the opportunity to add
them here.
2014-12-31 13:48:55 -08:00
Gregory Szorc
ad5d2929fc templatefilters.json: call functions
The "changeset" template from hgweb is using a lambda in the
"diffsummary" key. In preparation for enabling JSON output from hgweb,
teach the json filter how to call functions.
2014-12-31 11:22:17 -08:00
Anton Shestakov
ca791cb0ef templater: add count template filter, plus tests
Previously there was no way of telling how much children or bookmarks or tags a
certain changeset has in a template. It was possible to tell if a changeset has
either 0 or not 0 bookmarks, but not to tell if it has 1 or 2 of them, for
example.

This filter, simply named count, makes it possible to count the number of items
in a list or the length of a string (or, anything that python's len can count).
E.g.: {children|count}, {bookmarks|count}, {file_adds|count}.

Testing the filter on node hash and shortened node hash is chosen because they
both have defined length.

As for lists of strings - children, tags and file_adds are used, because they
provide some variety and also prove that what's counted is the number of string
items in the list, and not the list stringified (they are lists of non-empty,
multi-character strings).

Additionally, revset template function is used for testing the filter, since
the combination is very flexible and will possibly be used together a lot.

(The previous version of this patch had an incorrect email subject and was
apparently lost - patchwork says the patch has been accepted, but it's not so.
The changes between that and this patch are minimal: now the filter does not
disturb the alphabetical order of function definitions and dict keys.)
2014-09-09 22:14:13 +09:00
Matt Mackall
5fc8526562 merge with stable 2014-07-14 18:53:03 -05:00
Matt Mackall
de2b99d87c templates: escape NUL bytes in jsonescape (issue4303)
It's currently possible for various fields to contain NUL bytes, which
are disallowed in JSON.
2014-07-14 12:44:45 -05:00
Ryan McElroy
9f5399cbcd templatefilter: add splitlines function
This is useful for applying changes to each line, and it's especially powerful
when used in conjunction with conditionals to modify lines based on content.
2014-06-12 17:45:41 -07:00
Matt Mackall
397a3b5d72 merge with stable 2013-10-09 14:15:34 -07:00
Matt Mackall
23bced957e json: add more paranoid escaping 2013-10-09 11:50:19 -07:00
Mads Kiilerich
1e900bb145 check-code: check for spaces around = for named parameters 2013-10-03 14:50:47 +02:00
David Soria Parra
bd9e14bcec templatefilters: add short format for age formatting
Implements a short output format for ages e.g. "1 second ago" is
abbrevated as "1s ago".
2013-09-17 17:42:13 +02:00
Matt Mackall
dbd9dd9280 template: fix tabindent docstring (issue2880) 2013-07-19 12:58:30 -05:00
Sean Farley
44577c753d templater: add indentation arguments to the fill function 2013-04-18 15:48:22 -05:00
Sean Farley
8a5d9c21d4 templater: move templatefilters.func into the same place as the other funcs 2013-04-10 18:56:38 -05:00
Mads Kiilerich
00a100f5a5 merge with stable 2013-02-28 14:51:59 +01:00
Mads Kiilerich
93a2b8faf0 templatefilters: add missing import of _ 2013-02-28 13:55:00 +01:00
Angel Ezquerra
ed79324ad4 hgweb: add websub template filter
The purpose of this new filter is to make it possible to partially replace the
functionality of the interhg extension. The idea is to be able to define regular
expression based substitutions on a new "websub" config section. hgweb will then
be able to apply these substitutions wherever the "websub" filter is used on a
template.

This first revision just adds the code necessary to load the websub expressions
and adds the websub filter, but it does not add any calls to the websub filter
itself on any of the templates. That will be done on the following revisions.
2013-02-08 18:05:32 +01:00
Siddharth Agarwal
a03ea859ec hgweb: make the escape filter remove null characters (issue2567) 2012-10-15 09:43:34 -07:00
Christian Ebert
15900b9e01 templatefilters: avoid traceback caused by bogus date input (issue3344)
Wrap datefilters which split date texts with util.parsedate.

We do not abort, as the bogus date must have been given by the user.
2012-08-10 20:37:20 +01:00
Matt Mackall
14f92efff9 templatefilters: add parameterized date method 2012-09-24 15:54:45 -05:00
Matt Mackall
3289404a04 templatefilters: add parameterized fill function 2012-09-24 15:54:44 -05:00
Brodie Rao
a7ef0a0cc5 cleanup: "not x in y" -> "x not in y" 2012-05-12 16:00:57 +02:00
Matteo Capobianco
8305e8d305 templates/filters: extracting the user portion of an email address
Currently, the 'user' filter is using util.shortuser(text) (which clearly
doesn't extract only the user portion of an email address, even though the
help text says it does).

The new 'emailuser' filter uses the new util.emailuser(text) function which,
instead, does exactly that.

The help text on the 'user' filter has been modified accordingly.
2012-03-28 16:06:20 +02:00
Yann E. MORIN
e24b85ec3e templates/filters: add doctest to the 'person' filter
Add a doctest with an hopefuly-comprehensive list of combinations
we can expect in real-life situations.

This does not cover corner cases, for example when a CR or LF is
embedded in the name (allowed by RFC 5322!).

Code in tests/test-doctest.py contributed by:
    Martin Geisler <mg@aragost.com>
Thanks!

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
2012-03-07 01:02:12 +01:00
Yann E. MORIN
14521673fb templates/filters: strip quotes from {author|person}
RFC5322 (Internet Message Format) [0] says that the 'display name' of
an internet address [1] (what Mercurial calls 'person') can be quoted
with DQUOTE (ASCII 34: ") if it contains non-atom characters [2].
For example, dot '.' is a non-atom character. Also, DQUOTEs in a
quoted string will be escaped using "\" [2][3].

The current {author|person} template+filter just extracts the part
before an email address as-is. This can look ugly, especially on the
web interface, or when generating output for post-processing...

Moreover, as an example, the Mercurial repository has a bunch of
incoherent uses of DQUOTES in author names. As per Matt's digging:

  $ hg log --template "{author|person}\n" | grep '"' | sort | uniq
  "Andrei Vermel
  "Aurelien Jacobs
  "Daniel Santa Cruz
  "Hidetaka Iwai
  "Hiroshi Funai"
  "Mathieu Clabaut
  "Paul Moore
  "Peter Arrenbrecht"
  "Rafael Villar Burke
  "Shun-ichi GOTO"
  "Wallace, Eric S"
  "Yann E. MORIN"
  Josef "Jeff" Sipek
  Radoslaw "AstralStorm" Szkodzinski

Fix the 'person' filter to remove leading and trailing DQUOTES,
and unescape remaining DQUOTES.

Given this author: "J. \"random\" DOE" <john@doe.net>
  before:   {author|person} : "J. \"random\" DOE"
  after:    {author|person} : J. "random" DOE

For the Mercurial repository, that leaves us with two authors with
DQUOTES, in acceptable positions:

  $ hg log --template "{author|person}\n" | grep '"' | sort | uniq
  Josef "Jeff" Sipek
  Radoslaw "AstralStorm" Szkodzinski

[0] https://tools.ietf.org/html/rfc5322
[1] https://tools.ietf.org/html/rfc5322#section-3.4
[2] https://tools.ietf.org/html/rfc5322#section-3.2.4
[3] https://tools.ietf.org/html/rfc5322#section-3.2.1

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
2012-03-06 23:23:30 +01:00
Yann E. MORIN
ad9ca506f5 templates: add 'bisect' keyword to return a cset's bisect status
This new 'bisect' template expands to a cset's bisection status (good,
bad and so on...). There is also a new 'shortbisect' filter that yields
a single char representing the cset's bisection status.

It uses the two recently-added hbisect.label() and .shortlabel() functions.

Example output using the repository in test-bisect2.t, and some made-up
state of the 'end at merge' test (with graphlog, it's so explicit):

  $ hg glog --template '{rev}:{node|short} {bisect}\n'  \
            -r 'bisect(range)|bisect(ignored)'
  o  17:228c06deef46: bad
  |
  o  16:609d82a7ebae: bad (implicit)
  |
  o    15:857b178a7cf3: bad
  |\
  | o  13:b0a32c86eb31: good
  | |
  | o  12:9f259202bbe7: good (implicit)
  | |
  | o  11:82ca6f06eccd: good
  | |
  @ |    10:429fcd26f52d: untested
  |\ \
  | o |  9:3c77083deb4a: skipped
  | |/
  | o  8:dab8161ac8fc: good
  | |
  o |    6:a214d5d3811a: ignored
  |\ \
  | o |  5:385a529b6670: ignored
  | | |
  o | |  4:5c668c22234f: ignored
  | | |
  o | |  3:0950834f0a9c: ignored
  |/ /
  o /  2:051e12f87bf1: ignored
  |/

And now the same with the short label:

  $ hg log --template '{bisect|shortbisect} {rev}:{node|short}\n'
    18:d42e18c7bc9b
  B 17:228c06deef46
  B 16:609d82a7ebae
  B 15:857b178a7cf3
    14:faa450606157
  G 13:b0a32c86eb31
  G 12:9f259202bbe7
  G 11:82ca6f06eccd
  U 10:429fcd26f52d
  S 9:3c77083deb4a
  G 8:dab8161ac8fc
    7:50c76098bbf2
  I 6:a214d5d3811a
  I 5:385a529b6670
  I 4:5c668c22234f
  I 3:0950834f0a9c
  I 2:051e12f87bf1
    1:4ca5088da217
    0:33b1f9bc8bc5

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-22 01:36:01 +02:00
Augie Fackler
ababdf1e2e templatefilters: use safehasattr instead of hasattr 2011-07-25 16:02:42 -05:00
Augie Fackler
2e41c2e64a globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__') 2011-07-25 15:30:19 -05:00
Matt Mackall
1d5abac148 help: consolidate topic hooks in help.py
This removes loops like cmdutil->revset->help->extensions->cmdutil and
simplifies the code.
2011-05-13 12:57:27 -05:00
Adrian Buehlmann
3a0445e3c8 templatefilters: improve person() for john.doe@example.com
BEFORE: person('john.doe@example.com') -> 'john'
AFTER:  person('john.doe@example.com') -> 'john doe'
2011-04-17 21:34:25 +02:00
timeless
56241a1f0c templates: provide granularity for future values for age filter 2011-03-16 03:28:56 +01:00
Patrick Mezard
d297dd65c7 help: extract items doc generation function 2011-03-12 12:46:31 +01:00
Patrick Mezard
daf132553b templatefilters: move doc from templates.txt to docstrings 2011-03-12 12:46:31 +01:00
Patrick Mezard
456bc03d53 templatefilters: wrap all filters in dedicated functions
This will highly simplify the docstring integration. I measured "hg log
--style=changelog" duration on mercurial itself and could not detect any
difference.
2011-03-12 12:46:31 +01:00