Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/revsetlang.py @ 41219:e5b227f41e4a
revset: extract parsing logic out of formatspec
We want to be able to perform better handling of some input when running
revset (eg: `repo.revs("%ld", somerevs)`). The first step is to be able to
access some of the parsed content before it gets substituted. There are many
possible different substitutions, we'll add support for them gradually.
In this changeset we support none, we just split some logic in a sub function
as a preparatory step.
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Fri, 04 Jan 2019 02:29:04 +0100 |
parents | 24a1f67bb75a |
children | 8d26026b3335 |
comparison
equal
deleted
inserted
replaced
41218:24a1f67bb75a | 41219:e5b227f41e4a |
---|---|
664 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user']) | 664 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user']) |
665 "sort((:), 'desc', 'user')" | 665 "sort((:), 'desc', 'user')" |
666 >>> formatspec(b'%ls', [b'a', b"'"]) | 666 >>> formatspec(b'%ls', [b'a', b"'"]) |
667 "_list('a\\\\x00\\\\'')" | 667 "_list('a\\\\x00\\\\'')" |
668 ''' | 668 ''' |
669 parsed = _parseargs(expr, args) | |
670 ret = [] | |
671 for t, arg in parsed: | |
672 if t is None: | |
673 ret.append(arg) | |
674 else: | |
675 raise error.ProgrammingError("unknown revspec item type: %r" % t) | |
676 return b''.join(ret) | |
677 | |
678 def _parseargs(expr, args): | |
679 """parse the expression and replace all inexpensive args | |
680 | |
681 return a list of tuple [(arg-type, arg-value)] | |
682 | |
683 Arg-type can be: | |
684 * None: a string ready to be concatenated into a final spec | |
685 """ | |
669 expr = pycompat.bytestr(expr) | 686 expr = pycompat.bytestr(expr) |
670 argiter = iter(args) | 687 argiter = iter(args) |
671 ret = [] | 688 ret = [] |
672 pos = 0 | 689 pos = 0 |
673 while pos < len(expr): | 690 while pos < len(expr): |
674 q = expr.find('%', pos) | 691 q = expr.find('%', pos) |
675 if q < 0: | 692 if q < 0: |
676 ret.append(expr[pos:]) | 693 ret.append((None, expr[pos:])) |
677 break | 694 break |
678 ret.append(expr[pos:q]) | 695 ret.append((None, expr[pos:q])) |
679 pos = q + 1 | 696 pos = q + 1 |
680 try: | 697 try: |
681 d = expr[pos] | 698 d = expr[pos] |
682 except IndexError: | 699 except IndexError: |
683 raise error.ParseError(_('incomplete revspec format character')) | 700 raise error.ParseError(_('incomplete revspec format character')) |
684 if d == '%': | 701 if d == '%': |
685 ret.append(d) | 702 ret.append((None, d)) |
686 pos += 1 | 703 pos += 1 |
687 continue | 704 continue |
688 | 705 |
689 try: | 706 try: |
690 arg = next(argiter) | 707 arg = next(argiter) |
691 except StopIteration: | 708 except StopIteration: |
692 raise error.ParseError(_('missing argument for revspec')) | 709 raise error.ParseError(_('missing argument for revspec')) |
693 f = _formatlistfuncs.get(d) | 710 f = _formatlistfuncs.get(d) |
694 if f: | 711 if f: |
695 # a list of some type | 712 # a list of some type, might be expensive, do not replace |
696 pos += 1 | 713 pos += 1 |
697 try: | 714 try: |
698 d = expr[pos] | 715 d = expr[pos] |
699 except IndexError: | 716 except IndexError: |
700 raise error.ParseError(_('incomplete revspec format character')) | 717 raise error.ParseError(_('incomplete revspec format character')) |
701 try: | 718 try: |
702 ret.append(f(list(arg), d)) | 719 ret.append((None, f(list(arg), d))) |
703 except (TypeError, ValueError): | 720 except (TypeError, ValueError): |
704 raise error.ParseError(_('invalid argument for revspec')) | 721 raise error.ParseError(_('invalid argument for revspec')) |
705 else: | 722 else: |
723 # a single entry, not expensive, replace | |
706 try: | 724 try: |
707 ret.append(_formatargtype(d, arg)) | 725 ret.append((None, _formatargtype(d, arg))) |
708 except (TypeError, ValueError): | 726 except (TypeError, ValueError): |
709 raise error.ParseError(_('invalid argument for revspec')) | 727 raise error.ParseError(_('invalid argument for revspec')) |
710 pos += 1 | 728 pos += 1 |
711 | 729 |
712 try: | 730 try: |
713 next(argiter) | 731 next(argiter) |
714 raise error.ParseError(_('too many revspec arguments specified')) | 732 raise error.ParseError(_('too many revspec arguments specified')) |
715 except StopIteration: | 733 except StopIteration: |
716 pass | 734 pass |
717 return ''.join(ret) | 735 return ret |
718 | 736 |
719 def prettyformat(tree): | 737 def prettyformat(tree): |
720 return parser.prettyformat(tree, ('string', 'symbol')) | 738 return parser.prettyformat(tree, ('string', 'symbol')) |
721 | 739 |
722 def depth(tree): | 740 def depth(tree): |