add changelog style to command line template.
to use, "hg log --style=changelog". makes different output with no
flags, -q, -v, --debug.
templater module has new template filters for this.
email - committer email address
fill68 - refill text to 68 colums
fill76 - refill text to 76 colums
tabindent - prefix every not empty line with tab
shortdate - iso 8631 date, no time zone
stringify - turn template iterator into string
--- a/mercurial/templater.py Tue Mar 21 15:33:29 2006 +0100
+++ b/mercurial/templater.py Tue Mar 21 23:29:21 2006 -0800
@@ -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/util.py Tue Mar 21 15:33:29 2006 +0100
+++ b/mercurial/util.py Tue Mar 21 23:29:21 2006 -0800
@@ -744,15 +744,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 Tue Mar 21 23:29:21 2006 -0800
@@ -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* '