mercurial/revsetlang.py
changeset 41219 e5b227f41e4a
parent 41218 24a1f67bb75a
child 41220 8d26026b3335
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):