mercurial/templater.py
changeset 36669 80d7fb6c2dec
parent 36648 6585ac350fd9
child 36670 44048f1bcee5
equal deleted inserted replaced
36668:e77cee5de1c7 36669:80d7fb6c2dec
   211     """Parse template string into chunks of strings and template expressions"""
   211     """Parse template string into chunks of strings and template expressions"""
   212     sepchars = '{' + quote
   212     sepchars = '{' + quote
   213     unescape = [parser.unescapestr, pycompat.identity][raw]
   213     unescape = [parser.unescapestr, pycompat.identity][raw]
   214     pos = start
   214     pos = start
   215     p = parser.parser(elements)
   215     p = parser.parser(elements)
   216     while pos < stop:
   216     try:
   217         n = min((tmpl.find(c, pos, stop) for c in sepchars),
   217         while pos < stop:
   218                 key=lambda n: (n < 0, n))
   218             n = min((tmpl.find(c, pos, stop) for c in sepchars),
   219         if n < 0:
   219                     key=lambda n: (n < 0, n))
   220             yield ('string', unescape(tmpl[pos:stop]), pos)
   220             if n < 0:
   221             pos = stop
   221                 yield ('string', unescape(tmpl[pos:stop]), pos)
   222             break
   222                 pos = stop
   223         c = tmpl[n:n + 1]
   223                 break
   224         bs = 0  # count leading backslashes
   224             c = tmpl[n:n + 1]
   225         if not raw:
   225             bs = 0  # count leading backslashes
   226             bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
   226             if not raw:
   227         if bs % 2 == 1:
   227                 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
   228             # escaped (e.g. '\{', '\\\{', but not '\\{')
   228             if bs % 2 == 1:
   229             yield ('string', unescape(tmpl[pos:n - 1]) + c, pos)
   229                 # escaped (e.g. '\{', '\\\{', but not '\\{')
   230             pos = n + 1
   230                 yield ('string', unescape(tmpl[pos:n - 1]) + c, pos)
   231             continue
   231                 pos = n + 1
   232         if n > pos:
   232                 continue
   233             yield ('string', unescape(tmpl[pos:n]), pos)
   233             if n > pos:
   234         if c == quote:
   234                 yield ('string', unescape(tmpl[pos:n]), pos)
   235             yield ('end', None, n + 1)
   235             if c == quote:
   236             return
   236                 yield ('end', None, n + 1)
   237 
   237                 return
   238         parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
   238 
   239         if not tmpl.endswith('}', n + 1, pos):
   239             parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
   240             raise error.ParseError(_("invalid token"), pos)
   240             if not tmpl.endswith('}', n + 1, pos):
   241         yield ('template', parseres, n)
   241                 raise error.ParseError(_("invalid token"), pos)
   242 
   242             yield ('template', parseres, n)
   243     if quote:
   243 
   244         raise error.ParseError(_("unterminated string"), start)
   244         if quote:
       
   245             raise error.ParseError(_("unterminated string"), start)
       
   246     except error.ParseError as inst:
       
   247         if len(inst.args) > 1:  # has location
       
   248             loc = inst.args[1]
       
   249             # TODO: Opportunity for improvement! If there is a newline in the
       
   250             # template, this hint does not point to the right place, so skip.
       
   251             if '\n' not in tmpl:
       
   252                 # We want the caret to point to the place in the template that
       
   253                 # failed to parse, but in a hint we get a open paren at the
       
   254                 # start. Therefore, we print "loc" spaces (instead of "loc - 1")
       
   255                 # to line up the caret with the location of the error.
       
   256                 inst.hint = tmpl + '\n' + ' ' * (loc) + '^ ' + _('here')
       
   257         raise
   245     yield ('end', None, pos)
   258     yield ('end', None, pos)
   246 
   259 
   247 def _unnesttemplatelist(tree):
   260 def _unnesttemplatelist(tree):
   248     """Expand list of templates to node tuple
   261     """Expand list of templates to node tuple
   249 
   262