comparison mercurial/templatekw.py @ 37068:aa97e06a1912

templater: use template context to render old-style list template Prepares for dropping the 'templ' resource. This means old-style list templates are processed by the same engine class as the one for the list node. I think that's fine since templates for the same list should be tightly coupled, and I believe the extension point for the engine classes isn't actually used. Now templatekw._showlist() is a compatibility wrapper for _showcompatlist(), and will be deprecated soon. The function is still marked as private since I plan to change the interface to get rid of closures capturing context and mapping.
author Yuya Nishihara <yuya@tcha.org>
date Fri, 16 Mar 2018 22:47:15 +0900
parents c97b936d8bb5
children 724f2e21d870
comparison
equal deleted inserted replaced
37067:04aafcec00b9 37068:aa97e06a1912
27 util, 27 util,
28 ) 28 )
29 29
30 _hybrid = templateutil.hybrid 30 _hybrid = templateutil.hybrid
31 _mappable = templateutil.mappable 31 _mappable = templateutil.mappable
32 _showlist = templateutil._showlist
33 hybriddict = templateutil.hybriddict 32 hybriddict = templateutil.hybriddict
34 hybridlist = templateutil.hybridlist 33 hybridlist = templateutil.hybridlist
35 compatdict = templateutil.compatdict 34 compatdict = templateutil.compatdict
36 compatlist = templateutil.compatlist 35 compatlist = templateutil.compatlist
36 _showcompatlist = templateutil._showcompatlist
37
38 # TODO: temporary hack for porting; will be removed soon
39 class _fakecontextwrapper(object):
40 def __init__(self, templ):
41 self._templ = templ
42
43 def preload(self, t):
44 return t in self._templ
45
46 def process(self, t, mapping):
47 return self._templ.generatenamed(t, mapping)
48
49 def _showlist(name, values, templ, mapping, plural=None, separator=' '):
50 context = _fakecontextwrapper(templ)
51 return _showcompatlist(context, mapping, name, values, plural, separator)
37 52
38 def showdict(name, data, mapping, plural=None, key='key', value='value', 53 def showdict(name, data, mapping, plural=None, key='key', value='value',
39 fmt=None, separator=' '): 54 fmt=None, separator=' '):
40 ui = mapping.get('ui') 55 ui = mapping.get('ui')
41 if ui: 56 if ui:
201 committed. 216 committed.
202 """ 217 """
203 ctx = context.resource(mapping, 'ctx') 218 ctx = context.resource(mapping, 'ctx')
204 return ctx.branch() 219 return ctx.branch()
205 220
206 @templatekeyword('branches', requires={'ctx', 'templ'}) 221 @templatekeyword('branches', requires={'ctx'})
207 def showbranches(context, mapping): 222 def showbranches(context, mapping):
208 """List of strings. The name of the branch on which the 223 """List of strings. The name of the branch on which the
209 changeset was committed. Will be empty if the branch name was 224 changeset was committed. Will be empty if the branch name was
210 default. (DEPRECATED) 225 default. (DEPRECATED)
211 """ 226 """
228 active = repo._activebookmark 243 active = repo._activebookmark
229 makemap = lambda v: {'bookmark': v, 'active': active, 'current': active} 244 makemap = lambda v: {'bookmark': v, 'active': active, 'current': active}
230 f = _showlist('bookmark', bookmarks, templ, mapping) 245 f = _showlist('bookmark', bookmarks, templ, mapping)
231 return _hybrid(f, bookmarks, makemap, pycompat.identity) 246 return _hybrid(f, bookmarks, makemap, pycompat.identity)
232 247
233 @templatekeyword('children', requires={'ctx', 'templ'}) 248 @templatekeyword('children', requires={'ctx'})
234 def showchildren(context, mapping): 249 def showchildren(context, mapping):
235 """List of strings. The children of the changeset.""" 250 """List of strings. The children of the changeset."""
236 ctx = context.resource(mapping, 'ctx') 251 ctx = context.resource(mapping, 'ctx')
237 childrevs = ['%d:%s' % (cctx.rev(), cctx) for cctx in ctx.children()] 252 childrevs = ['%d:%s' % (cctx.rev(), cctx) for cctx in ctx.children()]
238 return compatlist(context, mapping, 'children', childrevs, element='child') 253 return compatlist(context, mapping, 'children', childrevs, element='child')
279 ctx = context.resource(mapping, 'ctx') 294 ctx = context.resource(mapping, 'ctx')
280 stats = patch.diffstatdata(util.iterlines(ctx.diff(noprefix=False))) 295 stats = patch.diffstatdata(util.iterlines(ctx.diff(noprefix=False)))
281 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats) 296 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
282 return '%d: +%d/-%d' % (len(stats), adds, removes) 297 return '%d: +%d/-%d' % (len(stats), adds, removes)
283 298
284 @templatekeyword('envvars', requires={'ui', 'templ'}) 299 @templatekeyword('envvars', requires={'ui'})
285 def showenvvars(context, mapping): 300 def showenvvars(context, mapping):
286 """A dictionary of environment variables. (EXPERIMENTAL)""" 301 """A dictionary of environment variables. (EXPERIMENTAL)"""
287 ui = context.resource(mapping, 'ui') 302 ui = context.resource(mapping, 'ui')
288 env = ui.exportableenviron() 303 env = ui.exportableenviron()
289 env = util.sortdict((k, env[k]) for k in sorted(env)) 304 env = util.sortdict((k, env[k]) for k in sorted(env))
310 if 'files' not in revcache: 325 if 'files' not in revcache:
311 revcache['files'] = repo.status(ctx.p1(), ctx)[:3] 326 revcache['files'] = repo.status(ctx.p1(), ctx)[:3]
312 files = revcache['files'][index] 327 files = revcache['files'][index]
313 return compatlist(context, mapping, name, files, element='file') 328 return compatlist(context, mapping, name, files, element='file')
314 329
315 @templatekeyword('file_adds', requires={'repo', 'ctx', 'revcache', 'templ'}) 330 @templatekeyword('file_adds', requires={'repo', 'ctx', 'revcache'})
316 def showfileadds(context, mapping): 331 def showfileadds(context, mapping):
317 """List of strings. Files added by this changeset.""" 332 """List of strings. Files added by this changeset."""
318 return _showfilesbystat(context, mapping, 'file_add', 1) 333 return _showfilesbystat(context, mapping, 'file_add', 1)
319 334
320 @templatekeyword('file_copies', 335 @templatekeyword('file_copies',
321 requires={'repo', 'ctx', 'cache', 'revcache', 'templ'}) 336 requires={'repo', 'ctx', 'cache', 'revcache'})
322 def showfilecopies(context, mapping): 337 def showfilecopies(context, mapping):
323 """List of strings. Files copied in this changeset with 338 """List of strings. Files copied in this changeset with
324 their sources. 339 their sources.
325 """ 340 """
326 repo = context.resource(mapping, 'repo') 341 repo = context.resource(mapping, 'repo')
343 plural='file_copies') 358 plural='file_copies')
344 359
345 # showfilecopiesswitch() displays file copies only if copy records are 360 # showfilecopiesswitch() displays file copies only if copy records are
346 # provided before calling the templater, usually with a --copies 361 # provided before calling the templater, usually with a --copies
347 # command line switch. 362 # command line switch.
348 @templatekeyword('file_copies_switch', requires={'revcache', 'templ'}) 363 @templatekeyword('file_copies_switch', requires={'revcache'})
349 def showfilecopiesswitch(context, mapping): 364 def showfilecopiesswitch(context, mapping):
350 """List of strings. Like "file_copies" but displayed 365 """List of strings. Like "file_copies" but displayed
351 only if the --copied switch is set. 366 only if the --copied switch is set.
352 """ 367 """
353 copies = context.resource(mapping, 'revcache').get('copies') or [] 368 copies = context.resource(mapping, 'revcache').get('copies') or []
354 copies = util.sortdict(copies) 369 copies = util.sortdict(copies)
355 return compatdict(context, mapping, 'file_copy', copies, 370 return compatdict(context, mapping, 'file_copy', copies,
356 key='name', value='source', fmt='%s (%s)', 371 key='name', value='source', fmt='%s (%s)',
357 plural='file_copies') 372 plural='file_copies')
358 373
359 @templatekeyword('file_dels', requires={'repo', 'ctx', 'revcache', 'templ'}) 374 @templatekeyword('file_dels', requires={'repo', 'ctx', 'revcache'})
360 def showfiledels(context, mapping): 375 def showfiledels(context, mapping):
361 """List of strings. Files removed by this changeset.""" 376 """List of strings. Files removed by this changeset."""
362 return _showfilesbystat(context, mapping, 'file_del', 2) 377 return _showfilesbystat(context, mapping, 'file_del', 2)
363 378
364 @templatekeyword('file_mods', requires={'repo', 'ctx', 'revcache', 'templ'}) 379 @templatekeyword('file_mods', requires={'repo', 'ctx', 'revcache'})
365 def showfilemods(context, mapping): 380 def showfilemods(context, mapping):
366 """List of strings. Files modified by this changeset.""" 381 """List of strings. Files modified by this changeset."""
367 return _showfilesbystat(context, mapping, 'file_mod', 0) 382 return _showfilesbystat(context, mapping, 'file_mod', 0)
368 383
369 @templatekeyword('files', requires={'ctx', 'templ'}) 384 @templatekeyword('files', requires={'ctx'})
370 def showfiles(context, mapping): 385 def showfiles(context, mapping):
371 """List of strings. All files modified, added, or removed by this 386 """List of strings. All files modified, added, or removed by this
372 changeset. 387 changeset.
373 """ 388 """
374 ctx = context.resource(mapping, 'ctx') 389 ctx = context.resource(mapping, 'ctx')
463 return len(repo.revs('only(%ld, %s)', revs, tag)) + offset 478 return len(repo.revs('only(%ld, %s)', revs, tag)) + offset
464 479
465 # teach templater latesttags.changes is switched to (context, mapping) API 480 # teach templater latesttags.changes is switched to (context, mapping) API
466 _showchangessincetag._requires = {'repo', 'ctx'} 481 _showchangessincetag._requires = {'repo', 'ctx'}
467 482
468 @templatekeyword('manifest', requires={'repo', 'ctx', 'templ'}) 483 @templatekeyword('manifest', requires={'repo', 'ctx'})
469 def showmanifest(context, mapping): 484 def showmanifest(context, mapping):
470 repo = context.resource(mapping, 'repo') 485 repo = context.resource(mapping, 'repo')
471 ctx = context.resource(mapping, 'ctx') 486 ctx = context.resource(mapping, 'ctx')
472 templ = context.resource(mapping, 'templ')
473 mnode = ctx.manifestnode() 487 mnode = ctx.manifestnode()
474 if mnode is None: 488 if mnode is None:
475 # just avoid crash, we might want to use the 'ff...' hash in future 489 # just avoid crash, we might want to use the 'ff...' hash in future
476 return 490 return
477 mrev = repo.manifestlog._revlog.rev(mnode) 491 mrev = repo.manifestlog._revlog.rev(mnode)
478 mhex = hex(mnode) 492 mhex = hex(mnode)
479 mapping = mapping.copy() 493 mapping = mapping.copy()
480 mapping.update({'rev': mrev, 'node': mhex}) 494 mapping.update({'rev': mrev, 'node': mhex})
481 f = templ.generate('manifest', mapping) 495 f = context.process('manifest', mapping)
482 # TODO: perhaps 'ctx' should be dropped from mapping because manifest 496 # TODO: perhaps 'ctx' should be dropped from mapping because manifest
483 # rev and node are completely different from changeset's. 497 # rev and node are completely different from changeset's.
484 return _mappable(f, None, f, lambda x: {'rev': mrev, 'node': mhex}) 498 return _mappable(f, None, f, lambda x: {'rev': mrev, 'node': mhex})
485 499
486 @templatekeyword('obsfate', requires={'ui', 'repo', 'ctx', 'templ'}) 500 @templatekeyword('obsfate', requires={'ui', 'repo', 'ctx', 'templ'})
736 f = _showlist(name, ['%d' % r for r in revs], templ, mapping) 750 f = _showlist(name, ['%d' % r for r in revs], templ, mapping)
737 return _hybrid(f, revs, 751 return _hybrid(f, revs,
738 lambda x: {name: x, 'ctx': repo[x], 'revcache': {}}, 752 lambda x: {name: x, 'ctx': repo[x], 'revcache': {}},
739 pycompat.identity, keytype=int) 753 pycompat.identity, keytype=int)
740 754
741 @templatekeyword('subrepos', requires={'ctx', 'templ'}) 755 @templatekeyword('subrepos', requires={'ctx'})
742 def showsubrepos(context, mapping): 756 def showsubrepos(context, mapping):
743 """List of strings. Updated subrepositories in the changeset.""" 757 """List of strings. Updated subrepositories in the changeset."""
744 ctx = context.resource(mapping, 'ctx') 758 ctx = context.resource(mapping, 'ctx')
745 substate = ctx.substate 759 substate = ctx.substate
746 if not substate: 760 if not substate:
756 return compatlist(context, mapping, 'subrepo', sorted(subrepos)) 770 return compatlist(context, mapping, 'subrepo', sorted(subrepos))
757 771
758 # don't remove "showtags" definition, even though namespaces will put 772 # don't remove "showtags" definition, even though namespaces will put
759 # a helper function for "tags" keyword into "keywords" map automatically, 773 # a helper function for "tags" keyword into "keywords" map automatically,
760 # because online help text is built without namespaces initialization 774 # because online help text is built without namespaces initialization
761 @templatekeyword('tags', requires={'repo', 'ctx', 'templ'}) 775 @templatekeyword('tags', requires={'repo', 'ctx'})
762 def showtags(context, mapping): 776 def showtags(context, mapping):
763 """List of strings. Any tags associated with the changeset.""" 777 """List of strings. Any tags associated with the changeset."""
764 return shownames(context, mapping, 'tags') 778 return shownames(context, mapping, 'tags')
765 779
766 @templatekeyword('termwidth', requires={'ui'}) 780 @templatekeyword('termwidth', requires={'ui'})
767 def showtermwidth(context, mapping): 781 def showtermwidth(context, mapping):
768 """Integer. The width of the current terminal.""" 782 """Integer. The width of the current terminal."""
769 ui = context.resource(mapping, 'ui') 783 ui = context.resource(mapping, 'ui')
770 return ui.termwidth() 784 return ui.termwidth()
771 785
772 @templatekeyword('instabilities', requires={'ctx', 'templ'}) 786 @templatekeyword('instabilities', requires={'ctx'})
773 def showinstabilities(context, mapping): 787 def showinstabilities(context, mapping):
774 """List of strings. Evolution instabilities affecting the changeset. 788 """List of strings. Evolution instabilities affecting the changeset.
775 (EXPERIMENTAL) 789 (EXPERIMENTAL)
776 """ 790 """
777 ctx = context.resource(mapping, 'ctx') 791 ctx = context.resource(mapping, 'ctx')