Commit Graph

304 Commits

Author SHA1 Message Date
Yuya Nishihara
e5c5114662 templater: port formatnode filter from changeset_templater
This slightly reduces the difference between changeset_templater and formatter,
and helps extending formatter to support changeset templating.

New formatnode() is not a template filter, but a function since a filter
cannot access to ui. And it's marked as DEPRECATED since I think it exists
only for compatibility reasons.
2017-02-25 16:26:58 +09:00
Yuya Nishihara
b2229f5117 revset: split language services to revsetlang module (API)
New revsetlang module hosts parser, tokenizer, and miscellaneous functions
working on parsed tree. It does not include functions for evaluation such as
getset() and match().

  2288 mercurial/revset.py
   684 mercurial/revsetlang.py
  2972 total

get*() functions are aliased since they are common in revset.py.
2017-02-19 18:19:33 +09:00
Pulkit Goyal
c109648881 py3: replace os.altsep with pycompat.altsep
All the occurences of os.altsep are replaced with pycompat.altsep which
returns bytes.
2016-12-18 01:17:12 +05:30
Pulkit Goyal
5629f71f5b py3: replace os.sep with pycompat.ossep (part 3 of 4) 2016-12-17 20:14:24 +05:30
Mads Kiilerich
38cb771268 spelling: fixes of non-dictionary words 2016-10-17 23:16:55 +02:00
Yuya Nishihara
01ff276025 templater: use unfiltered changelog to calculate shortest() at constant time
cl._partialmatch() can be pretty slow if hidden revisions are involved. This
patch cancels the slowdown introduced by the previous patch by using an
unfiltered changelog, which means shortest(node) isn't always the shortest.

The result isn't perfect, but seems okay as long as shortest(node) is short
enough to type and can be used as an identifier.

  (with hidden revisions)
  % hg log -R hg-committed -r0:20000 -T '{node|shortest}\n' --time > /dev/null
  (.^^) time: real 1.530 secs (user 1.480+0.000 sys 0.040+0.000)
  (.^)  time: real 43.080 secs (user 43.060+0.000 sys 0.030+0.000)
  (.)   time: real 1.680 secs (user 1.650+0.000 sys 0.020+0.000)
2016-10-25 21:49:30 +09:00
Yuya Nishihara
35fcce9afc templater: do not use index.partialmatch() directly to calculate shortest()
cl.index.partialmatch() isn't a drop-in replacement for cl._partialmatch().
It has no knowledge about hidden revisions, and it raises ValueError if a node
shorter than 4 chars is given. Instead, use index.partialmatch() through
cl._partialmatch(), which has no such problems and gives the identical result
with/without --pure.

The test output was sampled with --pure without this patch, which shows the
most correct result. However, we'll need to switch to using an unfiltered
changelog because _partialmatch() of a filtered changelog can be an order of
magnitude slower.

  (with hidden revisions)
  % hg log -R hg-committed -r0:20000 -T '{node|shortest}\n' --time > /dev/null
  (.^)  time: real 1.530 secs (user 1.480+0.000 sys 0.040+0.000)
  (.)   time: real 43.080 secs (user 43.060+0.000 sys 0.030+0.000)
2016-10-23 14:05:23 +09:00
Simon Farnsworth
d1e0848d7f templater: handle division by zero in arithmetic
For now, just turn it to an abort.
2016-10-09 08:09:20 -07:00
Simon Farnsworth
d5bf3ea399 templater: provide arithmetic operations on integers
The termwidth template keyword is of limited use without some way to ensure
that margins are respected.

Provide a full set of arithmetic operators (four basic operations plus the
mod function, defined to match Python's // for division), so that you can
create termwidth based layouts that match the user's terminal size
2016-10-09 05:51:04 -07:00
Yuya Nishihara
5196f3da90 templater: add relpath() to convert repo path to relative path (issue5394)
File paths in template are repository-absolute paths. This function can be
used to convert them to filesystem paths relative to cwd. This also converts
'/' to '\\' on Windows.
2016-10-08 15:24:26 +02:00
Anton Shestakov
64aa0688e0 templater: use "needle" and "haystack" as (meta-)variables for ifcontains()
It wasn't immediately clear if it's supposed to look for "search" in "thing" or
"thing" in "search".
2016-10-01 09:55:32 +08:00
Hannes Oldenburg
d853961750 templates: add built-in files() function
We already support multiple primitive for listing files, which were
affected by the current changeset.
This patch adds files() which returns files of the current changeset
matching a given pattern or fileset query via the "set:" prefix.
2016-09-23 08:15:05 +00:00
Matt Mackall
6041ad2e9e templater: add template path to __base__ search
This does a fall-back check for style files or directories that are
in Mercurial's template path for user convenience.

We intentionally don't use this for the built-in coal style because we don't
want the style to mysteriously break if the working directory just
happens to have a file named "paper".
2016-08-24 17:43:45 -07:00
Yuya Nishihara
6b6fa2e134 templater: rename "right" argument of pad() function
Before, right=True meant right justify, which I think is left padding.
2016-04-22 21:32:30 +09:00
Yuya Nishihara
f9c7bd7213 templater: make pad() evaluate boolean argument (BC)
Otherwise it would crash if template expression was passed.

This patch unifies the way how boolean expression is evaluated, which involves
BC. Before "if(true)" and "pad(..., 'false')" were False, which are now True
since they are boolean literal and non-empty string respectively.

"func is runsymbol" is the same hack as evalstringliteral(), which is needed
for label() to take color literals.
2016-04-22 21:29:13 +09:00
Yuya Nishihara
e86fcc2294 templater: fix if() to not evaluate False as bool('False')
Before, False was True. This patch fixes the issue by processing True/False
transparently. The other values (including integer 0) are tested as strings
for backward compatibility, which means "if(latesttagdistance)" never be False.

Should we change the behavior of "if(0)" as well?
2016-08-18 16:29:22 +09:00
Yuya Nishihara
03b3f18ede templater: make it clearer that _flatten() omits None 2016-08-18 15:55:07 +09:00
Matt Mackall
60e14951ba templater: add inheritance support to style maps
We can now specify a base map file:

__base__ = path/to/map/file

That map file will be read and used to populate unset elements of the
current map. Unlike using %include, elements in the inherited class
will be read relative to that path.

This makes it much easier to make custom local tweaks to a style.
2016-08-17 13:40:27 -05:00
Matt Mackall
6fad3ce25a date: refactor timezone parsing
We want to be able to accept ISO 8601 style timezones that don't
include a space separator, so we change the timezone parsing function
to accept a full date string and return both the offset and the
non-timezone portion.
2016-07-27 15:14:19 -05:00
Martin von Zweigbergk
f553986d8e templater: add separate() template function
A pretty common pattern in templates is adding conditional separators
like so:

  {node}{if(bookmarks, " {bookmarks}")}{if(tags, " {tags}")}

With this patch, the above can be simplified to:

  {separate(" ", node, bookmarks, tags)}

The function is similar to the already existing join(), but with a few
differences:

 * separate() skips empty arguments

 * join() expects a single list argument, while separate() expects
   each item as a separate argument

 * separate() takes the separator first in order to allow a variable
   number of arguments after it
2016-05-03 09:49:54 -07:00
Yuya Nishihara
ec53346d72 templater: load and expand aliases by template engine (API) (issue4842)
Now template aliases are fully supported in log and formatter templates.

As I said before, aliases are not expanded in map files. This avoids possible
corruption of our stock styles and web templates. This behavior is undocumented
since no map file nor [templates] section are documented at all. Later on,
we might want to add [aliases] section to map files if it appears to be useful.
2016-03-27 20:59:36 +09:00
Yuya Nishihara
97c46852fc templater: inline compiletemplate() function into engine
This allows the template engine to modify parsed tree.
2016-04-03 13:23:40 +09:00
Yuya Nishihara
3f981af86b templater: separate function to create templater from map file (API)
New frommapfile() function will make it clear when template aliases will be
loaded. They should be applied to command arguments and templates in hgrc,
but not to map files. Otherwise, our stock styles and web templates
(i.e map-file templates) could be modified unintentionally.

Future patches will add "aliases" argument to __init__(), but not to
frommapfile().
2016-04-03 23:26:48 +09:00
Yuya Nishihara
7c3e18d9fe templater: extract function that loads template map file
Prepares for API change. See the next patch for details.

'map' variable is renamed to avoid shadowing map() function.
2016-04-03 23:18:30 +09:00
Yuya Nishihara
dda7a93bdf templater: demote "base" directory of map file to local variable
It isn't referenced from other places.
2016-04-03 23:22:43 +09:00
Yuya Nishihara
d00a0ddedf templater: add parsing and expansion rules to process "templatealias" section
The debugtemplate command is updated to show expanded tree, but still the
template engine doesn't support alias expansion. That's why the test says
"parse error" for now.
2016-03-27 20:31:56 +09:00
Yuya Nishihara
b9d70a8ce1 templater: add function to parse whole string as template expression
This will be a parser of template aliases, and it can also be used for
processing quoted string templates in map files. That's why this function
isn't defined in the upcoming _aliasrules class.
2016-03-27 20:29:03 +09:00
Yuya Nishihara
72e05b7594 templater: drop deprecated handling of KeyError from changeset_templater
It's been superseded by 50f9d20d4c27 and the previous patch. templater.mapfile
is no longer used and removed.
2016-04-03 11:23:31 +09:00
Yuya Nishihara
d6788adafc templater: give better error message for invalid engine type
Before, KeyError was caught at changeset_templater._show(), which said "no
key named '%s'" as it was intended to catch the KeyError of unknown map key.
Instead, we should catch KeyError explicitly for better error indication.

For those who don't know what the template engine is (read "everyone"), it is
hidden extension feature that allows switching template syntax in map file.
See b901d7e82888 for details.
2016-04-03 11:20:50 +09:00
FUJIWARA Katsunori
4f1a0e917c templater: use templatefunc to mark a function as template function
Using decorator can localize changes for adding (or removing) a
template function in source code.

This patch also removes leading ":FUNC(ARG...):" part in help document
of each function, because using templatefunc makes it useless.

This patch uses not 'func' but 'templatefunc' as a decorator name,
because the former is too generic one, even though the latter is a
little redundant in 'templater.py'.
2016-03-30 02:10:44 +09:00
FUJIWARA Katsunori
7a6d96d902 registrar: add templatefunc to mark a function as template function (API)
This patch also adds loadfunction() to templater, because this
combination helps to figure out how they cooperate with each other.

Listing up loadfunction() in dispatch.extraloaders causes implicit
loading template function at loading (3rd party) extension.

This patch explicitly tests whether templatefunc decorator works as
expected, because there is no bundled extension, which defines
template function.

This change requires that "templatefunc" attribute of (3rd party)
extension is registrar.templatefunc or so.
2016-03-30 02:10:44 +09:00
Yuya Nishihara
a32c974037 templater: do not strip non-quote characters from template config
Before this patch, the first and last characters were stripped from
ui.logtemplate and template.* if they were the same. It could lead to a
strange result as quotes are optional. See the test for example.
2016-03-27 17:42:19 +09:00
Yuya Nishihara
634500f64e templater: relax unquotestring() to fall back to bare string
This is convenient for our use case where quotes are optional except in
a map file.
2016-03-26 18:12:12 +09:00
Yuya Nishihara
f0125a308f templater: do not abuse SyntaxError to report errors in template map file
SyntaxError is the class representing syntax errors in Python code. We should
use a dedicated exception class for our needs. With this change, unnecessary
re-wrapping of SyntaxError can be eliminated.
2016-03-26 18:01:04 +09:00
Yuya Nishihara
e489dfcaf7 templater: expand list of parsed templates to template node
This patch eliminates a nested data structure other than the parsed tree.

  ('template', [(op, data), ..]) -> ('template', (op, data), ..)

New expanded tree can be processed by common parser functions. This change
will help implementing template aliases.

Because a (template ..) node should have at least one child node, an empty
template (template []) is mapped to (string ''). Also a trivial string
(template [(string ..)]) node is unwrapped to (string ..) at parsing phase,
instead of compiling phase.
2016-02-13 23:20:47 +09:00
Yuya Nishihara
633de11fa7 templater: relax type of mapped template
Now compiled template fragments are packed into a generic type, (func, data),
a string can be a valid template. This change allows us to unwrap a trivial
string node. See the next patch for details.
2016-02-14 15:42:49 +09:00
Yuya Nishihara
402c2c88bb templater: lift parsed and compiled templates to generic data types
Before this patch, parsed and compiled templates were kept as lists. That
was inconvenient for applying transformation such as alias expansion.

This patch changes the types of the outermost objects as follows:

  stage     old             new
  --------  --------------  ------------------------------
  parsed    [(op, ..)]      ('template', [(op, ..)])
  compiled  [(func, data)]  (runtemplate, [(func, data)])

New templater.parse() function has the same signature as revset.parse()
and fileset.parse().
2016-02-13 23:54:24 +09:00
Yuya Nishihara
823c900008 templater: make label() just fail if ui object isn't available
Silent failure hides bugs and makes it harder to track down the issue. It's
worse than raising exception.

In future patches, I plan to sort out template functions that require 'ui',
'ctx', 'fctx', etc. so that incompatible functions are excluded and the doc can
say in which context these functions are usable.

  @templatefunc('label', requires=('ui',))
  def label(context, mapping, args):
      ...
2016-03-09 23:59:26 +09:00
timeless
4ff3d8a36b templater: ignore orig/rej files
If your mercurial/templates/ directory is dirty, then the template system would
otherwise import duplicate templates from the .orig files and potentially try to
parse .rej files.

Since editing/reverting these templates isn't an unexpected action, and since
they're in .hgignore, it's best that the template system know to skip them."
2016-03-02 05:27:07 +00:00
Kostia Balytskyi
e31d7d20ae formatter: make labels work with templated output
To describe the bug this fix is addressing, one can do
   ``$ hg status -T "{label('red', path)}\n" --color=debug``
and observe that the label is not applied before my fix and applied with it.
2016-03-08 04:08:33 -08:00
Yuya Nishihara
b20edef8a1 templater: move label() function from color extension
ui.label() is no-op by default, so we can just call ui.label() by label()
template function no matter if the color is enabled or not.
2015-06-11 23:04:14 +09:00
Yuya Nishihara
e7ec9f2344 templater: make label() take unknown symbol as color literal
Instead of the mapping hack introduced by d4686e0c15c9, this patch changes the
way how a label symbol is evaluated. This is still hackish, but should be more
predictable in that it doesn't depend on the known color effects.

This change is intended to eliminate the reference to color._effects so that
color.templatelabel() can be merged with templater.label().
2015-06-11 22:58:27 +09:00
Yuya Nishihara
e7f2a2e46a templater: handle exception when applying map operator to non-iterable object
Before this, "{noniterable % template}" raised an exception. This tries to
provide a better indication for the common case, where a left-hand-side
expression is a keyword.
2016-02-14 13:58:46 +09:00
Yuya Nishihara
a0a8a0401c templater: factor out thin helper that evaluates argument as string
This function is trivial, but it can make it clear that args[i] is a
(func, data) pair.
2016-02-14 13:30:32 +09:00
Yuya Nishihara
40ff3175fd templater: fix shortest() to evaluate int argument and handle error 2016-02-14 13:09:17 +09:00
Yuya Nishihara
7bcf850662 templater: fix pad() to evaluate int argument and handle error 2016-02-14 13:05:09 +09:00
Yuya Nishihara
608ccd9ef6 templater: drop redundant type conversion when evaluating integer argument
A function argument may be an integer. In this case, it isn't necessary to
convert a value to string and back to integer.

Because an argument may be an arbitrary object (e.g. date tuple), TypeError
should be caught as well.
2016-02-14 12:48:14 +09:00
Yuya Nishihara
077f7d6378 templater: factor out function that evaluates argument as integer
We have more bare int()s that may raise ValueError or TypeError. This function
will be used to fix them.
2016-02-14 12:42:25 +09:00
Yuya Nishihara
bbfa1c1944 templater: make date() use helper function to evaluate argument
A date argument should never be a generator, but using evalfuncarg() should
be good for consistency.
2016-02-14 13:36:50 +09:00
Yuya Nishihara
946f6161fa templater: fix revset() to evaluate format arguments eagerly
See the previous patch for why. This patch also removes redundant list()
construction from a list.
2016-02-14 00:27:09 +09:00