comparison mercurial/revsetlang.py @ 35596:a57acea31b3b

revsetlang: unnest inner functions from formatspec()
author Yuya Nishihara <yuya@tcha.org>
date Tue, 02 Jan 2018 21:05:40 +0900
parents 91201737d07a
children ed0902e8053e
comparison
equal deleted inserted replaced
35595:91201737d07a 35596:a57acea31b3b
553 >>> _quote(1) 553 >>> _quote(1)
554 "'1'" 554 "'1'"
555 """ 555 """
556 return "'%s'" % util.escapestr(pycompat.bytestr(s)) 556 return "'%s'" % util.escapestr(pycompat.bytestr(s))
557 557
558 def _formatargtype(c, arg):
559 if c == 'd':
560 return '%d' % int(arg)
561 elif c == 's':
562 return _quote(arg)
563 elif c == 'r':
564 parse(arg) # make sure syntax errors are confined
565 return '(%s)' % arg
566 elif c == 'n':
567 return _quote(node.hex(arg))
568 elif c == 'b':
569 try:
570 return _quote(arg.branch())
571 except AttributeError:
572 raise TypeError
573 raise error.ParseError(_('unexpected revspec format character %s') % c)
574
575 def _formatlistexp(s, t):
576 l = len(s)
577 if l == 0:
578 return "_list('')"
579 elif l == 1:
580 return _formatargtype(t, s[0])
581 elif t == 'd':
582 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s)
583 elif t == 's':
584 return "_list(%s)" % _quote("\0".join(s))
585 elif t == 'n':
586 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
587 elif t == 'b':
588 try:
589 return "_list('%s')" % "\0".join(a.branch() for a in s)
590 except AttributeError:
591 raise TypeError
592
593 m = l // 2
594 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
595
558 def formatspec(expr, *args): 596 def formatspec(expr, *args):
559 ''' 597 '''
560 This is a convenience function for using revsets internally, and 598 This is a convenience function for using revsets internally, and
561 escapes arguments appropriately. Aliases are intentionally ignored 599 escapes arguments appropriately. Aliases are intentionally ignored
562 so that intended expression behavior isn't accidentally subverted. 600 so that intended expression behavior isn't accidentally subverted.
587 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) 625 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd'])
588 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))" 626 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))"
589 >>> formatspec('%ls', ['a', "'"]) 627 >>> formatspec('%ls', ['a', "'"])
590 "_list('a\\\\x00\\\\'')" 628 "_list('a\\\\x00\\\\'')"
591 ''' 629 '''
592
593 def argtype(c, arg):
594 if c == 'd':
595 return '%d' % int(arg)
596 elif c == 's':
597 return _quote(arg)
598 elif c == 'r':
599 parse(arg) # make sure syntax errors are confined
600 return '(%s)' % arg
601 elif c == 'n':
602 return _quote(node.hex(arg))
603 elif c == 'b':
604 try:
605 return _quote(arg.branch())
606 except AttributeError:
607 raise TypeError
608 raise error.ParseError(_('unexpected revspec format character %s') % c)
609
610 def listexp(s, t):
611 l = len(s)
612 if l == 0:
613 return "_list('')"
614 elif l == 1:
615 return argtype(t, s[0])
616 elif t == 'd':
617 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s)
618 elif t == 's':
619 return "_list(%s)" % _quote("\0".join(s))
620 elif t == 'n':
621 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
622 elif t == 'b':
623 try:
624 return "_list('%s')" % "\0".join(a.branch() for a in s)
625 except AttributeError:
626 raise TypeError
627
628 m = l // 2
629 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
630
631 expr = pycompat.bytestr(expr) 630 expr = pycompat.bytestr(expr)
632 argiter = iter(args) 631 argiter = iter(args)
633 ret = [] 632 ret = []
634 pos = 0 633 pos = 0
635 while pos < len(expr): 634 while pos < len(expr):
658 try: 657 try:
659 d = expr[pos] 658 d = expr[pos]
660 except IndexError: 659 except IndexError:
661 raise error.ParseError(_('incomplete revspec format character')) 660 raise error.ParseError(_('incomplete revspec format character'))
662 try: 661 try:
663 ret.append(listexp(list(arg), d)) 662 ret.append(_formatlistexp(list(arg), d))
664 except (TypeError, ValueError): 663 except (TypeError, ValueError):
665 raise error.ParseError(_('invalid argument for revspec')) 664 raise error.ParseError(_('invalid argument for revspec'))
666 else: 665 else:
667 try: 666 try:
668 ret.append(argtype(d, arg)) 667 ret.append(_formatargtype(d, arg))
669 except (TypeError, ValueError): 668 except (TypeError, ValueError):
670 raise error.ParseError(_('invalid argument for revspec')) 669 raise error.ParseError(_('invalid argument for revspec'))
671 pos += 1 670 pos += 1
672 671
673 try: 672 try: