merge with self
authorBenoit Boissinot <benoit.boissinot@ens-lyon.org>
Thu, 23 Mar 2006 23:55:51 +0100
changeset 1991 a8a618c57690
parent 1990 4b0535c678d6 (current diff)
parent 1989 0541768fa558 (diff)
child 1992 ea8345a7a29d
merge with self
mercurial/util.py
--- a/mercurial/templater.py	Thu Mar 23 23:39:53 2006 +0100
+++ b/mercurial/templater.py	Thu Mar 23 23:55:51 2006 +0100
@@ -8,7 +8,7 @@
 import re
 from demandload import demandload
 from i18n import gettext as _
-demandload(globals(), "cStringIO cgi sys os time urllib util")
+demandload(globals(), "cStringIO cgi re sys os time urllib util textwrap")
 
 esctable = {
     '\\': '\\',
@@ -181,8 +181,43 @@
         if n >= 2 or s == 1:
             return fmt(t, n)
 
+def stringify(thing):
+    '''turn nested template iterator into string.'''
+    cs = cStringIO.StringIO()
+    def walk(things):
+        for t in things:
+            if hasattr(t, '__iter__'):
+                walk(t)
+            else:
+                cs.write(t)
+    walk(thing)
+    return cs.getvalue()
+
+para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
+space_re = re.compile(r'  +')
+
+def fill(text, width):
+    '''fill many paragraphs.'''
+    def findparas():
+        start = 0
+        while True:
+            m = para_re.search(text, start)
+            if not m:
+                w = len(text)
+                while w > start and text[w-1].isspace(): w -= 1
+                yield text[start:w], text[w:]
+                break
+            yield text[start:m.start(0)], m.group(1)
+            start = m.end(1)
+            
+    fp = cStringIO.StringIO()
+    for para, rest in findparas():
+        fp.write(space_re.sub(' ', textwrap.fill(para, width)))
+        fp.write(rest)
+    return fp.getvalue()
+
 def isodate(date):
-    '''turn a (timestamp, tzoff) tuple into an iso 8631 date.'''
+    '''turn a (timestamp, tzoff) tuple into an iso 8631 date and time.'''
     return util.datestr(date, format='%Y-%m-%d %H:%M')
 
 def nl2br(text):
@@ -201,25 +236,54 @@
     if f >= 0: author = author[:f]
     return author
 
+def email(author):
+    '''get email of author.'''
+    r = author.find('>')
+    if r == -1: r = None
+    return author[author.find('<')+1:r]
+    
 def person(author):
     '''get name of author, or else username.'''
     f = author.find('<')
     if f == -1: return util.shortuser(author)
     return author[:f].rstrip()
 
+def shortdate(date):
+    '''turn (timestamp, tzoff) tuple into iso 8631 date.'''
+    return util.datestr(date, format='%Y-%m-%d', timezone=False)
+
+def indent(text, prefix):
+    '''indent each non-empty line of text after first with prefix.'''
+    fp = cStringIO.StringIO()
+    lines = text.splitlines()
+    num_lines = len(lines)
+    for i in xrange(num_lines):
+        l = lines[i]
+        if i and l.strip(): fp.write(prefix)
+        fp.write(l)
+        if i < num_lines - 1 or text.endswith('\n'):
+            fp.write('\n')
+    return fp.getvalue()
+
 common_filters = {
     "addbreaks": nl2br,
     "age": age,
     "date": lambda x: util.datestr(x),
     "domain": domain,
+    "email": email,
     "escape": lambda x: cgi.escape(x, True),
+    "fill68": lambda x: fill(x, width=68),
+    "fill76": lambda x: fill(x, width=76),
     "firstline": lambda x: x.splitlines(1)[0].rstrip('\r\n'),
+    "tabindent": lambda x: indent(x, '\t'),
     "isodate": isodate,
     "obfuscate": obfuscate,
     "permissions": lambda x: x and "-rwxr-xr-x" or "-rw-r--r--",
     "person": person,
     "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
     "short": lambda x: x[:12],
+    "shortdate": shortdate,
+    "stringify": stringify,
     "strip": lambda x: x.strip(),
     "urlescape": lambda x: urllib.quote(x),
     "user": lambda x: util.shortuser(x),
--- a/mercurial/ui.py	Thu Mar 23 23:39:53 2006 +0100
+++ b/mercurial/ui.py	Thu Mar 23 23:55:51 2006 +0100
@@ -8,7 +8,7 @@
 import ConfigParser
 from i18n import gettext as _
 from demandload import *
-demandload(globals(), "os re socket sys util tempfile")
+demandload(globals(), "errno os re socket sys tempfile util")
 
 class ui(object):
     def __init__(self, verbose=False, debug=False, quiet=False,
@@ -179,9 +179,13 @@
             sys.stdout.write(str(a))
 
     def write_err(self, *args):
-        if not sys.stdout.closed: sys.stdout.flush()
-        for a in args:
-            sys.stderr.write(str(a))
+        try:
+            if not sys.stdout.closed: sys.stdout.flush()
+            for a in args:
+                sys.stderr.write(str(a))
+        except IOError, inst:
+            if inst.errno != errno.EPIPE:
+                raise
 
     def flush(self):
         try:
--- a/mercurial/util.py	Thu Mar 23 23:39:53 2006 +0100
+++ b/mercurial/util.py	Thu Mar 23 23:55:51 2006 +0100
@@ -751,15 +751,16 @@
         tz = time.timezone
     return time.mktime(lt), tz
 
-def datestr(date=None, format='%a %b %d %H:%M:%S %Y'):
+def datestr(date=None, format='%a %b %d %H:%M:%S %Y', timezone=True):
     """represent a (unixtime, offset) tuple as a localized time.
     unixtime is seconds since the epoch, and offset is the time zone's
-    number of seconds away from UTC."""
+    number of seconds away from UTC. if timezone is false, do not
+    append time zone to string."""
     t, tz = date or makedate()
-    return ("%s %+03d%02d" %
-            (time.strftime(format, time.gmtime(float(t) - tz)),
-             -tz / 3600,
-             ((-tz % 3600) / 60)))
+    s = time.strftime(format, time.gmtime(float(t) - tz))
+    if timezone:
+        s += " %+03d%02d" % (-tz / 3600, ((-tz % 3600) / 60))
+    return s
 
 def shortuser(user):
     """Return a short representation of a user name or email address."""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/map-cmdline.changelog	Thu Mar 23 23:55:51 2006 +0100
@@ -0,0 +1,15 @@
+changeset = '{date|shortdate}  {author|person}  <{author|email}>  ({node|short}{tags})\n\n\t* {files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n'
+changeset_quiet = '{date|shortdate}  {author|person}  <{author|email}>\n\n\t* {desc|firstline|fill68|tabindent|strip}\n\n'
+changeset_verbose = '{date|isodate}  {author|person}  <{author|email}>  ({node|short}{tags})\n\n\t* {file_adds|stringify|fill68|tabindent}{file_dels|stringify|fill68|tabindent}{files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n'
+start_tags = ' ['
+tag = '{tag}, '
+last_tag = '{tag}]'
+start_files = '('
+file = '{file}, '
+last_file = '{file}):\n\t'
+start_file_adds = '('
+file_add = '{file_add}, '
+last_file_add = '{file_add}): new file.\n* '
+start_file_dels = '('
+file_del = '{file_del}, '
+last_file_del = '{file_del}): deleted file.\n* '