Show More
@@ -20,6 +20,7 b' from . import (' | |||||
20 | error, |
|
20 | error, | |
21 | minirst, |
|
21 | minirst, | |
22 | obsutil, |
|
22 | obsutil, | |
|
23 | pycompat, | |||
23 | registrar, |
|
24 | registrar, | |
24 | revset as revsetmod, |
|
25 | revset as revsetmod, | |
25 | revsetlang, |
|
26 | revsetlang, | |
@@ -581,6 +582,40 b' def rstdoc(context, mapping, args):' | |||||
581 |
|
582 | |||
582 | return minirst.format(text, style=style, keep=['verbose']) |
|
583 | return minirst.format(text, style=style, keep=['verbose']) | |
583 |
|
584 | |||
|
585 | @templatefunc('search(pattern, text)') | |||
|
586 | def search(context, mapping, args): | |||
|
587 | """Look for the first text matching the regular expression pattern. | |||
|
588 | Groups are accessible as ``{1}``, ``{2}``, ... in %-mapped template.""" | |||
|
589 | if len(args) != 2: | |||
|
590 | # i18n: "search" is a keyword | |||
|
591 | raise error.ParseError(_(b'search expects two arguments')) | |||
|
592 | ||||
|
593 | pat = evalstring(context, mapping, args[0]) | |||
|
594 | src = evalstring(context, mapping, args[1]) | |||
|
595 | try: | |||
|
596 | patre = re.compile(pat) | |||
|
597 | except re.error: | |||
|
598 | # i18n: "search" is a keyword | |||
|
599 | raise error.ParseError(_(b'search got an invalid pattern: %s') % pat) | |||
|
600 | # named groups shouldn't shadow *reserved* resource keywords | |||
|
601 | badgroups = (context.knownresourcekeys() | |||
|
602 | & set(pycompat.byteskwargs(patre.groupindex))) | |||
|
603 | if badgroups: | |||
|
604 | raise error.ParseError( | |||
|
605 | # i18n: "search" is a keyword | |||
|
606 | _(b'invalid group %(group)s in search pattern: %(pat)s') | |||
|
607 | % {b'group': b', '.join("'%s'" % g for g in sorted(badgroups)), | |||
|
608 | b'pat': pat}) | |||
|
609 | ||||
|
610 | match = patre.search(src) | |||
|
611 | if not match: | |||
|
612 | return | |||
|
613 | ||||
|
614 | lm = {b'0': match.group(0)} | |||
|
615 | lm.update((b'%d' % i, v) for i, v in enumerate(match.groups(), 1)) | |||
|
616 | lm.update(pycompat.byteskwargs(match.groupdict())) | |||
|
617 | return templateutil.mappingdict(lm, tmpl=b'{0}') | |||
|
618 | ||||
584 | @templatefunc('separate(sep, args...)', argspec='sep *args') |
|
619 | @templatefunc('separate(sep, args...)', argspec='sep *args') | |
585 | def separate(context, mapping, args): |
|
620 | def separate(context, mapping, args): | |
586 | """Add a separator between non-empty arguments.""" |
|
621 | """Add a separator between non-empty arguments.""" |
@@ -603,6 +603,53 b' Test laziness of if() then/else clause' | |||||
603 | $ hg debugtemplate '{ifeq(0, 0, "", count(0))}' |
|
603 | $ hg debugtemplate '{ifeq(0, 0, "", count(0))}' | |
604 | $ hg debugtemplate '{ifeq(0, 1, count(0), "")}' |
|
604 | $ hg debugtemplate '{ifeq(0, 1, count(0), "")}' | |
605 |
|
605 | |||
|
606 | Test search() function: | |||
|
607 | ||||
|
608 | $ hg log -R a -r2 -T '{desc}\n' | |||
|
609 | no person | |||
|
610 | ||||
|
611 | $ hg log -R a -r2 -T '{search(r"p.*", desc)}\n' | |||
|
612 | person | |||
|
613 | ||||
|
614 | as bool | |||
|
615 | ||||
|
616 | $ hg log -R a -r2 -T '{if(search(r"p.*", desc), "", "not ")}found\n' | |||
|
617 | found | |||
|
618 | $ hg log -R a -r2 -T '{if(search(r"q", desc), "", "not ")}found\n' | |||
|
619 | not found | |||
|
620 | ||||
|
621 | match as json | |||
|
622 | ||||
|
623 | $ hg log -R a -r2 -T '{search(r"(no) p.*", desc)|json}\n' | |||
|
624 | {"0": "no person", "1": "no"} | |||
|
625 | $ hg log -R a -r2 -T '{search(r"q", desc)|json}\n' | |||
|
626 | null | |||
|
627 | ||||
|
628 | group reference | |||
|
629 | ||||
|
630 | $ hg log -R a -r2 -T '{search(r"(no) (p.*)", desc) % "{1|upper} {2|hex}"}\n' | |||
|
631 | NO 706572736f6e | |||
|
632 | $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc) % "{foo}"}\n' | |||
|
633 | no | |||
|
634 | $ hg log -R a -r2 -T '{search(r"(?P<foo>[a-z]*)", desc).foo}\n' | |||
|
635 | no | |||
|
636 | ||||
|
637 | group reference with no match | |||
|
638 | (TODO: we'll probably want to map it to an empty value) | |||
|
639 | ||||
|
640 | $ hg log -R a -r2 -T '{search(r"q", desc) % "match: {0}"}\n' | |||
|
641 | hg: parse error: None is not iterable of mappings | |||
|
642 | [255] | |||
|
643 | ||||
|
644 | bad group names | |||
|
645 | ||||
|
646 | $ hg log -R a -r2 -T '{search(r"(?P<0>.)", desc) % "{0}"}\n' | |||
|
647 | hg: parse error: search got an invalid pattern: (?P<0>.) | |||
|
648 | [255] | |||
|
649 | $ hg log -R a -r2 -T '{search(r"(?P<repo>.)", desc) % "{repo}"}\n' | |||
|
650 | hg: parse error: invalid group 'repo' in search pattern: (?P<repo>.) | |||
|
651 | [255] | |||
|
652 | ||||
606 | Test the sub function of templating for expansion: |
|
653 | Test the sub function of templating for expansion: | |
607 |
|
654 | |||
608 |
$ |
|
655 | $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n' |
General Comments 0
You need to be logged in to leave comments.
Login now