##// END OF EJS Templates
profiling: move 'fp' closing logic into its own function...
profiling: move 'fp' closing logic into its own function We are about to make the logic more robust and reuse it in more place, we start by isolating what we have.

File last commit:

r32743:f924dd04 default
r32804:c0b2c8f2 default
Show More
templatefilters.py
437 lines | 12.5 KiB | text/x-python | PythonLexer
Yuya Nishihara
templatefilers: correct filename in header comment
r32740 # templatefilters.py - common template expansion filters
Matt Mackall
templates: move filters to their own module...
r5976 #
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
templates: move filters to their own module...
r5976
Gregory Szorc
templatefilters: use absolute_import
r25983 from __future__ import absolute_import
import cgi
import os
import re
import time
from . import (
encoding,
hbisect,
node,
Pulkit Goyal
py3: alias long to int on Python 3
r32126 pycompat,
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 registrar,
Gregory Szorc
templatefilters: use absolute_import
r25983 templatekw,
util,
)
Matt Mackall
templates: move filters to their own module...
r5976
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Pulkit Goyal
py3: alias long to int on Python 3
r32126 if pycompat.ispy3:
long = int
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 # filters are callables like:
# fn(obj)
# with:
# obj - object to be filtered (text, date, list and so on)
filters = {}
templatefilter = registrar.templatefilter(filters)
@templatefilter('addbreaks')
Patrick Mezard
templatefilters: sort function definitions
r13588 def addbreaks(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Add an XHTML "<br />" tag before the end of
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 every line except the last.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 return text.replace('\n', '<br/>\n')
Dirkjan Ochtman
templater: provide the standard template filters by default
r8360
David Soria Parra
templatefilters: add short format for age formatting...
r19736 agescales = [("year", 3600 * 24 * 365, 'Y'),
("month", 3600 * 24 * 30, 'M'),
("week", 3600 * 24 * 7, 'W'),
("day", 3600 * 24, 'd'),
("hour", 3600, 'h'),
("minute", 60, 'm'),
("second", 1, 's')]
Matt Mackall
templates: move filters to their own module...
r5976
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('age')
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def age(date, abbrev=False):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a human-readable date/time difference between the
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 given date/time and the current date/time.
"""
Matt Mackall
templates: move filters to their own module...
r5976
def plural(t, c):
if c == 1:
return t
return t + "s"
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def fmt(t, c, a):
if abbrev:
return "%d%s" % (c, a)
Matt Mackall
templates: move filters to their own module...
r5976 return "%d %s" % (c, plural(t, c))
now = time.time()
then = date[0]
timeless
templates: provide granularity for future values for age filter
r13666 future = False
Dirkjan Ochtman
templater: fix age filter to state the obvious on future timestamps
r7682 if then > now:
timeless
templates: provide granularity for future values for age filter
r13666 future = True
delta = max(1, int(then - now))
if delta > agescales[0][1] * 30:
return 'in the distant future'
else:
delta = max(1, int(now - then))
if delta > agescales[0][1] * 2:
return util.shortdate(date)
Dirkjan Ochtman
templater: readable dates older than 24 months revert to ISO8601 (issue1006)
r9722
David Soria Parra
templatefilters: add short format for age formatting...
r19736 for t, s, a in agescales:
Alejandro Santos
compat: use // for integer division
r9029 n = delta // s
Matt Mackall
templates: move filters to their own module...
r5976 if n >= 2 or s == 1:
timeless
templates: provide granularity for future values for age filter
r13666 if future:
David Soria Parra
templatefilters: add short format for age formatting...
r19736 return '%s from now' % fmt(t, n, a)
return '%s ago' % fmt(t, n, a)
Matt Mackall
templates: move filters to their own module...
r5976
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('basename')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def basename(path):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Treats the text as a path, and returns the last
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 component of the path after splitting by the path separator
(ignoring trailing separators). For example, "foo/bar/baz" becomes
"baz" and "foo/bar//" becomes "bar".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return os.path.basename(path)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('count')
Anton Shestakov
templater: add count template filter, plus tests...
r22668 def count(i):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """List or text. Returns the length as an integer."""
Anton Shestakov
templater: add count template filter, plus tests...
r22668 return len(i)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('domain')
Patrick Mezard
templatefilters: sort function definitions
r13588 def domain(author):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Finds the first string that looks like an email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 address, and extracts just the domain component. Example: ``User
<user@example.com>`` becomes ``example.com``.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 f = author.find('@')
if f == -1:
return ''
author = author[f + 1:]
f = author.find('>')
if f >= 0:
author = author[:f]
return author
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('email')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def email(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Extracts the first string that looks like an email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 address. Example: ``User <user@example.com>`` becomes
``user@example.com``.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.email(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('escape')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def escape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Replaces the special XML/XHTML characters "&", "<"
Siddharth Agarwal
hgweb: make the escape filter remove null characters (issue2567)
r17772 and ">" with XML entities, and filters out NUL characters.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Siddharth Agarwal
hgweb: make the escape filter remove null characters (issue2567)
r17772 return cgi.escape(text.replace('\0', ''), True)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Matt Mackall
templates: move filters to their own module...
r5976 para_re = None
space_re = None
Mads Kiilerich
check-code: check for spaces around = for named parameters
r19872 def fill(text, width, initindent='', hangindent=''):
Sean Farley
templater: add indentation arguments to the fill function
r19228 '''fill many paragraphs with optional indentation.'''
Matt Mackall
templates: move filters to their own module...
r5976 global para_re, space_re
if para_re is None:
para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
space_re = re.compile(r' +')
def findparas():
start = 0
while True:
m = para_re.search(text, start)
if not m:
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 uctext = unicode(text[start:], encoding.encoding)
w = len(uctext)
while 0 < w and uctext[w - 1].isspace():
Matt Mackall
many, many trivial check-code fixups
r10282 w -= 1
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 yield (uctext[:w].encode(encoding.encoding),
uctext[w:].encode(encoding.encoding))
Matt Mackall
templates: move filters to their own module...
r5976 break
yield text[start:m.start(0)], m.group(1)
start = m.end(1)
Sean Farley
templater: add indentation arguments to the fill function
r19228 return "".join([util.wrap(space_re.sub(' ', util.wrap(para, width)),
width, initindent, hangindent) + rest
Matt Mackall
templates: move filters to their own module...
r5976 for para, rest in findparas()])
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('fill68')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def fill68(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Wraps the text to fit in 68 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 68)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('fill76')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def fill76(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Wraps the text to fit in 76 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 76)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('firstline')
Matt Mackall
templates: move filters to their own module...
r5976 def firstline(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the first line of text."""
Matt Mackall
templates: move filters to their own module...
r5976 try:
Nicolas Dumazet
for calls expecting bool args, pass bool instead of int...
r9136 return text.splitlines(True)[0].rstrip('\r\n')
Matt Mackall
templates: move filters to their own module...
r5976 except IndexError:
return ''
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('hex')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def hexfilter(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Convert a binary Mercurial node identifier into
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 its long hexadecimal representation.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return node.hex(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('hgdate')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def hgdate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date as a pair of numbers: "1157407993
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 25200" (Unix timestamp, timezone offset).
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return "%d %d" % text
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('isodate')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def isodate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 +0200".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('isodatesec')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def isodatesec(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date in ISO 8601 format, including
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
filter.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
Matt Mackall
templates: move filters to their own module...
r5976 def indent(text, prefix):
'''indent each non-empty line of text after first with prefix.'''
lines = text.splitlines()
num_lines = len(lines)
Nicolas Dumazet
templatefilters: indent: do not compute text.endswith('\n') in each iteration
r9387 endswithnewline = text[-1:] == '\n'
Matt Mackall
templates: move filters to their own module...
r5976 def indenter():
for i in xrange(num_lines):
l = lines[i]
if i and l.strip():
yield prefix
yield l
Nicolas Dumazet
templatefilters: indent: do not compute text.endswith('\n') in each iteration
r9387 if i < num_lines - 1 or endswithnewline:
Matt Mackall
templates: move filters to their own module...
r5976 yield '\n'
return "".join(indenter())
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('json')
Yuya Nishihara
formatter: use templatefilters.json()...
r31782 def json(obj, paranoid=True):
Yuya Nishihara
templatefilters: unroll handling of None/False/True...
r31780 if obj is None:
return 'null'
elif obj is False:
return 'false'
elif obj is True:
return 'true'
Matt Harbison
templatefilter: add support for 'long' to json()...
r31728 elif isinstance(obj, (int, long, float)):
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r32127 return pycompat.bytestr(obj)
Pulkit Goyal
py3: replace str with bytes in isinstance()
r32128 elif isinstance(obj, bytes):
Yuya Nishihara
formatter: use templatefilters.json()...
r31782 return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
Augie Fackler
templatefilters: use safehasattr instead of hasattr
r14967 elif util.safehasattr(obj, 'keys'):
Yuya Nishihara
json: pass formatting options recursively...
r32743 out = ['"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid),
json(v, paranoid))
Yuya Nishihara
templatefilters: use list comprehension in json()...
r31781 for k, v in sorted(obj.iteritems())]
Dirkjan Ochtman
add graph page to hgweb
r6691 return '{' + ', '.join(out) + '}'
Augie Fackler
globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
r14944 elif util.safehasattr(obj, '__iter__'):
Yuya Nishihara
json: pass formatting options recursively...
r32743 out = [json(i, paranoid) for i in obj]
Dirkjan Ochtman
add graph page to hgweb
r6691 return '[' + ', '.join(out) + ']'
else:
raise TypeError('cannot encode type %s' % obj.__class__.__name__)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('lower')
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 def lower(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts the text to lowercase."""
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 return encoding.lower(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('nonempty')
Patrick Mezard
templatefilters: sort function definitions
r13588 def nonempty(str):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns '(none)' if the string is empty."""
Patrick Mezard
templatefilters: sort function definitions
r13588 return str or "(none)"
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('obfuscate')
Patrick Mezard
templatefilters: sort function definitions
r13588 def obfuscate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the input text rendered as a sequence of
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 XML entities.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 text = unicode(text, encoding.encoding, 'replace')
return ''.join(['&#%d;' % ord(c) for c in text])
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('permissions')
Patrick Mezard
templatefilters: sort function definitions
r13588 def permissions(flags):
if "l" in flags:
return "lrwxrwxrwx"
if "x" in flags:
return "-rwxr-xr-x"
return "-rw-r--r--"
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('person')
Patrick Mezard
templatefilters: sort function definitions
r13588 def person(author):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the name before an email address,
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 interpreting it as per RFC 5322.
"Yann E. MORIN"
templates/filters: add doctest to the 'person' filter...
r16251
>>> person('foo@bar')
'foo'
>>> person('Foo Bar <foo@bar>')
'Foo Bar'
>>> person('"Foo Bar" <foo@bar>')
'Foo Bar'
>>> person('"Foo \"buz\" Bar" <foo@bar>')
'Foo "buz" Bar'
>>> # The following are invalid, but do exist in real-life
...
>>> person('Foo "buz" Bar <foo@bar>')
'Foo "buz" Bar'
>>> person('"Foo Bar <foo@bar>')
'Foo Bar'
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 """
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 if '@' not in author:
Patrick Mezard
templatefilters: sort function definitions
r13588 return author
f = author.find('<')
Adrian Buehlmann
templatefilters: improve person() for john.doe@example.com...
r13951 if f != -1:
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 return author[:f].strip(' "').replace('\\"', '"')
Adrian Buehlmann
templatefilters: improve person() for john.doe@example.com...
r13951 f = author.find('@')
return author[:f].replace('.', ' ')
Patrick Mezard
templatefilters: sort function definitions
r13588
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('revescape')
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778 def revescape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Escapes all "special" characters, except @.
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778 Forward slashes are escaped twice to prevent web servers from prematurely
unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
"""
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 return urlreq.quote(text, safe='/@').replace('/', '%252F')
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('rfc3339date')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def rfc3339date(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date using the Internet date format
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('rfc822date')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def rfc822date(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date using the same format used in email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('short')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def short(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Changeset hash. Returns the short form of a changeset hash,
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 i.e. a 12 hexadecimal digit string.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return text[:12]
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('shortbisect')
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 def shortbisect(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Treats `text` as a bisection status, and
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 returns a single-character representing the status (G: good, B: bad,
S: skipped, U: untested, I: ignored). Returns single space if `text`
is not a valid bisection status.
"""
return hbisect.shortlabel(text) or ' '
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('shortdate')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def shortdate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date like "2006-09-18"."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.shortdate(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('splitlines')
Ryan McElroy
templatefilter: add splitlines function...
r21820 def splitlines(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Split text into a list of lines."""
Yuya Nishihara
templatefilters: fix crash by string formatting of '{x|splitlines}'...
r32039 return templatekw.hybridlist(text.splitlines(), name='line')
Ryan McElroy
templatefilter: add splitlines function...
r21820
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('stringescape')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def stringescape(text):
Yuya Nishihara
util: wrap s.encode('string_escape') call for future py3 compatibility
r31451 return util.escapestr(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('stringify')
Patrick Mezard
templatefilters: sort function definitions
r13588 def stringify(thing):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any type. Turns the value into text by converting values into
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 text and concatenating them.
"""
Yuya Nishihara
templater: remove __iter__() from _hybrid, resolve it explicitly...
r31880 thing = templatekw.unwraphybrid(thing)
Pulkit Goyal
py3: replace str with bytes in isinstance()
r32128 if util.safehasattr(thing, '__iter__') and not isinstance(thing, bytes):
Patrick Mezard
templatefilters: sort function definitions
r13588 return "".join([stringify(t) for t in thing if t is not None])
Jordi Gutiérrez Hermoso
templatefilters: don't stringify None into "None"...
r25000 if thing is None:
return ""
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r32127 return pycompat.bytestr(thing)
Patrick Mezard
templatefilters: sort function definitions
r13588
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('stripdir')
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 def stripdir(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Treat the text as path and strip a directory level, if
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 possible. For example, "foo" and "foo/bar" becomes "foo".
"""
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 dir = os.path.dirname(text)
if dir == "":
return os.path.basename(text)
else:
return dir
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('tabindent')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def tabindent(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the text, with every non-empty line
Matt Mackall
template: fix tabindent docstring (issue2880)
r19467 except the first starting with a tab character.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return indent(text, '\t')
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('upper')
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 def upper(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts the text to uppercase."""
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 return encoding.upper(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('urlescape')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def urlescape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Escapes all "special" characters. For example,
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 "foo bar" becomes "foo%20bar".
"""
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 return urlreq.quote(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('user')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def userfilter(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns a short representation of a user name or email
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 address."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.shortuser(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('emailuser')
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 def emailuser(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the user portion of an email address."""
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 return util.emailuser(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('utf8')
Yuya Nishihara
templatefilters: add "utf8" to get utf-8 bytes from local-encoding text...
r28209 def utf8(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts from the local character encoding to UTF-8."""
Yuya Nishihara
templatefilters: add "utf8" to get utf-8 bytes from local-encoding text...
r28209 return encoding.fromlocal(text)
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 @templatefilter('xmlescape')
Patrick Mezard
templatefilters: sort function definitions
r13588 def xmlescape(text):
text = (text
.replace('&', '&amp;')
.replace('<', '&lt;')
.replace('>', '&gt;')
.replace('"', '&quot;')
.replace("'", '&#39;')) # &apos; invalid in HTML
return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
Rocco Rutte
templatefilters: add "nonempty" template filter...
r8234
Angel Ezquerra
hgweb: add websub template filter...
r18627 def websub(text, websubtable):
""":websub: Any text. Only applies to hgweb. Applies the regular
expression replacements defined in the websub section.
"""
if websubtable:
for regexp, format in websubtable:
text = regexp.sub(format, text)
return text
FUJIWARA Katsunori
registrar: add templatefilter to mark a function as template filter (API)...
r28692 def loadfilter(ui, extname, registrarobj):
"""Load template filter from specified registrarobj
"""
for name, func in registrarobj._table.iteritems():
filters[name] = func
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 # tell hggettext to extract docstrings from these functions:
i18nfunctions = filters.values()