mercurial/revset.py
changeset 28871 6d6201fc5aae
parent 28870 475dad3432fd
child 28872 5f31d2248745
equal deleted inserted replaced
28870:475dad3432fd 28871:6d6201fc5aae
  2235                     syminitletters=_aliassyminitletters)
  2235                     syminitletters=_aliassyminitletters)
  2236 
  2236 
  2237 def _parsealiasdecl(decl):
  2237 def _parsealiasdecl(decl):
  2238     """Parse alias declaration ``decl``
  2238     """Parse alias declaration ``decl``
  2239 
  2239 
  2240     This returns ``(name, tree, args, errorstr)`` tuple:
  2240     >>> _parsealiasdecl('foo($1)')
  2241 
  2241     ('func', ('symbol', 'foo'), ('symbol', '$1'))
  2242     - ``name``: of declared alias (may be ``decl`` itself at error)
       
  2243     - ``tree``: parse result (or ``None`` at error)
       
  2244     - ``args``: list of alias argument names (or None for symbol declaration)
       
  2245     - ``errorstr``: detail about detected error (or None)
       
  2246 
       
  2247     >>> _parsealiasdecl('foo')
       
  2248     ('foo', ('symbol', 'foo'), None, None)
       
  2249     >>> _parsealiasdecl('$foo')
       
  2250     ('$foo', None, None, "'$' not for alias arguments")
       
  2251     >>> _parsealiasdecl('foo::bar')
       
  2252     ('foo::bar', None, None, 'invalid format')
       
  2253     >>> _parsealiasdecl('foo bar')
  2242     >>> _parsealiasdecl('foo bar')
  2254     ('foo bar', None, None, 'at 4: invalid token')
  2243     Traceback (most recent call last):
  2255     >>> _parsealiasdecl('foo()')
  2244       ...
  2256     ('foo', ('func', ('symbol', 'foo')), [], None)
  2245     ParseError: ('invalid token', 4)
  2257     >>> _parsealiasdecl('$foo()')
       
  2258     ('$foo()', None, None, "'$' not for alias arguments")
       
  2259     >>> _parsealiasdecl('foo($1, $2)')
       
  2260     ('foo', ('func', ('symbol', 'foo')), ['$1', '$2'], None)
       
  2261     >>> _parsealiasdecl('foo(bar_bar, baz.baz)')
       
  2262     ('foo', ('func', ('symbol', 'foo')), ['bar_bar', 'baz.baz'], None)
       
  2263     >>> _parsealiasdecl('foo($1, $2, nested($1, $2))')
       
  2264     ('foo($1, $2, nested($1, $2))', None, None, 'invalid argument list')
       
  2265     >>> _parsealiasdecl('foo(bar($1, $2))')
       
  2266     ('foo(bar($1, $2))', None, None, 'invalid argument list')
       
  2267     >>> _parsealiasdecl('foo("string")')
       
  2268     ('foo("string")', None, None, 'invalid argument list')
       
  2269     >>> _parsealiasdecl('foo($1, $2')
       
  2270     ('foo($1, $2', None, None, 'at 10: unexpected token: end')
       
  2271     >>> _parsealiasdecl('foo("string')
       
  2272     ('foo("string', None, None, 'at 5: unterminated string')
       
  2273     >>> _parsealiasdecl('foo($1, $2, $1)')
       
  2274     ('foo', None, None, 'argument names collide with each other')
       
  2275     """
  2246     """
  2276     p = parser.parser(elements)
  2247     p = parser.parser(elements)
  2277     try:
  2248     tree, pos = p.parse(_tokenizealias(decl))
  2278         tree, pos = p.parse(_tokenizealias(decl))
  2249     if pos != len(decl):
  2279         if (pos != len(decl)):
  2250         raise error.ParseError(_('invalid token'), pos)
  2280             raise error.ParseError(_('invalid token'), pos)
  2251     return parser.simplifyinfixops(tree, ('list',))
  2281         tree = parser.simplifyinfixops(tree, ('list',))
       
  2282     except error.ParseError as inst:
       
  2283         return (decl, None, None, parser.parseerrordetail(inst))
       
  2284 
       
  2285     if True:  # XXX to be removed
       
  2286         if tree[0] == 'symbol':
       
  2287             # "name = ...." style
       
  2288             name = tree[1]
       
  2289             if name.startswith('$'):
       
  2290                 return (decl, None, None, _("'$' not for alias arguments"))
       
  2291             return (name, tree, None, None)
       
  2292 
       
  2293         if tree[0] == 'func' and tree[1][0] == 'symbol':
       
  2294             # "name(arg, ....) = ...." style
       
  2295             name = tree[1][1]
       
  2296             if name.startswith('$'):
       
  2297                 return (decl, None, None, _("'$' not for alias arguments"))
       
  2298             args = []
       
  2299             for arg in getlist(tree[2]):
       
  2300                 if arg[0] != 'symbol':
       
  2301                     return (decl, None, None, _("invalid argument list"))
       
  2302                 args.append(arg[1])
       
  2303             if len(args) != len(set(args)):
       
  2304                 return (name, None, None,
       
  2305                         _("argument names collide with each other"))
       
  2306             return (name, tree[:2], args, None)
       
  2307 
       
  2308         return (decl, None, None, _("invalid format"))
       
  2309 
  2252 
  2310 def _relabelaliasargs(tree, args):
  2253 def _relabelaliasargs(tree, args):
  2311     if not isinstance(tree, tuple):
  2254     if not isinstance(tree, tuple):
  2312         return tree
  2255         return tree
  2313     op = tree[0]
  2256     op = tree[0]
  2367     return _relabelaliasargs(tree, args)
  2310     return _relabelaliasargs(tree, args)
  2368 
  2311 
  2369 class _aliasrules(parser.basealiasrules):
  2312 class _aliasrules(parser.basealiasrules):
  2370     """Parsing and expansion rule set of revset aliases"""
  2313     """Parsing and expansion rule set of revset aliases"""
  2371     _section = _('revset alias')
  2314     _section = _('revset alias')
       
  2315     _parsedecl = staticmethod(_parsealiasdecl)
  2372     _getlist = staticmethod(getlist)
  2316     _getlist = staticmethod(getlist)
  2373 
  2317 
  2374 class revsetalias(object):
  2318 class revsetalias(object):
  2375     # whether own `error` information is already shown or not.
  2319     # whether own `error` information is already shown or not.
  2376     # this avoids showing same warning multiple times at each `findaliases`.
  2320     # this avoids showing same warning multiple times at each `findaliases`.
  2380         '''Aliases like:
  2324         '''Aliases like:
  2381 
  2325 
  2382         h = heads(default)
  2326         h = heads(default)
  2383         b($1) = ancestors($1) - ancestors(default)
  2327         b($1) = ancestors($1) - ancestors(default)
  2384         '''
  2328         '''
  2385         self.name, self.tree, self.args, self.error = _parsealiasdecl(name)
  2329         r = _aliasrules._builddecl(name)
       
  2330         self.name, self.tree, self.args, self.error = r
  2386         if self.error:
  2331         if self.error:
  2387             self.error = _('failed to parse the declaration of revset alias'
  2332             self.error = _('failed to parse the declaration of revset alias'
  2388                            ' "%s": %s') % (self.name, self.error)
  2333                            ' "%s": %s') % (self.name, self.error)
  2389             return
  2334             return
  2390 
  2335