def fill(context, mapping, args): if not (1 <= len(args) <= 4): raise error.ParseError(_("fill expects one to four arguments")) text = stringify(args[0][0](context, mapping, args[0][1])) width = 76 initindent = '' hangindent = '' if 2 <= len(args) <= 4: try: width = int(stringify(args[1][0](context, mapping, args[1][1]))) except ValueError: raise error.ParseError(_("fill expects an integer width")) try: initindent = stringify(args[2][0](context, mapping, args[2][1])) initindent = stringify( runtemplate(context, mapping, compiletemplate(initindent, context))) hangindent = stringify(args[3][0](context, mapping, args[3][1])) hangindent = stringify( runtemplate(context, mapping, compiletemplate(hangindent, context))) except IndexError: pass return templatefilters.fill(text, width, initindent, hangindent)
def _expandaliases(aliases, tree, expanding): """Expand aliases in tree, recursively. 'aliases' is a dictionary mapping user defined aliases to revsetalias objects. """ if not isinstance(tree, tuple): # Do not expand raw strings return tree alias = _getalias(aliases, tree) if alias is not None: if alias in expanding: raise error.ParseError( _('infinite expansion of revset alias "%s" ' 'detected') % alias.name) expanding.append(alias) result = _expandaliases(aliases, alias.replacement, expanding) expanding.pop() if alias.args is not None: l = getlist(tree[2]) if len(l) != len(alias.args): raise error.ParseError( _('invalid number of arguments: %s') % len(l)) l = [_expandaliases(aliases, a, []) for a in l] result = _expandargs(result, dict(zip(alias.args, l))) else: result = tuple(_expandaliases(aliases, t, expanding) for t in tree) return result
def buildargsdict(trees, funcname, keys, keyvaluenode, keynode): """Build dict from list containing positional and keyword arguments Invalid keywords or too many positional arguments are rejected, but missing arguments are just omitted. """ if len(trees) > len(keys): raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments") % {'func': funcname, 'nargs': len(keys)}) args = {} # consume positional arguments for k, x in zip(keys, trees): if x[0] == keyvaluenode: break args[k] = x # remainder should be keyword arguments for x in trees[len(args):]: if x[0] != keyvaluenode or x[1][0] != keynode: raise error.ParseError(_("%(func)s got an invalid argument") % {'func': funcname}) k = x[1][1] if k not in keys: raise error.ParseError(_("%(func)s got an unexpected keyword " "argument '%(key)s'") % {'func': funcname, 'key': k}) if k in args: raise error.ParseError(_("%(func)s got multiple values for keyword " "argument '%(key)s'") % {'func': funcname, 'key': k}) args[k] = x[2] return args
def tokenize(program): pos, l = 0, len(program) while pos < l: c = program[pos] if c.isspace(): # skip inter-token whitespace pass elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully yield ('::', None, pos) pos += 1 # skip ahead elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully yield ('..', None, pos) pos += 1 # skip ahead elif c in "():,-|&+!~^": # handle simple operators yield (c, None, pos) elif (c in '"\'' or c == 'r' and program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings if c == 'r': pos += 1 c = program[pos] decode = lambda x: x else: decode = lambda x: x.decode('string-escape') pos += 1 s = pos while pos < l: # find closing quote d = program[pos] if d == '\\': # skip over escaped characters pos += 2 continue if d == c: yield ('string', decode(program[s:pos]), s) break pos += 1 else: raise error.ParseError(_("unterminated string"), s) elif c.isalnum( ) or c in '._' or ord(c) > 127: # gather up a symbol/keyword s = pos pos += 1 while pos < l: # find end of symbol d = program[pos] if not (d.isalnum() or d in "._/" or ord(d) > 127): break if d == '.' and program[pos - 1] == '.': # special case for .. pos -= 1 break pos += 1 sym = program[s:pos] if sym in keywords: # operator keywords yield (sym, None, s) else: yield ('symbol', sym, s) pos -= 1 else: raise error.ParseError(_("syntax error"), pos) pos += 1 yield ('end', None, pos)
def get(context, mapping, args): if len(args) != 2: # i18n: "get" is a keyword raise error.ParseError(_("get() expects two arguments")) dictarg = args[0][0](context, mapping, args[0][1]) if not util.safehasattr(dictarg, 'get'): # i18n: "get" is a keyword raise error.ParseError(_("get() expects a dict as first argument")) key = args[1][0](context, mapping, args[1][1]) yield dictarg.get(key)
def match(ui, spec): if not spec: raise error.ParseError(_("empty query")) tree, pos = parse(spec) if (pos != len(spec)): raise error.ParseError(_("invalid token"), pos) if ui: tree = findaliases(ui, tree) weight, tree = optimize(tree, True) def mfunc(repo, subset): return getset(repo, subset, tree) return mfunc
def buildfunc(exp, context): n = getsymbol(exp[1]) args = [compileexp(x, context) for x in getlist(exp[2])] if n in funcs: f = funcs[n] return (f, args) if n in context._filters: if len(args) != 1: raise error.ParseError(_("filter %s expects one argument") % n) f = context._filters[n] return (runfilter, (args[0][0], args[0][1], f)) raise error.ParseError(_("unknown function '%s'") % n)
def tokenizer(data): program, start, end = data pos = start while pos < end: c = program[pos] if c.isspace(): # skip inter-token whitespace pass elif c in "(,)%|": # handle simple operators yield (c, None, pos) elif (c in '"\'' or c == 'r' and program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings if c == 'r': pos += 1 c = program[pos] decode = False else: decode = True pos += 1 s = pos while pos < end: # find closing quote d = program[pos] if decode and d == '\\': # skip over escaped characters pos += 2 continue if d == c: if not decode: yield ('string', program[s:pos].replace('\\', r'\\'), s) break yield ('string', program[s:pos].decode('string-escape'), s) break pos += 1 else: raise error.ParseError(_("unterminated string"), s) elif c.isalnum() or c in '_': s = pos pos += 1 while pos < end: # find end of symbol d = program[pos] if not (d.isalnum() or d == "_"): break pos += 1 sym = program[s:pos] yield ('symbol', sym, s) pos -= 1 elif c == '}': pos += 1 break else: raise error.ParseError(_("syntax error"), pos) pos += 1 yield ('end', None, pos)
def get(context, mapping, args): """:get(dict, key): Get an attribute/key from an object. Some keywords are complex types. This function allows you to obtain the value of an attribute on these type.""" if len(args) != 2: # i18n: "get" is a keyword raise error.ParseError(_("get() expects two arguments")) dictarg = args[0][0](context, mapping, args[0][1]) if not util.safehasattr(dictarg, 'get'): # i18n: "get" is a keyword raise error.ParseError(_("get() expects a dict as first argument")) key = args[1][0](context, mapping, args[1][1]) yield dictarg.get(key)
def getfileset(ctx, expr): tree, pos = parse(expr) if (pos != len(expr)): raise error.ParseError(_("invalid token"), pos) # do we need status info? if _intree([ 'modified', 'added', 'removed', 'deleted', 'unknown', 'ignored', 'clean' ], tree): unknown = _intree(['unknown'], tree) ignored = _intree(['ignored'], tree) r = ctx._repo status = r.status(ctx.p1(), ctx, unknown=unknown, ignored=ignored, clean=True) subset = [] for c in status: subset.extend(c) else: status = None subset = ctx.walk(ctx.match([])) return getset(matchctx(ctx, subset, status), tree)
def getfileset(ctx, expr): tree, pos = parse(expr) if (pos != len(expr)): raise error.ParseError(_("invalid token"), pos) # do we need status info? if (_intree(['modified', 'added', 'removed', 'deleted', 'unknown', 'ignored', 'clean'], tree) or # Using matchctx.existing() on a workingctx requires us to check # for deleted files. (ctx.rev() is None and _intree(_existingcallers, tree))): unknown = _intree(['unknown'], tree) ignored = _intree(['ignored'], tree) r = ctx._repo status = r.status(ctx.p1(), ctx, unknown=unknown, ignored=ignored, clean=True) subset = [] for c in status: subset.extend(c) else: status = None subset = list(ctx.walk(ctx.match([]))) return getset(matchctx(ctx, subset, status), tree)
def pad(context, mapping, args): """usage: pad(text, width, fillchar=' ', right=False) """ if not (2 <= len(args) <= 4): # i18n: "pad" is a keyword raise error.ParseError(_("pad() expects two to four arguments")) width = int(args[1][1]) text = stringify(args[0][0](context, mapping, args[0][1])) if args[0][0] == runstring: text = stringify( runtemplate(context, mapping, compiletemplate(text, context))) right = False fillchar = ' ' if len(args) > 2: fillchar = stringify(args[2][0](context, mapping, args[2][1])) if len(args) > 3: right = util.parsebool(args[3][1]) if right: return text.rjust(width, fillchar) else: return text.ljust(width, fillchar)
def gobble_string(self, string: str): initial_index = self.msg_index for i in range(len(string)): if string[i] == self.current(): self.gobble() else: raise error.ParseError(string, initial_index, self.msg)
def revset(context, mapping, args): """usage: revset(query[, formatargs...]) """ if not len(args) > 0: # i18n: "revset" is a keyword raise error.ParseError(_("revset expects one or more arguments")) raw = args[0][1] ctx = mapping['ctx'] repo = ctx.repo() def query(expr): m = revsetmod.match(repo.ui, expr) return m(repo) if len(args) > 1: formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]]) revs = query(revsetmod.formatspec(raw, *formatargs)) revs = list([str(r) for r in revs]) else: revsetcache = mapping['cache'].setdefault("revsetcache", {}) if raw in revsetcache: revs = revsetcache[raw] else: revs = query(raw) revs = list([str(r) for r in revs]) revsetcache[raw] = revs return templatekw.showlist("revision", revs, **mapping)
def label(context, mapping, args): if len(args) != 2: # i18n: "label" is a keyword raise error.ParseError(_("label expects two arguments")) # ignore args[0] (the label string) since this is supposed to be a a no-op yield _evalifliteral(args[1], context, mapping)
def _parse(ui, args): options = {} cmdoptions = {} try: args = fancyopts.fancyopts(args, commands.globalopts, options) except fancyopts.getopt.GetoptError, inst: raise error.ParseError(None, inst)
def label(context, mapping, args): if len(args) != 2: # i18n: "label" is a keyword raise error.ParseError(_("label expects two arguments")) # ignore args[0] (the label string) since this is supposed to be a a no-op t = stringify(args[1][0](context, mapping, args[1][1])) yield runtemplate(context, mapping, compiletemplate(t, context))
def match(spec): if not spec: raise error.ParseError(_("empty query")) tree = parse(spec) weight, tree = optimize(tree, True) def mfunc(repo, subset): return getset(repo, subset, tree) return mfunc
def date(context, mapping, args): if not (1 <= len(args) <= 2): raise error.ParseError(_("date expects one or two arguments")) date = args[0][0](context, mapping, args[0][1]) if len(args) == 2: fmt = stringify(args[1][0](context, mapping, args[1][1])) return util.datestr(date, fmt) return util.datestr(date)
def _sizetoint(s): try: s = s.strip() for k, v in _units.items(): if s.endswith(k): return int(float(s[:-len(k)]) * v) return int(s) except ValueError: raise error.ParseError(_("couldn't parse size: %s") % s)
def grep(mctx, x): """``grep(regex)`` File contains the given regular expression. """ try: # i18n: "grep" is a keyword r = re.compile(getstring(x, _("grep requires a pattern"))) except re.error, e: raise error.ParseError(_('invalid match pattern: %s') % e)
def strip(context, mapping, args): if not (1 <= len(args) <= 2): raise error.ParseError(_("strip expects one or two arguments")) text = stringify(args[0][0](context, mapping, args[0][1])) if len(args) == 2: chars = stringify(args[1][0](context, mapping, args[1][1])) return text.strip(chars) return text.strip()
def gettemplate(exp, context): if exp[0] == 'template': return compiletemplate(exp[1], context) if exp[0] == 'symbol': # unlike runsymbol(), here 'symbol' is always taken as template name # even if it exists in mapping. this allows us to override mapping # by web templates, e.g. 'changelogtag' is redefined in map file. return context._load(exp[1]) raise error.ParseError(_("expected template specifier"))
def sub(context, mapping, args): if len(args) != 3: # i18n: "sub" is a keyword raise error.ParseError(_("sub expects three arguments")) pat = stringify(args[0][0](context, mapping, args[0][1])) rpl = stringify(args[1][0](context, mapping, args[1][1])) src = stringify(_evalifliteral(args[2], context, mapping)) yield re.sub(pat, rpl, src)
def rstdoc(context, mapping, args): if len(args) != 2: # i18n: "rstdoc" is a keyword raise error.ParseError(_("rstdoc expects two arguments")) text = stringify(args[0][0](context, mapping, args[0][1])) style = stringify(args[1][0](context, mapping, args[1][1])) return minirst.format(text, style=style, keep=['verbose'])
def sort(repo, subset, x): """``sort(set[, [-]key...])`` Sort set by keys. The default sort order is ascending, specify a key as ``-key`` to sort in descending order. The keys can be: - ``rev`` for the revision number, - ``branch`` for the branch name, - ``desc`` for the commit message (description), - ``user`` for user name (``author`` can be used as an alias), - ``date`` for the commit date """ # i18n: "sort" is a keyword l = getargs(x, 1, 2, _("sort requires one or two arguments")) keys = "rev" if len(l) == 2: keys = getstring(l[1], _("sort spec must be a string")) s = l[0] keys = keys.split() l = [] def invert(s): return "".join(chr(255 - ord(c)) for c in s) for r in getset(repo, subset, s): c = repo[r] e = [] for k in keys: if k == 'rev': e.append(r) elif k == '-rev': e.append(-r) elif k == 'branch': e.append(c.branch()) elif k == '-branch': e.append(invert(c.branch())) elif k == 'desc': e.append(c.description()) elif k == '-desc': e.append(invert(c.description())) elif k in 'user author': e.append(c.user()) elif k in '-user -author': e.append(invert(c.user())) elif k == 'date': e.append(c.date()[0]) elif k == '-date': e.append(-c.date()[0]) else: raise error.ParseError(_("unknown sort key %r") % k) e.append(r) l.append(e) l.sort() return [e[-1] for e in l]
def startswith(context, mapping, args): if len(args) != 2: # i18n: "startswith" is a keyword raise error.ParseError(_("startswith expects two arguments")) patn = stringify(args[0][0](context, mapping, args[0][1])) text = stringify(args[1][0](context, mapping, args[1][1])) if text.startswith(patn): return text return ''
def _checkaliasarg(tree, known=None): """Check tree contains no _aliasarg construct or only ones which value is in known. Used to avoid alias placeholders injection. """ if isinstance(tree, tuple): arg = _getaliasarg(tree) if arg is not None and (not known or arg not in known): raise error.ParseError(_("not a function: %s") % '_aliasarg') for t in tree: _checkaliasarg(t, known)
def grep(mctx, x): """``grep(regex)`` File contains the given regular expression. """ try: # i18n: "grep" is a keyword r = re.compile(getstring(x, _("grep requires a pattern"))) except re.error as e: raise error.ParseError(_('invalid match pattern: %s') % e) return [f for f in mctx.existing() if r.search(mctx.ctx[f].data())]
def if_(context, mapping, args): if not (2 <= len(args) <= 3): # i18n: "if" is a keyword raise error.ParseError(_("if expects two or three arguments")) test = stringify(args[0][0](context, mapping, args[0][1])) if test: yield _evalifliteral(args[1], context, mapping) elif len(args) == 3: yield _evalifliteral(args[2], context, mapping)