And port "hg files" to test it.
As you can see, extra indent is necessary to port to this API. I don't think
we should switch every fm.formatter() call to "with" statement.
We sometimes need to build nested items by formatter, but there was no
convenient way other than building and putting them manually by fm.data():
exts = []
for n, v in extensions:
fm.plain('%s %s\n' % (n, v))
exts.append({'name': n, 'ver': v})
fm.data(extensions=exts)
This should work for simple cases, but doing this would make it harder to
change the underlying data type for better templating support.
So this patch provides fm.nested(field), which returns new nested formatter
(or self if items aren't structured and just written to ui.) A nested formatter
stores items which will later be rendered by the parent formatter.
fn = fm.nested('extensions')
for n, v in extensions:
fn.startitem()
fn.write('name ver', '%s %s\n', n, v)
fn.end()
Nested items are directly exported to a template for now:
{extensions % "{name} {ver}\n"}
There's no {extensions} nor {join(extensions, sep)} yet. I have a plan for
them by extending fm.nested() API, but I want to revisit it after trying
out this API in the real world.
New converter classes will be reused by a nested formatter. See the next
patch for details.
This change is also good in that the default values are defined uniquely
by the baseformatter.
This will be used to process key-value pairs by formatter. The default
field names and format are derived from the {extras} template keyword.
Tests will be added later.
Before, it wasn't possible for formatter to handle array structure other
than date tuple. We've discussed that at the last sprint, which ended we
would probably want to allow only templatable data structure, i.e. a list
of dicts:
data(tags=[{'tag': a}, {'tag': b}, ...])
Unfortunately, it turned out not working well with template functions:
"{ifcontains(a, tags, ...)}"
^^^^^^^^^^^^^^^^^^
"a in tags", where tags should be a plain list/set of tags
So the formatter must at least know if the type [{}] was constructed from
a plain list or was actually a list of dicts.
This patch introduces new explicit interface to convert an array structure
to an appropriate data type for the current formatter, which can be used
as follows:
fm.write('tags', _('tags: %s\n'), fm.formatlist(tags, name='tag'))
No separate fm.data() call should be necessary.
The cPickle is renamed to _pickle in python3 and this C extension is available
in pickle which was not included in earlier versions. So imports are conditionalized
to import cPickle in py2 and pickle in py3. Moreover the use of pickle in py2 is
switched to cPickle as the C extension is faster. The hack is added in util.py and
the modules import util.pickle
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.
This function will host loading of template aliases. It is not defined at
templater, but at formatter, since formatter is the module handling ui stuff
in front of templater.
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().
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.
The home of 'Abort' is 'error' not 'util' however, a lot of code seems to be
confused about that and gives all the credit to 'util' instead of the
hardworking 'error'. In a spirit of equity, we break the cycle of injustice and
give back to 'error' the respect it deserves. And screw that 'util' poser.
For great justice.
This lets all the non-log commands that use the formatter use
templates. There are still some things that don't work, for instance:
- color (needs "repo" in map)
- shortest (needs "ctx" in map)
We want to share this function between formatter and cmdutils. It
doesn't belong in templater because it imports knowledge of ui layers
that shouldn't be there. We'd prefer cmdutil to layer on the formatter
rather than vice-versa. Since the formatter is the handler for -T
options for all non-log commands, let's move the helper there. We
leave the bits specific to the old --style option behind.
This seems a bit awkward, but it can avoid duplicates in annotate, tags,
branches and bookmarks.
I guess fm.hexfunc can eventually be removed (or redesigned) when it gets
template backend.
This is necessary for "annotate" to encode ctx.date() in the same manner
as jsonchangeset printer.
It doesn't support list object because keeping mutable object in _item could
be a source of hidden bugs. Also, I can't think of the use case.
This alternate syntax was proposed by Bryan O'Sullivan in a review of
441ebe37ceb5. I haven't been able to measure any particular performance
difference, but the new syntax is more concise and easier to read.