[ resent ]
On Thu, Apr 23, 2009 at 08:06:28PM -0500, Manoj Srivastava wrote:
> >> I suspect the answer might be to get a working implementation out
> >> in the wild (it does not have to be packages.d.o or anything
> >> official -- even a standalone software that takes the output from
> >> grep-dctrl or parses a Packages file will suffice)
> > Would you consider the tasks pages I announced yesterday [1] as
> > such an implementation.
> Sure. It would be great to have another implementation, perhaps
> one that people can play with (something that, for example, one can
> pipe the output of a grep-dctrl command to, and get an html snippet
> from (hey, that can then be packaged as an ikiwiki plugin).
Please find one attached as the script "render-dctrl". Sample usage:
grep-available -s Package,Depends,Description ocaml | render-dctrl > packages.html
Sample "packages.html" (obtained with the command above) is available
at [1]. To run it you will need python-debian and python-markdown. The
script will be shipped as an example of python-debian starting from
the next release [2].
I've on purpose not looked at Andreas implementation, in order to see
if we have mutually thought at different issues. That also means that
it can be utterly buggy, you have been warned :-)
Already in the attached sample output you can find what I believe will
be the most problematic issue to deal with (see the
libocamlbricks-ocaml-dev package). Namely: not-indented multi-line
list items which are not surrounded by blank lines. Arguably though, a
long description using a list as in the libocamlbricks-ocaml-dev
package is already "horrible" per se, and deserves to be fixed no
matter what. The interesting snippet is as follows:
> Library OCaml which provide a set of needed and useful macros for developing.
> Modules and functionality are the follows :
> .
> - Configuration_files: Allow to get information from configuration files
> - Environments: Environments are useful for maintaining the state, intendend
> as a set of bindings, of a user interaction with a GUI
> - FilenameExtra: Additional features for the standard module Filename
Cheers.
[1] http://upsilon.cc/~zack/stuff/packages.html
[2] http://git.debian.org/?p=pkg-python-debian/python-debian.git;a=commit;h=b90ffafd6a1806ab7e3e7620d1675a53ae38e66e
PS mail like this one of mine should be better stored in the log of a
bug report against the policy, to keep track of the
status.
Andreas: do we have one already? If not, can you please
submit it with references to the thread? ... or else shout and
I'll do that.
--
Stefano Zacchiroli -o- PhD in Computer Science \ PostDoc @ Univ. Paris 7
zack@{upsilon.cc,pps.jussieu.fr,debian.org} -<>- http://upsilon.cc/zack/
Dietro un grande uomo c'è ..| . |. Et ne m'en veux pas si je te tutoie
sempre uno zaino ...........| ..: |.... Je dis tu à tous ceux que j'aime
#!/usr/bin/python
# render-dctrl
# Copyright (C) 2009 Stefano Zacchiroli <zack@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()
Attachment:
signature.asc
Description: Digital signature