mercurial/templater.py
changeset 1896 f8f818a04f5b
child 1897 58b6784cf9f1
equal deleted inserted replaced
1800:414e81ae971f 1896:f8f818a04f5b
       
     1 from demandload import demandload
       
     2 demandload(globals(), "cgi os re time urllib util")
       
     3 
       
     4 class templater(object):
       
     5     def __init__(self, mapfile, filters={}, defaults={}):
       
     6         self.cache = {}
       
     7         self.map = {}
       
     8         self.base = os.path.dirname(mapfile)
       
     9         self.filters = filters
       
    10         self.defaults = defaults
       
    11 
       
    12         for l in file(mapfile):
       
    13             m = re.match(r'(\S+)\s*=\s*"(.*)"$', l)
       
    14             if m:
       
    15                 self.cache[m.group(1)] = m.group(2)
       
    16             else:
       
    17                 m = re.match(r'(\S+)\s*=\s*(\S+)', l)
       
    18                 if m:
       
    19                     self.map[m.group(1)] = os.path.join(self.base, m.group(2))
       
    20                 else:
       
    21                     raise LookupError(_("unknown map entry '%s'") % l)
       
    22 
       
    23     def __call__(self, t, **map):
       
    24         m = self.defaults.copy()
       
    25         m.update(map)
       
    26         try:
       
    27             tmpl = self.cache[t]
       
    28         except KeyError:
       
    29             tmpl = self.cache[t] = file(self.map[t]).read()
       
    30         return self.template(tmpl, self.filters, **m)
       
    31 
       
    32     def template(self, tmpl, filters={}, **map):
       
    33         while tmpl:
       
    34             m = re.search(r"#([a-zA-Z0-9]+)((%[a-zA-Z0-9]+)*)((\|[a-zA-Z0-9]+)*)#", tmpl)
       
    35             if m:
       
    36                 yield tmpl[:m.start(0)]
       
    37                 v = map.get(m.group(1), "")
       
    38                 v = callable(v) and v(**map) or v
       
    39 
       
    40                 format = m.group(2)
       
    41                 fl = m.group(4)
       
    42 
       
    43                 if format:
       
    44                     q = v.__iter__
       
    45                     for i in q():
       
    46                         lm = map.copy()
       
    47                         lm.update(i)
       
    48                         yield self(format[1:], **lm)
       
    49 
       
    50                     v = ""
       
    51 
       
    52                 elif fl:
       
    53                     for f in fl.split("|")[1:]:
       
    54                         v = filters[f](v)
       
    55 
       
    56                 yield v
       
    57                 tmpl = tmpl[m.end(0):]
       
    58             else:
       
    59                 yield tmpl
       
    60                 return
       
    61 
       
    62 def age(x):
       
    63     def plural(t, c):
       
    64         if c == 1:
       
    65             return t
       
    66         return t + "s"
       
    67     def fmt(t, c):
       
    68         return "%d %s" % (c, plural(t, c))
       
    69 
       
    70     now = time.time()
       
    71     then = x[0]
       
    72     delta = max(1, int(now - then))
       
    73 
       
    74     scales = [["second", 1],
       
    75               ["minute", 60],
       
    76               ["hour", 3600],
       
    77               ["day", 3600 * 24],
       
    78               ["week", 3600 * 24 * 7],
       
    79               ["month", 3600 * 24 * 30],
       
    80               ["year", 3600 * 24 * 365]]
       
    81 
       
    82     scales.reverse()
       
    83 
       
    84     for t, s in scales:
       
    85         n = delta / s
       
    86         if n >= 2 or s == 1:
       
    87             return fmt(t, n)
       
    88 
       
    89 def nl2br(text):
       
    90     return text.replace('\n', '<br/>\n')
       
    91 
       
    92 def obfuscate(text):
       
    93     return ''.join(['&#%d;' % ord(c) for c in text])
       
    94 
       
    95 common_filters = {
       
    96     "escape": lambda x: cgi.escape(x, True),
       
    97     "urlescape": urllib.quote,
       
    98     "strip": lambda x: x.strip(),
       
    99     "age": age,
       
   100     "date": lambda x: util.datestr(x),
       
   101     "addbreaks": nl2br,
       
   102     "obfuscate": obfuscate,
       
   103     "short": (lambda x: x[:12]),
       
   104     "firstline": (lambda x: x.splitlines(1)[0]),
       
   105     "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"),
       
   106     "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
       
   107     }