##// END OF EJS Templates
templater: add option to parse template string just like raw string literal...
Yuya Nishihara -
r36527:638c012a default
parent child Browse files
Show More
@@ -178,8 +178,14 b' def _parsetemplate(tmpl, start, stop, qu'
178 raise error.ProgrammingError('unexpected type: %s' % typ)
178 raise error.ProgrammingError('unexpected type: %s' % typ)
179 raise error.ProgrammingError('unterminated scanning of template')
179 raise error.ProgrammingError('unterminated scanning of template')
180
180
181 def scantemplate(tmpl):
181 def scantemplate(tmpl, raw=False):
182 """Scan (type, start, end) positions of outermost elements in template
182 r"""Scan (type, start, end) positions of outermost elements in template
183
184 If raw=True, a backslash is not taken as an escape character just like
185 r'' string in Python. Note that this is different from r'' literal in
186 template in that no template fragment can appear in r'', e.g. r'{foo}'
187 is a literal '{foo}', but ('{foo}', raw=True) is a template expression
188 'foo'.
183
189
184 >>> list(scantemplate(b'foo{bar}"baz'))
190 >>> list(scantemplate(b'foo{bar}"baz'))
185 [('string', 0, 3), ('template', 3, 8), ('string', 8, 12)]
191 [('string', 0, 3), ('template', 3, 8), ('string', 8, 12)]
@@ -187,9 +193,11 b' def scantemplate(tmpl):'
187 [('string', 0, 5), ('template', 5, 14), ('string', 14, 19)]
193 [('string', 0, 5), ('template', 5, 14), ('string', 14, 19)]
188 >>> list(scantemplate(b'foo\\{escaped}'))
194 >>> list(scantemplate(b'foo\\{escaped}'))
189 [('string', 0, 5), ('string', 5, 13)]
195 [('string', 0, 5), ('string', 5, 13)]
196 >>> list(scantemplate(b'foo\\{escaped}', raw=True))
197 [('string', 0, 4), ('template', 4, 13)]
190 """
198 """
191 last = None
199 last = None
192 for typ, val, pos in _scantemplate(tmpl, 0, len(tmpl)):
200 for typ, val, pos in _scantemplate(tmpl, 0, len(tmpl), raw=raw):
193 if last:
201 if last:
194 yield last + (pos,)
202 yield last + (pos,)
195 if typ == 'end':
203 if typ == 'end':
@@ -198,27 +206,30 b' def scantemplate(tmpl):'
198 last = (typ, pos)
206 last = (typ, pos)
199 raise error.ProgrammingError('unterminated scanning of template')
207 raise error.ProgrammingError('unterminated scanning of template')
200
208
201 def _scantemplate(tmpl, start, stop, quote=''):
209 def _scantemplate(tmpl, start, stop, quote='', raw=False):
202 """Parse template string into chunks of strings and template expressions"""
210 """Parse template string into chunks of strings and template expressions"""
203 sepchars = '{' + quote
211 sepchars = '{' + quote
212 unescape = [parser.unescapestr, pycompat.identity][raw]
204 pos = start
213 pos = start
205 p = parser.parser(elements)
214 p = parser.parser(elements)
206 while pos < stop:
215 while pos < stop:
207 n = min((tmpl.find(c, pos, stop) for c in sepchars),
216 n = min((tmpl.find(c, pos, stop) for c in sepchars),
208 key=lambda n: (n < 0, n))
217 key=lambda n: (n < 0, n))
209 if n < 0:
218 if n < 0:
210 yield ('string', parser.unescapestr(tmpl[pos:stop]), pos)
219 yield ('string', unescape(tmpl[pos:stop]), pos)
211 pos = stop
220 pos = stop
212 break
221 break
213 c = tmpl[n:n + 1]
222 c = tmpl[n:n + 1]
214 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
223 bs = 0 # count leading backslashes
224 if not raw:
225 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
215 if bs % 2 == 1:
226 if bs % 2 == 1:
216 # escaped (e.g. '\{', '\\\{', but not '\\{')
227 # escaped (e.g. '\{', '\\\{', but not '\\{')
217 yield ('string', parser.unescapestr(tmpl[pos:n - 1]) + c, pos)
228 yield ('string', unescape(tmpl[pos:n - 1]) + c, pos)
218 pos = n + 1
229 pos = n + 1
219 continue
230 continue
220 if n > pos:
231 if n > pos:
221 yield ('string', parser.unescapestr(tmpl[pos:n]), pos)
232 yield ('string', unescape(tmpl[pos:n]), pos)
222 if c == quote:
233 if c == quote:
223 yield ('end', None, n + 1)
234 yield ('end', None, n + 1)
224 return
235 return
General Comments 0
You need to be logged in to leave comments. Login now