[python-debian/master] examples/deb822/: add new example render-dctrl
Stefano Zacchiroli
zack at upsilon.cc
Sun Apr 26 16:10:19 UTC 2009
---
debian/changelog | 7 ++
examples/deb822/render-dctrl | 170 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 0 deletions(-)
create mode 100755 examples/deb822/render-dctrl
diff --git a/debian/changelog b/debian/changelog
index 4ef3d7d..8788db4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+python-debian (0.1.14) UNRELEASED; urgency=low
+
+ * examples/deb822/: add new example render-dctrl, to render packages in
+ a dctrl-tools pipeline (using Markdown as long description syntax)
+
+ -- Stefano Zacchiroli <zack at debian.org> Sun, 26 Apr 2009 18:08:50 +0200
+
python-debian (0.1.13) unstable; urgency=low
[ John Wright ]
diff --git a/examples/deb822/render-dctrl b/examples/deb822/render-dctrl
new file mode 100755
index 0000000..19d48d2
--- /dev/null
+++ b/examples/deb822/render-dctrl
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+
+# render-dctrl
+# Copyright (C) 2009 Stefano Zacchiroli <zack at debian.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# Requirements (Debian packages): python-debian python-markdown
+
+usage = """Usage: render-dctrl [OPTION ...] [FILE ...]
+
+Render a 822-like listing of Debian packages (AKA "Packages" file) to
+XHTML, rendering (long) descriptions as Markdown text. Render text
+coming from FILEs, if given, or from standard input otherwise. Typical
+usage is within a dctrl-tools pipeline, example:
+
+ grep-available -s Package,Depends,Description ocaml | render-dctrl > foo.html
+
+Warning: beware of #525525 and thus avoid using "-s Description" alone."""
+
+import re
+import string
+import sys
+from debian_bundle import deb822
+from markdown import markdown
+from optparse import OptionParser
+
+options = None # global, for cmdline options
+
+css = """
+body { font-family: sans-serif; }
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-bottom: 5pt;
+}
+div.package {
+ border: solid 1pt;
+ margin-top: 10pt;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+.raw {
+ font-family: monospace;
+ background: #ddd;
+ padding-left: 2pt;
+ padding-right: 2pt;
+}
+.shortdesc {
+ text-decoration: underline;
+ margin-bottom: 5pt;
+ display: block;
+}
+.longdesc {
+ background: #eee;
+}
+span.package {
+ font-family: monospace;
+ font-size: 110%;
+}
+.uid {
+ float: right;
+ font-size: x-small;
+ padding-right: 10pt;
+}
+"""
+html_header = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style type="text/css">%s</style>
+ </head>
+ <body>
+""" % css
+html_trailer = """ </body>
+</html>
+"""
+
+mdwn_list_line = re.compile(r'^(\s*)[\*\+\-]') # Markdown list item line
+# mdwn_head_line = re.compile(r'^(\s*)#') # Markdown header
+padding = re.compile(r'^(\s*)')
+
+def get_indent(s):
+ m = padding.match(s)
+ if m:
+ return len(m.group(1))
+ else:
+ return 0
+
+def render_longdesc(lines):
+ print '<div class="longdesc">'
+ lines = map(lambda s: s[1:], lines) # strip 822 heading space
+ curpara, paragraphs = [], []
+ inlist, listindent = False, 0
+ store_para = lambda: paragraphs.append(string.join(curpara, '\n') + '\n')
+
+ for l in lines: # recognize Markdown paragraphs
+ if l.rstrip() == '.': # RULE 1: split paragraphs at Debian's "."
+ store_para()
+ curpara, inlist, listindent = [], False, 0
+ else:
+ m = mdwn_list_line.match(l)
+ if not inlist and m and curpara:
+ # RULE 2: handle list item *not* at paragraph beginning
+ store_para() # => start a new paragraph
+ curpara, inlist, listindent = [l], True, get_indent(l)
+ elif inlist and get_indent(l) <= listindent:
+ # RULE 3: leave list when indentation decreases
+ store_para() # => start a new paragraph
+ curpara, inlist, listindent = [l], False, 0
+ else:
+ curpara.append(l)
+
+ for p in paragraphs: # render paragraphs
+ print markdown(p)
+ print '</div>'
+
+def render_field(field, val):
+ field = field.lower()
+ print '<dt>%s</dt>' % field
+ print '<dd class="%s">' % field
+ if field == 'description':
+ lines = val.split('\n')
+ print '<span class="shortdesc">%s</span>' % lines[0]
+ render_longdesc(lines[1:])
+ elif field == 'package':
+ print '<a href="#%s" class="uid">id</a>' % val
+ print '<span id="%s" class="package">%s</span>' % (val, val)
+ elif field in []: # fields not to be typeset as "raw"
+ print '<span class="%s">%s</span>' % (field, val)
+ else:
+ print '<span class="raw">%s</span>' % val
+ print '</dd>'
+
+def render_file(f):
+ global options, html_header, html_trailer
+
+ if options.print_header:
+ print html_header
+ for pkg in deb822.Packages.iter_paragraphs(f):
+ print '<div class="package">'
+ print '<dl class="fields">'
+ for (field, val) in pkg.iteritems():
+ render_field(field, val)
+ print '</dl>'
+ print '</div>\n'
+ if options.print_header:
+ print html_trailer
+
+def main():
+ global options, usage
+
+ parser = OptionParser(usage=usage)
+ parser.add_option("-n", "--no-headers",
+ action="store_false", dest="print_header", default=True,
+ help="suppress printing of HTML header/trailer")
+ (options, args) = parser.parse_args()
+ if len(args):
+ for fname in args:
+ render_file(open(fname))
+ else:
+ render_file(sys.stdin)
+
+if __name__ == '__main__':
+ main()
--
1.5.6.5
More information about the pkg-python-debian-commits
mailing list