comparison mercurial/revsetlang.py @ 35597:ed0902e8053e

revsetlang: add %p specifier to format list of function arguments This will be used to construct parameters passed to _matchfiles().
author Yuya Nishihara <yuya@tcha.org>
date Tue, 02 Jan 2018 18:35:11 +0900
parents a57acea31b3b
children 4269971b0d26
comparison
equal deleted inserted replaced
35596:a57acea31b3b 35597:ed0902e8053e
591 raise TypeError 591 raise TypeError
592 592
593 m = l // 2 593 m = l // 2
594 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t)) 594 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
595 595
596 def _formatparamexp(args, t):
597 return ', '.join(_formatargtype(t, a) for a in args)
598
599 _formatlistfuncs = {
600 'l': _formatlistexp,
601 'p': _formatparamexp,
602 }
603
596 def formatspec(expr, *args): 604 def formatspec(expr, *args):
597 ''' 605 '''
598 This is a convenience function for using revsets internally, and 606 This is a convenience function for using revsets internally, and
599 escapes arguments appropriately. Aliases are intentionally ignored 607 escapes arguments appropriately. Aliases are intentionally ignored
600 so that intended expression behavior isn't accidentally subverted. 608 so that intended expression behavior isn't accidentally subverted.
606 %s = string(arg), escaped and single-quoted 614 %s = string(arg), escaped and single-quoted
607 %b = arg.branch(), escaped and single-quoted 615 %b = arg.branch(), escaped and single-quoted
608 %n = hex(arg), single-quoted 616 %n = hex(arg), single-quoted
609 %% = a literal '%' 617 %% = a literal '%'
610 618
611 Prefixing the type with 'l' specifies a parenthesized list of that type. 619 Prefixing the type with 'l' specifies a parenthesized list of that type,
620 and 'p' specifies a list of function parameters of that type.
612 621
613 >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()")) 622 >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()"))
614 '(10 or 11):: and ((this()) or (that()))' 623 '(10 or 11):: and ((this()) or (that()))'
615 >>> formatspec(b'%d:: and not %d::', 10, 20) 624 >>> formatspec(b'%d:: and not %d::', 10, 20)
616 '10:: and not 20::' 625 '10:: and not 20::'
622 >>> b.branch = b 631 >>> b.branch = b
623 >>> formatspec(b'branch(%b)', b) 632 >>> formatspec(b'branch(%b)', b)
624 "branch('default')" 633 "branch('default')"
625 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) 634 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd'])
626 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))" 635 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))"
636 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user'])
637 "sort((:), 'desc', 'user')"
627 >>> formatspec('%ls', ['a', "'"]) 638 >>> formatspec('%ls', ['a', "'"])
628 "_list('a\\\\x00\\\\'')" 639 "_list('a\\\\x00\\\\'')"
629 ''' 640 '''
630 expr = pycompat.bytestr(expr) 641 expr = pycompat.bytestr(expr)
631 argiter = iter(args) 642 argiter = iter(args)
649 660
650 try: 661 try:
651 arg = next(argiter) 662 arg = next(argiter)
652 except StopIteration: 663 except StopIteration:
653 raise error.ParseError(_('missing argument for revspec')) 664 raise error.ParseError(_('missing argument for revspec'))
654 if d == 'l': 665 f = _formatlistfuncs.get(d)
666 if f:
655 # a list of some type 667 # a list of some type
656 pos += 1 668 pos += 1
657 try: 669 try:
658 d = expr[pos] 670 d = expr[pos]
659 except IndexError: 671 except IndexError:
660 raise error.ParseError(_('incomplete revspec format character')) 672 raise error.ParseError(_('incomplete revspec format character'))
661 try: 673 try:
662 ret.append(_formatlistexp(list(arg), d)) 674 ret.append(f(list(arg), d))
663 except (TypeError, ValueError): 675 except (TypeError, ValueError):
664 raise error.ParseError(_('invalid argument for revspec')) 676 raise error.ParseError(_('invalid argument for revspec'))
665 else: 677 else:
666 try: 678 try:
667 ret.append(_formatargtype(d, arg)) 679 ret.append(_formatargtype(d, arg))