Commit Graph

70 Commits

Author SHA1 Message Date
Siddharth Agarwal
bf23516938 jsonchangeset: don't honor whitespace and format-changing diffopts
JSON is meant to be parsed by computers, and format changes can break them.
2014-11-18 22:13:05 -08:00
Matt Mackall
7e6c7ddb4e merge with stable 2014-10-10 12:15:46 -05:00
Matt Mackall
8090c41031 templater: fix ifcontains when list is a string (issue4399) 2014-10-10 11:38:00 -05:00
Yuya Nishihara
525193c247 templater: fix precedence of --style and --template options
Since 266cfa7de44d, --template option is ignored if --style is specified,
which is wrong according to the doc of show_changeset():

    Display format will be the first non-empty hit of:
    1. option 'template'
    2. option 'style'
    ...
2014-09-30 23:15:56 +09:00
Jordi Gutiérrez Hermoso
49b364f72a log: rewrite default template to use labels (issue2866)
This is a complete rewrite of the default template to use labels. This
seems ultimately useless to me in most cases. The biggest benefit of
this patch to me seems to be a fairly complicated example of the
templating engine. It was a lot of hard work to figure out the precise
acceptable syntax, since it's almost undocumented. Hat tip to Steve
Losh's smartlog template, which helped me figure out a lot of the
syntax. Hopefully later I can use the present default log template
as an example for documenting the templating engine.

A test is attached. My goal was to match the --color=debug output,
which may differ slightly in newlines from the actual ANSI escape
codes output. I consider this an acceptable invisible deviation.

There seems to be a considerable slowdown with this rewrite.

Before:

    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.882s
    user  0m0.812s
    sys   0m0.064s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.872s
    user  0m0.796s
    sys   0m0.068s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.917s
    user  0m0.836s
    sys   0m0.076s

After:

    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.480s
    user  0m1.392s
    sys   0m0.072s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.500s
    user  0m1.400s
    sys   0m0.088s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.462s
    user  0m1.364s
    sys   0m0.092s

Following the maxim, "make it work, profile, make it faster, in that
order", I deem this slowdown acceptable for now.

I suspect but have not confirmed that a big slowdown comes from
calling keywords twice in the file templates, once to test the
existence of output and again to actually list the output. If so, a
simple speedup might be to improve the templating engine to cache
keywords when called more than once on the same revision.

TODO: I found a bug while working on this. The following stack traces:

    hg log -r . -T '{ifcontains(phase, "secret public", "lol", "omg")}\n'
2014-10-03 19:48:56 -04:00
Jordi Gutiérrez Hermoso
281cec5b64 templater: set the correct phase for parents
Akin to b5baef1e39f6 which did this for `hg log`, the following sets
the correct phase for the {phase} keyword when the context is a parent
of the current cset. This allows templates such as the following to be
defined,

    parent = '{label("log.parent changeset.{phase}",
                      "parent:      {rev}:{node|formatnode}")}\n'

which when called on a parent (e.g. with the `parents` template
keyword), will produce the correct phase.
2014-10-03 22:03:31 -04: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
0602ddc218 merge with stable 2014-09-30 18:22:58 -05:00
FUJIWARA Katsunori
330bc07caa templater: add "diff" template function
"diff" allows to embed changes in the target revision into template
output, even if the command itself doesn't take "--patch" option

Combination of "[committemplate]" configuration and "diff" template
function can achieve the feature like issue231 ("option to have diff
displayed in commit editor buffer")

    http://bz.selenic.com/show_bug.cgi?id=231

For example, templating below can be used to add each "diff" output
lines "HG: " prefix::

      {splitlines(diff) % 'HG: {line}\n'}

This patch implements "diff" not as "a template keyword" but as "a
template function" to take include/exclude patterns at runtime.

It allows to specify target files of command (by -I/-X command line
options) and "diff" separately.
2014-08-28 22:45:36 +09:00
Matt Mackall
7cc7319641 cmdutil: add json style to log-like commands
Sadly, this can't be done with the normal templater like we do with
XML due to JSON's inter-record comma rules.
2014-09-15 13:11:13 -05:00
FUJIWARA Katsunori
baa869750d templater: enable alias predicates to be used in "revset()" function
Before this patch, predicates defined in "[revsetalias]" can't be used
in the query specified to template function "revset()", because:

  - "revset()" uses "localrepository.revs()" to get query result, but
  - "localrepository.revs()" passes "None" as "ui" to "revset.match()", then
  - "revset.match()" can't recognize any alias predicates

To enable alias predicates to be used in "revset()" function, this
patch invokes "revset.match()" directly with "repo.ui".

This patch doesn't make "localrepository.revs()" pass "self.ui" to
"revset.match()", because this may be intentional implementation to
prevent alias predicates from shadowing built-in ones and breaking
functions internally using "localrepository.revs()".

Even if it isn't intentional one, the check for shadowing should be
implemented (maybe on default branch) before fixing it for safety.
2014-08-23 21:23:02 +09:00
Matt Mackall
f648f507dd templates: re-add template listing support
We used to have --style nosuch to list templates, but --style is now
merged with --template/-T where random strings are acceptable
templates. So we reserve 'list' to allow listing templates.
2014-07-25 15:35:09 -05:00
FUJIWARA Katsunori
843d08c987 templatekw: add 'currentbookmark' keyword to show current bookmark easily
Before this patch, complicated template expression below is required
to show current active bookmark if it is associated with the
changeset.

    "{bookmarks % '{ifeq(bookmark, current, \"{bookmark}\")}'}"

This patch add 'currentbookmark' keyword to show current bookmark
easily.
2014-07-15 23:34:13 +09:00
Ryan McElroy
2464893018 templater: introduce word function
This function allows returning only the nth "word" from a string. By default
a string is split as by Python's split() function default, but an optional
third parameter can also override what string the string is split by.
2014-06-12 18:02:23 -07:00
Ryan McElroy
e3b09c4564 templater: add symbol to error
This patch makes it easier to debug writing templater functions by
telling the user exactly what was sent to the templater.
2014-06-12 18:07:21 -07:00
Ryan McElroy
f735b30979 templater: introduce startswith function
This function returns a string only if it starts with a given string.
It is particularly useful when combined with splitlines and/or used with
conditionals that fail when empty strings are passed in to take action
based on the contents of a line.
2014-06-12 17:53:37 -07: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
Durham Goode
63d5c92a11 templates: fix ifcontains against sets with length > 1 (issue4259)
Previously the ifcontains revset was checking against the set using a pure
__contains__ check.  It turns out the set was actually a list of
formatted strings meant for ui output, which meant the contains check failed if
the formatted string wasn't significantly different from the raw value.

This change makes it check against the raw data, prior to it being formatted.
2014-05-23 16:25:55 -07:00
Mads Kiilerich
0e8795ccd6 spelling: fixes from spell checker 2014-04-13 19:01:00 +02:00
Kevin Bullock
c63d1fcf68 merge with stable
This should correct an earlier couple of bad merges (5433856b2558 and
596960a4ad0d, now pruned) that accidentally brought in a change that had
been marked obsolete (244ac996a821).
2014-03-31 10:12:07 -05:00
Sean Farley
029b060498 templater: raise error for unknown func
Previously, if a template '{foo()}' was given, the buildfunc would not be able
to match it and hit a code path that would not return so it would error out
later in the templater stating that NoneType was not iterable. This patch makes
sure that a proper error is raised so that the user can be informed.

Tests have been updated.
2014-03-27 17:21:27 -05:00
FUJIWARA Katsunori
d28789bf48 templater: make strings in template expressions be "string-escape"-ed correctly
Changeset 83ff877959a6 (released with 2.8.1) fixed "recursively
evaluate string literals as templates" problem (issue4102) by moving
the location of "string-escape"-ing from "tokenizer()" to
"compiletemplate()".

But some parts in template expressions below are not processed by
"compiletemplate()", and it may cause unexpected result.

  - 'expr' of 'if(expr, then, else)'
  - 'expr's of 'ifeq(expr, expr, then, else)'
  - 'sep' of 'join(list, sep)'
  - 'text' and 'style' of 'rstdoc(text, style)'
  - 'text' and 'chars' of 'strip(text, chars)'
  - 'pat' and 'repl' of 'sub(pat, repl, expr)'

For example, '\n' of "{join(extras, '\n')}" is not "string-escape"-ed
and treated as a literal '\n'. This breaks "Display the contents of
the 'extra' field, one per line" example in "hg help templates".

Just "string-escape"-ing on each parts above may not work correctly,
because inside expression of nested ones already applies
"string-escape" on string literals. For example:

  - "{join(files, '\n')}" doesn't return "string-escape"-ed string, but
  - "{join(files, if(branch, '\n', '\n'))}" does

To fix this problem, this patch does:

  - introduce "rawstring" token and "runrawstring" method to handle
    strings not to be "string-escape"-ed correctly, and

  - make "runstring" method return "string-escape"-ed string, and
    delay "string-escape"-ing until evaluation

This patch invokes "compiletemplate()" with "strtoken=exp[0]" in
"gettemplate()", because "exp[1]" is not yet evaluated. This code path
is tested via mapping ("expr % '{template}'").

In the other hand, this patch invokes it with "strtoken='rawstring'"
in "_evalifliteral()", because "t" is the result of "arg" evaluation
and it should be "string-escape"-ed if "arg" is "string" expression.

This patch doesn't test "string-escape"-ing on 'expr' of 'if(expr,
then, else)', because it doesn't affect the result.
2014-03-10 01:01:43 +09:00
FUJIWARA Katsunori
f3e5f1e6c1 templater: apply "stringify()" on sub expression to get string correctly
Templating syntax allows nested expression to be specified as parts
below, but they are evaluated as a generator and don't work correctly.

  - 'sep' of 'join(list, sep)'
  - 'text' and 'chars' of 'strip(text, chars)'

In the former case, 'sep' returns expected string only for the first
separation, and empty one for the second or later, because the
generator has only one element.

In the latter case, templating is aborted by exception, because the
generator doesn't have 'strip()' method (as 'text') and can't be
passed as the argument to 'str.strip()' (as 'chars').

This patch applies "stringify()" on these sub expression to get string
correctly.
2014-03-10 01:01:43 +09:00
FUJIWARA Katsunori
7a7d1bc22c templater: avoid recursive evaluation of string literals completely
Changeset c84f81c3e120 (released with 2.8.1) fixed "recursively
evaluate string literals as templates" problem (issue4103) by
introducing "_evalifliteral()".

But some parts in template expressions below are still processed by
the combination of "compiletemplate()" and "runtemplate()", and may
cause same problem unexpectedly.

  - 'init' and 'hang' of 'fill(text, width, init, hang)'
  - 'expr' of 'sub(pat, repl, expr)'
  - 'label' of 'label(label, expr)'

This patch processes them by "_evalifliteral()" instead of the
combination of "compiletemplate()" and "runtemplate()" to avoid
recursive evaluation of string literals completely.
2014-03-10 01:01:42 +09:00
Matt Mackall
3672c23fd5 merge with stable 2014-03-11 16:19:08 -05:00
Matt Mackall
94e268974b templating: make -T much more flexible
It can now accept styles and paths and references to settings in
[templates].
2014-03-08 17:38:50 -06:00
Matt Mackall
a759f7ceae commands: add -T alternative to --template 2014-03-08 15:27:25 -06:00
Durham Goode
2d869e6a8e template: add 'current' to scope during {bookmarks % ...}
This adds the keyword 'current' to the template scope when processing a
bookmark list. The 'current' keyword resolves to the name of the currently
active bookmark in the repo. This allows us to apply special labels to the
current bookmark to distinguish it (especially in the case where there are
multiple bookmarks on the same commit).

Example: "{bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}"

Results in a space separated list of bookmarks where the current bookmark has
an asterix.
2014-02-11 21:40:33 -08:00
Durham Goode
f8aca20bcb template: add revset() template function
Adds a template function that executes a revset and returns the list of
revisions as the result. It has the signature 'revset(query [, args...])'. The
args are optional and are applied to the query string using the standard
python string.format(args) pattern. This allows things like:
'{revset("parents({0})", rev)}' to produce the parents of each individual
commit in the log output.  If no args are specified, the revset result is
cached for the duration of the templater; so it's better to not use args if
performance is a concern.

By itself, revset() can be used to print commit parents, print the common
ancestor of a commit with the main branch, etc.

It can be used with the ifcontains() function to do things like
'{ifcontains(rev, revset('.'), label(...), ...)}' to color the working copy
parent, to color certain branches, to color draft commits, etc.
2014-02-11 21:04:12 -08:00
Durham Goode
cb61deed09 template: add ifcontains template function
Adds a template function with the signature 'ifcontains(item, set, then[,
else])'.  It can be used to do things like '{ifcontains('.hgignore',
file_mods, label(...), ...)}' to color commits that edit the .hgignore file.
A future patch will add the revset() function which will combine with
ifcontains to allow us to color commits if they are in the revset.
2014-02-11 21:10:00 -08:00
Durham Goode
fe9653ca83 template: add pad function for padding output
Adds a pad template function with the following signature:

pad(text, width, fillchar=' ', right=False)

This uses the standard python ljust and rjust functions to produce a string
that is at least a certain width. This is useful for aligning variable length
strings in log output (like user names or shortest(node) output).
2014-01-17 00:16:48 -08:00
Durham Goode
156d6da226 template: add shortest(node) template function
Adds a '{shortest(node)}' template function that results in the shortest hex node
that uniquely identifies the changeset at that time. The minimum length can be
specified as an optional second argument and defaults to 4.

This is useful for producing prettier log output, like so:

@  durham  shortestnode
|  77cf    template: add pad function for padding output
|
o  durham
|  b183    template: add shortestnode keyword
|
o  pierre-yves @
|  6545    backout: add a message after backout that need manual commit
|
| o  durham   manifestcache
|/   93f0    manifest cache
|
| o  durham   catperf
| |  c765    cat: increase perf when catting single files
| |
| o  durham
|/   9c53    changectx: increase perf of walk function
|
2014-01-17 00:10:37 -08:00
Matt Mackall
df890e8b8a merge with stable 2013-11-21 15:08:30 -06:00
Siddharth Agarwal
5b9c86b786 test-command-template.t: fix failure due to trailing whitespace 2013-11-21 12:47:03 -08:00
Matt Mackall
fb22d26dbd templater: makes branches work correctly with stringify (issue4108) 2013-11-21 11:30:52 -06:00
Matt Mackall
52dafe7a2a templater: only recursively evaluate string literals as templates (issue4103) 2013-11-18 15:37:09 -05:00
Matt Mackall
c9a233d77e templater: fix escaping in nested string literals (issue4102)
Before the templater got extended for nested expressions, it made
sense to decode string escapes across the whole string. Now we do it
on a piece by piece basis.
2013-11-18 14:02:26 -05:00
Matt Mackall
74cf3d4bf4 merge with stable 2013-11-19 11:29:56 -05:00
Matt Mackall
280eec0087 tests: skip tests that require not having root (issue4089)
This adds a new root hghave to test against. Almost all of these are a
subset of unix-permissions, but that is also used for checking exec
bit handling.
2013-11-14 18:07:43 -06:00
Matt Mackall
6e88e21cca date: allow %z in format (issue4040) 2013-11-07 15:24:23 -06:00
Alexander Plavin
38dc1f0139 templater: support using templates with non-standard names from map file
Allow to add arbitrarily-named entries to a template map file and then
reference them, to make it possible to deduplicate and simplify
templates code.
2013-09-22 13:52:18 +04:00
Alexander Plavin
10b1e709b7 templater: add strip function with chars as an extra argument
This allows specifying characters to strip, like the Python strip function.
2013-06-25 21:02:22 +04:00
Augie Fackler
40d8d30902 templater: fix output instability from gsoc patches 2013-05-02 20:41:22 -05:00
Sean Farley
766233e4bb template: call runtemplate on the src argument to sub
This allows using a template keyword on calls to the sub function and brings
the function inline with most other semantics of the other template functions.
2013-04-10 19:27:49 -05:00
Matt Mackall
7f909e9c22 templatekw: add default styles for hybrid types (issue3887)
This allows elements like file_copies to be printed as 'name (source)'
when used with join.
2013-04-16 09:44:29 -05:00
Brendan Cully
6bf5800d14 templater: back out 0da42d2ff029, it breaks schemes ({1}) 2013-04-09 21:38:08 -07:00
Brendan Cully
1c111a8da8 template: allow unquoted int function arguments 2013-04-07 23:25:50 -07:00
Matt Mackall
b88b659df4 templater: properly handle file_copies with % 2013-02-22 13:45:46 -06:00
Benoit Boissinot
487f5cb58d test-command-template.t: make "age" filter test work on Feb 29th
reported by Julien Cristau.
2013-01-02 13:59:07 +01:00
Augie Fackler
f909cd2da7 test-command-template.t: fix test so it all year
This test started failing for me after midnight UTC on December
31st. Fixed it by specifying a date 7 years in the future more
precisely (rather than just adding 8 to the year and specifying
January 1st), which allows the test to pass both now and on 2012-12-01
at the same time.
2012-12-31 21:50:35 -06:00