mercurial/templater.py
changeset 20670 0084fcd5d7e2
parent 20539 aa021ece4506
parent 20663 5ab28a2e9962
child 20860 81d6dc8c3c63
equal deleted inserted replaced
20669:870d60294b04 20670:0084fcd5d7e2
    19     "|": (5, None, ("|", 5)),
    19     "|": (5, None, ("|", 5)),
    20     "%": (6, None, ("%", 6)),
    20     "%": (6, None, ("%", 6)),
    21     ")": (0, None, None),
    21     ")": (0, None, None),
    22     "symbol": (0, ("symbol",), None),
    22     "symbol": (0, ("symbol",), None),
    23     "string": (0, ("string",), None),
    23     "string": (0, ("string",), None),
       
    24     "rawstring": (0, ("rawstring",), None),
    24     "end": (0, None, None),
    25     "end": (0, None, None),
    25 }
    26 }
    26 
    27 
    27 def tokenizer(data):
    28 def tokenizer(data):
    28     program, start, end = data
    29     program, start, end = data
    48                 if decode and d == '\\': # skip over escaped characters
    49                 if decode and d == '\\': # skip over escaped characters
    49                     pos += 2
    50                     pos += 2
    50                     continue
    51                     continue
    51                 if d == c:
    52                 if d == c:
    52                     if not decode:
    53                     if not decode:
    53                         yield ('string', program[s:pos].replace('\\', r'\\'), s)
    54                         yield ('rawstring', program[s:pos], s)
    54                         break
    55                         break
    55                     yield ('string', program[s:pos], s)
    56                     yield ('string', program[s:pos], s)
    56                     break
    57                     break
    57                 pos += 1
    58                 pos += 1
    58             else:
    59             else:
    74         else:
    75         else:
    75             raise error.ParseError(_("syntax error"), pos)
    76             raise error.ParseError(_("syntax error"), pos)
    76         pos += 1
    77         pos += 1
    77     yield ('end', None, pos)
    78     yield ('end', None, pos)
    78 
    79 
    79 def compiletemplate(tmpl, context):
    80 def compiletemplate(tmpl, context, strtoken="string"):
    80     parsed = []
    81     parsed = []
    81     pos, stop = 0, len(tmpl)
    82     pos, stop = 0, len(tmpl)
    82     p = parser.parser(tokenizer, elements)
    83     p = parser.parser(tokenizer, elements)
    83     while pos < stop:
    84     while pos < stop:
    84         n = tmpl.find('{', pos)
    85         n = tmpl.find('{', pos)
    85         if n < 0:
    86         if n < 0:
    86             parsed.append(("string", tmpl[pos:].decode("string-escape")))
    87             parsed.append((strtoken, tmpl[pos:]))
    87             break
    88             break
    88         if n > 0 and tmpl[n - 1] == '\\':
    89         if n > 0 and tmpl[n - 1] == '\\':
    89             # escaped
    90             # escaped
    90             parsed.append(("string",
    91             parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
    91                            (tmpl[pos:n - 1] + "{").decode("string-escape")))
       
    92             pos = n + 1
    92             pos = n + 1
    93             continue
    93             continue
    94         if n > pos:
    94         if n > pos:
    95             parsed.append(("string", tmpl[pos:n].decode("string-escape")))
    95             parsed.append((strtoken, tmpl[pos:n]))
    96 
    96 
    97         pd = [tmpl, n + 1, stop]
    97         pd = [tmpl, n + 1, stop]
    98         parseres, pos = p.parse(pd)
    98         parseres, pos = p.parse(pd)
    99         parsed.append(parseres)
    99         parsed.append(parseres)
   100 
   100 
   125     if f not in context._filters:
   125     if f not in context._filters:
   126         raise error.ParseError(_("unknown function '%s'") % f)
   126         raise error.ParseError(_("unknown function '%s'") % f)
   127     return context._filters[f]
   127     return context._filters[f]
   128 
   128 
   129 def gettemplate(exp, context):
   129 def gettemplate(exp, context):
   130     if exp[0] == 'string':
   130     if exp[0] == 'string' or exp[0] == 'rawstring':
   131         return compiletemplate(exp[1], context)
   131         return compiletemplate(exp[1], context, strtoken=exp[0])
   132     if exp[0] == 'symbol':
   132     if exp[0] == 'symbol':
   133         return context._load(exp[1])
   133         return context._load(exp[1])
   134     raise error.ParseError(_("expected template specifier"))
   134     raise error.ParseError(_("expected template specifier"))
   135 
   135 
   136 def runstring(context, mapping, data):
   136 def runstring(context, mapping, data):
       
   137     return data.decode("string-escape")
       
   138 
       
   139 def runrawstring(context, mapping, data):
   137     return data
   140     return data
   138 
   141 
   139 def runsymbol(context, mapping, key):
   142 def runsymbol(context, mapping, key):
   140     v = mapping.get(key)
   143     v = mapping.get(key)
   141     if v is None:
   144     if v is None:
   232         try:
   235         try:
   233             width = int(stringify(args[1][0](context, mapping, args[1][1])))
   236             width = int(stringify(args[1][0](context, mapping, args[1][1])))
   234         except ValueError:
   237         except ValueError:
   235             raise error.ParseError(_("fill expects an integer width"))
   238             raise error.ParseError(_("fill expects an integer width"))
   236         try:
   239         try:
   237             initindent = stringify(args[2][0](context, mapping, args[2][1]))
   240             initindent = stringify(_evalifliteral(args[2], context, mapping))
   238             initindent = stringify(runtemplate(context, mapping,
   241             hangindent = stringify(_evalifliteral(args[3], context, mapping))
   239                                      compiletemplate(initindent, context)))
       
   240             hangindent = stringify(args[3][0](context, mapping, args[3][1]))
       
   241             hangindent = stringify(runtemplate(context, mapping,
       
   242                                      compiletemplate(hangindent, context)))
       
   243         except IndexError:
   242         except IndexError:
   244             pass
   243             pass
   245 
   244 
   246     return templatefilters.fill(text, width, initindent, hangindent)
   245     return templatefilters.fill(text, width, initindent, hangindent)
   247 
   246 
   283     key = args[1][0](context, mapping, args[1][1])
   282     key = args[1][0](context, mapping, args[1][1])
   284     yield dictarg.get(key)
   283     yield dictarg.get(key)
   285 
   284 
   286 def _evalifliteral(arg, context, mapping):
   285 def _evalifliteral(arg, context, mapping):
   287     t = stringify(arg[0](context, mapping, arg[1]))
   286     t = stringify(arg[0](context, mapping, arg[1]))
   288     if arg[0] == runstring:
   287     if arg[0] == runstring or arg[0] == runrawstring:
   289         yield runtemplate(context, mapping, compiletemplate(t, context))
   288         yield runtemplate(context, mapping,
       
   289                           compiletemplate(t, context, strtoken='rawstring'))
   290     else:
   290     else:
   291         yield t
   291         yield t
   292 
   292 
   293 def if_(context, mapping, args):
   293 def if_(context, mapping, args):
   294     if not (2 <= len(args) <= 3):
   294     if not (2 <= len(args) <= 3):
   336         jf = joinset.joinfmt
   336         jf = joinset.joinfmt
   337         joinset = [jf(x) for x in joinset()]
   337         joinset = [jf(x) for x in joinset()]
   338 
   338 
   339     joiner = " "
   339     joiner = " "
   340     if len(args) > 1:
   340     if len(args) > 1:
   341         joiner = args[1][0](context, mapping, args[1][1])
   341         joiner = stringify(args[1][0](context, mapping, args[1][1]))
   342 
   342 
   343     first = True
   343     first = True
   344     for x in joinset:
   344     for x in joinset:
   345         if first:
   345         if first:
   346             first = False
   346             first = False
   445 
   445 
   446 def strip(context, mapping, args):
   446 def strip(context, mapping, args):
   447     if not (1 <= len(args) <= 2):
   447     if not (1 <= len(args) <= 2):
   448         raise error.ParseError(_("strip expects one or two arguments"))
   448         raise error.ParseError(_("strip expects one or two arguments"))
   449 
   449 
   450     text = args[0][0](context, mapping, args[0][1])
   450     text = stringify(args[0][0](context, mapping, args[0][1]))
   451     if len(args) == 2:
   451     if len(args) == 2:
   452         chars = args[1][0](context, mapping, args[1][1])
   452         chars = stringify(args[1][0](context, mapping, args[1][1]))
   453         return text.strip(chars)
   453         return text.strip(chars)
   454     return text.strip()
   454     return text.strip()
   455 
   455 
   456 def sub(context, mapping, args):
   456 def sub(context, mapping, args):
   457     if len(args) != 3:
   457     if len(args) != 3:
   458         # i18n: "sub" is a keyword
   458         # i18n: "sub" is a keyword
   459         raise error.ParseError(_("sub expects three arguments"))
   459         raise error.ParseError(_("sub expects three arguments"))
   460 
   460 
   461     pat = stringify(args[0][0](context, mapping, args[0][1]))
   461     pat = stringify(args[0][0](context, mapping, args[0][1]))
   462     rpl = stringify(args[1][0](context, mapping, args[1][1]))
   462     rpl = stringify(args[1][0](context, mapping, args[1][1]))
   463     src = stringify(args[2][0](context, mapping, args[2][1]))
   463     src = stringify(_evalifliteral(args[2], context, mapping))
   464     src = stringify(runtemplate(context, mapping,
       
   465                                 compiletemplate(src, context)))
       
   466     yield re.sub(pat, rpl, src)
   464     yield re.sub(pat, rpl, src)
   467 
   465 
   468 methods = {
   466 methods = {
   469     "string": lambda e, c: (runstring, e[1]),
   467     "string": lambda e, c: (runstring, e[1]),
       
   468     "rawstring": lambda e, c: (runrawstring, e[1]),
   470     "symbol": lambda e, c: (runsymbol, e[1]),
   469     "symbol": lambda e, c: (runsymbol, e[1]),
   471     "group": lambda e, c: compileexp(e[1], c),
   470     "group": lambda e, c: compileexp(e[1], c),
   472 #    ".": buildmember,
   471 #    ".": buildmember,
   473     "|": buildfilter,
   472     "|": buildfilter,
   474     "%": buildmap,
   473     "%": buildmap,