Show More
@@ -2840,6 +2840,10 b' def debugrevspec(ui, repo, expr, **opts)' | |||||
2840 | newtree = revset.findaliases(ui, tree) |
|
2840 | newtree = revset.findaliases(ui, tree) | |
2841 | if newtree != tree: |
|
2841 | if newtree != tree: | |
2842 | ui.note(revset.prettyformat(newtree), "\n") |
|
2842 | ui.note(revset.prettyformat(newtree), "\n") | |
|
2843 | tree = newtree | |||
|
2844 | newtree = revset.foldconcat(tree) | |||
|
2845 | if newtree != tree: | |||
|
2846 | ui.note(revset.prettyformat(newtree), "\n") | |||
2843 | if opts["optimize"]: |
|
2847 | if opts["optimize"]: | |
2844 | weight, optimizedtree = revset.optimize(newtree, True) |
|
2848 | weight, optimizedtree = revset.optimize(newtree, True) | |
2845 | ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n") |
|
2849 | ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n") |
@@ -81,6 +81,19 b' For example,' | |||||
81 | defines three aliases, ``h``, ``d``, and ``rs``. ``rs(0:tip, author)`` is |
|
81 | defines three aliases, ``h``, ``d``, and ``rs``. ``rs(0:tip, author)`` is | |
82 | exactly equivalent to ``reverse(sort(0:tip, author))``. |
|
82 | exactly equivalent to ``reverse(sort(0:tip, author))``. | |
83 |
|
83 | |||
|
84 | An infix operator ``##`` can concatenate strings and identifiers into | |||
|
85 | one string. For example:: | |||
|
86 | ||||
|
87 | [revsetalias] | |||
|
88 | issue($1) = grep(r'\bissue[ :]?' ## $1 ## r'\b|\bbug\(' ## $1 ## r'\)') | |||
|
89 | ||||
|
90 | ``issue(1234)`` is equivalent to ``grep(r'\bissue[ :]?1234\b|\bbug\(1234\)')`` | |||
|
91 | in this case. This matches against all of "issue 1234", "issue:1234", | |||
|
92 | "issue1234" and "bug(1234)". | |||
|
93 | ||||
|
94 | All other prefix, infix and postfix operators have lower priority than | |||
|
95 | ``##``. For example, ``$1 ## $2~2`` is equivalent to ``($1 ## $2)~2``. | |||
|
96 | ||||
84 | Command line equivalents for :hg:`log`:: |
|
97 | Command line equivalents for :hg:`log`:: | |
85 |
|
98 | |||
86 | -f -> ::. |
|
99 | -f -> ::. |
@@ -102,7 +102,8 b' def _revsbetween(repo, roots, heads):' | |||||
102 | return baseset(sorted(reachable)) |
|
102 | return baseset(sorted(reachable)) | |
103 |
|
103 | |||
104 | elements = { |
|
104 | elements = { | |
105 |
"(": (2 |
|
105 | "(": (21, ("group", 1, ")"), ("func", 1, ")")), | |
|
106 | "##": (20, None, ("_concat", 20)), | |||
106 | "~": (18, None, ("ancestor", 18)), |
|
107 | "~": (18, None, ("ancestor", 18)), | |
107 | "^": (18, None, ("parent", 18), ("parentpost", 18)), |
|
108 | "^": (18, None, ("parent", 18), ("parentpost", 18)), | |
108 | "-": (5, ("negate", 19), ("minus", 5)), |
|
109 | "-": (5, ("negate", 19), ("minus", 5)), | |
@@ -148,6 +149,9 b' def tokenize(program, lookup=None):' | |||||
148 | elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully |
|
149 | elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully | |
149 | yield ('..', None, pos) |
|
150 | yield ('..', None, pos) | |
150 | pos += 1 # skip ahead |
|
151 | pos += 1 # skip ahead | |
|
152 | elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully | |||
|
153 | yield ('##', None, pos) | |||
|
154 | pos += 1 # skip ahead | |||
151 | elif c in "():,-|&+!~^": # handle simple operators |
|
155 | elif c in "():,-|&+!~^": # handle simple operators | |
152 | yield (c, None, pos) |
|
156 | yield (c, None, pos) | |
153 | elif (c in '"\'' or c == 'r' and |
|
157 | elif (c in '"\'' or c == 'r' and | |
@@ -2156,6 +2160,27 b' def findaliases(ui, tree, showwarning=No' | |||||
2156 | alias.warned = True |
|
2160 | alias.warned = True | |
2157 | return tree |
|
2161 | return tree | |
2158 |
|
2162 | |||
|
2163 | def foldconcat(tree): | |||
|
2164 | """Fold elements to be concatenated by `##` | |||
|
2165 | """ | |||
|
2166 | if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'): | |||
|
2167 | return tree | |||
|
2168 | if tree[0] == '_concat': | |||
|
2169 | pending = [tree] | |||
|
2170 | l = [] | |||
|
2171 | while pending: | |||
|
2172 | e = pending.pop() | |||
|
2173 | if e[0] == '_concat': | |||
|
2174 | pending.extend(reversed(e[1:])) | |||
|
2175 | elif e[0] in ('string', 'symbol'): | |||
|
2176 | l.append(e[1]) | |||
|
2177 | else: | |||
|
2178 | msg = _("\"##\" can't concatenate \"%s\" element") % (e[0]) | |||
|
2179 | raise error.ParseError(msg) | |||
|
2180 | return ('string', ''.join(l)) | |||
|
2181 | else: | |||
|
2182 | return tuple(foldconcat(t) for t in tree) | |||
|
2183 | ||||
2159 | def parse(spec, lookup=None): |
|
2184 | def parse(spec, lookup=None): | |
2160 | p = parser.parser(tokenize, elements) |
|
2185 | p = parser.parser(tokenize, elements) | |
2161 | return p.parse(spec, lookup=lookup) |
|
2186 | return p.parse(spec, lookup=lookup) | |
@@ -2171,6 +2196,7 b' def match(ui, spec, repo=None):' | |||||
2171 | raise error.ParseError(_("invalid token"), pos) |
|
2196 | raise error.ParseError(_("invalid token"), pos) | |
2172 | if ui: |
|
2197 | if ui: | |
2173 | tree = findaliases(ui, tree, showwarning=ui.warn) |
|
2198 | tree = findaliases(ui, tree, showwarning=ui.warn) | |
|
2199 | tree = foldconcat(tree) | |||
2174 | weight, tree = optimize(tree, True) |
|
2200 | weight, tree = optimize(tree, True) | |
2175 | def mfunc(repo, subset): |
|
2201 | def mfunc(repo, subset): | |
2176 | if util.safehasattr(subset, 'isascending'): |
|
2202 | if util.safehasattr(subset, 'isascending'): |
@@ -1123,6 +1123,54 b' 3. more than local specified sp' | |||||
1123 | $ cd ../repo |
|
1123 | $ cd ../repo | |
1124 | $ log 'remote(".a.b.c.", "../remote3")' |
|
1124 | $ log 'remote(".a.b.c.", "../remote3")' | |
1125 |
|
1125 | |||
|
1126 | tests for concatenation of strings/symbols by "##" | |||
|
1127 | ||||
|
1128 | $ try "278 ## '5f5' ## 1ee ## 'ce5'" | |||
|
1129 | (_concat | |||
|
1130 | (_concat | |||
|
1131 | (_concat | |||
|
1132 | ('symbol', '278') | |||
|
1133 | ('string', '5f5')) | |||
|
1134 | ('symbol', '1ee')) | |||
|
1135 | ('string', 'ce5')) | |||
|
1136 | ('string', '2785f51eece5') | |||
|
1137 | 0 | |||
|
1138 | ||||
|
1139 | $ echo 'cat4($1, $2, $3, $4) = $1 ## $2 ## $3 ## $4' >> .hg/hgrc | |||
|
1140 | $ try "cat4(278, '5f5', 1ee, 'ce5')" | |||
|
1141 | (func | |||
|
1142 | ('symbol', 'cat4') | |||
|
1143 | (list | |||
|
1144 | (list | |||
|
1145 | (list | |||
|
1146 | ('symbol', '278') | |||
|
1147 | ('string', '5f5')) | |||
|
1148 | ('symbol', '1ee')) | |||
|
1149 | ('string', 'ce5'))) | |||
|
1150 | (_concat | |||
|
1151 | (_concat | |||
|
1152 | (_concat | |||
|
1153 | ('symbol', '278') | |||
|
1154 | ('string', '5f5')) | |||
|
1155 | ('symbol', '1ee')) | |||
|
1156 | ('string', 'ce5')) | |||
|
1157 | ('string', '2785f51eece5') | |||
|
1158 | 0 | |||
|
1159 | ||||
|
1160 | (check concatenation in alias nesting) | |||
|
1161 | ||||
|
1162 | $ echo 'cat2($1, $2) = $1 ## $2' >> .hg/hgrc | |||
|
1163 | $ echo 'cat2x2($1, $2, $3, $4) = cat2($1 ## $2, $3 ## $4)' >> .hg/hgrc | |||
|
1164 | $ log "cat2x2(278, '5f5', 1ee, 'ce5')" | |||
|
1165 | 0 | |||
|
1166 | ||||
|
1167 | (check operator priority) | |||
|
1168 | ||||
|
1169 | $ echo 'cat2n2($1, $2, $3, $4) = $1 ## $2 or $3 ## $4~2' >> .hg/hgrc | |||
|
1170 | $ log "cat2n2(2785f5, 1eece5, 24286f, 4ae135)" | |||
|
1171 | 0 | |||
|
1172 | 4 | |||
|
1173 | ||||
1126 | $ cd .. |
|
1174 | $ cd .. | |
1127 |
|
1175 | |||
1128 | test author/desc/keyword in problematic encoding |
|
1176 | test author/desc/keyword in problematic encoding |
General Comments 0
You need to be logged in to leave comments.
Login now