##// END OF EJS Templates
revset aliases
Alexander Solovyov -
r14098:9f5a0acb default
parent child Browse files
Show More
@@ -174,7 +174,7 b' def revrange(repo, revs):'
174 174 pass
175 175
176 176 # fall through to new-style queries if old-style fails
177 m = revset.match(spec)
177 m = revset.match(repo.ui, spec)
178 178 for r in m(repo, range(len(repo))):
179 179 if r not in seen:
180 180 l.append(r)
@@ -1296,7 +1296,10 b' def debugrevspec(ui, repo, expr):'
1296 1296 if ui.verbose:
1297 1297 tree = revset.parse(expr)[0]
1298 1298 ui.note(tree, "\n")
1299 func = revset.match(expr)
1299 newtree = revset.findaliases(ui, tree)
1300 if newtree != tree:
1301 ui.note(newtree, "\n")
1302 func = revset.match(ui, expr)
1300 1303 for c in func(repo, range(len(repo))):
1301 1304 ui.write("%s\n" % c)
1302 1305
@@ -61,6 +61,26 b' The following predicates are supported:'
61 61
62 62 .. predicatesmarker
63 63
64 New predicates (known as "aliases") can be defined, using any combination of
65 existing predicates or other aliases. An alias definition looks like::
66
67 <alias> = <definition>
68
69 in the ``revsetalias`` section of ``.hgrc``. Arguments of the form `$1`, `$2`,
70 etc. are substituted from the alias into the definition.
71
72 For example,
73
74 ::
75
76 [revsetalias]
77 h = heads()
78 d($1) = sort($1, date)
79 rs($1, $2) = reverse(sort($1, $2))
80
81 defines three aliases, ``h``, ``d``, and ``rs``. ``rs(0:tip, author)`` is
82 exactly equivalent to ``reverse(sort(0:tip, author))``.
83
64 84 Command line equivalents for :hg:`log`::
65 85
66 86 -f -> ::.
@@ -889,14 +889,89 b' def optimize(x, small):'
889 889 return w + wa, (op, x[1], ta)
890 890 return 1, x
891 891
892 class revsetalias(object):
893 funcre = re.compile('^([^(]+)\(([^)]+)\)$')
894 args = ()
895
896 def __init__(self, token, value):
897 '''Aliases like:
898
899 h = heads(default)
900 b($1) = ancestors($1) - ancestors(default)
901 '''
902 if isinstance(token, tuple):
903 self.type, self.name = token
904 else:
905 m = self.funcre.search(token)
906 if m:
907 self.type = 'func'
908 self.name = m.group(1)
909 self.args = [x.strip() for x in m.group(2).split(',')]
910 else:
911 self.type = 'symbol'
912 self.name = token
913
914 if isinstance(value, str):
915 for arg in self.args:
916 value = value.replace(arg, repr(arg))
917 self.replacement, pos = parse(value)
918 if pos != len(value):
919 raise error.ParseError('invalid token', pos)
920 else:
921 self.replacement = value
922
923 def match(self, tree):
924 if not tree:
925 return False
926 if tree == (self.type, self.name):
927 return True
928 if tree[0] != self.type:
929 return False
930 if len(tree) > 1 and tree[1] != ('symbol', self.name):
931 return False
932 # 'func' + funcname + args
933 if ((self.args and len(tree) != 3) or
934 (len(self.args) == 1 and tree[2][0] == 'list') or
935 (len(self.args) > 1 and (tree[2][0] != 'list' or
936 len(tree[2]) - 1 != len(self.args)))):
937 raise error.ParseError('invalid amount of arguments', len(tree) - 2)
938 return True
939
940 def replace(self, tree):
941 if tree == (self.type, self.name):
942 return self.replacement
943 result = self.replacement
944 def getsubtree(i):
945 if tree[2][0] == 'list':
946 return tree[2][i + 1]
947 return tree[i + 2]
948 for i, v in enumerate(self.args):
949 valalias = revsetalias(('string', v), getsubtree(i))
950 result = valalias.process(result)
951 return result
952
953 def process(self, tree):
954 if self.match(tree):
955 return self.replace(tree)
956 if isinstance(tree, tuple):
957 return tuple(map(self.process, tree))
958 return tree
959
960 def findaliases(ui, tree):
961 for k, v in ui.configitems('revsetalias'):
962 alias = revsetalias(k, v)
963 tree = alias.process(tree)
964 return tree
965
892 966 parse = parser.parser(tokenize, elements).parse
893 967
894 def match(spec):
968 def match(ui, spec):
895 969 if not spec:
896 970 raise error.ParseError(_("empty query"))
897 971 tree, pos = parse(spec)
898 972 if (pos != len(spec)):
899 973 raise error.ParseError("invalid token", pos)
974 tree = findaliases(ui, tree)
900 975 weight, tree = optimize(tree, True)
901 976 def mfunc(repo, subset):
902 977 return getset(repo, subset, tree)
@@ -2,7 +2,7 b''
2 2 $ export HGENCODING
3 3
4 4 $ try() {
5 > hg debugrevspec --debug $@
5 > hg debugrevspec --debug "$@"
6 6 > }
7 7
8 8 $ log() {
@@ -411,3 +411,27 b' parentrevspec'
411 411 $ log 'tip^foo'
412 412 hg: parse error: ^ expects a number 0, 1, or 2
413 413 [255]
414
415 aliases:
416
417 $ echo '[revsetalias]' >> .hg/hgrc
418 $ echo 'm = merge()' >> .hg/hgrc
419 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
420 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
421
422 $ try m
423 ('symbol', 'm')
424 ('func', ('symbol', 'merge'), None)
425 6
426 $ try 'd(2:5)'
427 ('func', ('symbol', 'd'), ('range', ('symbol', '2'), ('symbol', '5')))
428 ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('range', ('symbol', '2'), ('symbol', '5')), ('symbol', 'date'))))
429 4
430 5
431 3
432 2
433 $ try 'rs(2 or 3, date)'
434 ('func', ('symbol', 'rs'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date')))
435 ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date'))))
436 3
437 2
General Comments 0
You need to be logged in to leave comments. Login now