[libvirt] [PATCH] Fix API doc extractor to stop munging comment formatting

The python method help docs are copied across from the C funtion comments, but in the process all line breaks and indentation was being lost. This made the resulting text and code examples completely unreadable. Both the API doc extractor and the python generator were destroying whitespace & this fixes them to preserve it exactly. * docs/apibuild.py: Preserve all whitespace when extracting function comments. Print function comment inside a <![CDATA[ section to fully preserve all whitespace. Look for the word 'returns' to describe return values, instead of 'return' to avoid getting confused with code examples including the C 'return' statement. * python/generator.py: Preserve all whitespace when printing function help docs * src/libvirt.c: Change any return parameter indicated by 'return' to be 'returns', to avoid confusing the API extractor --- docs/apibuild.py | 31 +++++++++++++++++++--------- python/generator.py | 25 ++++++++++++----------- src/libvirt.c | 54 +++++++++++++++++++++++++------------------------- 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index 855569b..70a7efc 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -838,14 +838,20 @@ class CParser: arg, name)) while len(lines) > 0 and lines[0] == '*': del lines[0] - desc = "" + desc = None while len(lines) > 0: l = lines[0] - while len(l) > 0 and l[0] == '*': - l = l[1:] - l = string.strip(l) - if len(l) >= 6 and l[0:6] == "return" or l[0:6] == "Return": - try: + i = 0 + # Remove all leading '*', followed by at most one ' ' character + # since we need to preserve correct identation of code examples + while i < len(l) and l[i] == '*': + i = i + 1 + if i > 0: + if i < len(l) and l[i] == ' ': + i = i + 1 + l = l[i:] + if len(l) >= 6 and l[0:7] == "returns" or l[0:7] == "Returns": + try: l = string.split(l, ' ', 1)[1] except: l = "" @@ -859,9 +865,14 @@ class CParser: retdesc = retdesc + " " + l del lines[0] else: - desc = desc + " " + l + if desc is not None: + desc = desc + "\n" + l + else: + desc = l del lines[0] + if desc is None: + desc = "" retdesc = string.strip(retdesc) desc = string.strip(desc) @@ -1716,7 +1727,7 @@ class docBuilder: try: (args, desc) = id.info if desc != None and desc != "": - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc)) self.indexString(name, desc) for arg in args: (name, desc) = arg @@ -1760,7 +1771,7 @@ class docBuilder: try: desc = id.extra if desc != None and desc != "": - output.write(">\n <info>%s</info>\n" % (escape(desc))) + output.write(">\n <info><![CDATA[%s]]></info>\n" % (desc)) output.write(" </typedef>\n") else: output.write("/>\n") @@ -1796,7 +1807,7 @@ class docBuilder: output.write(" <cond>%s</cond>\n"% (apstr)); try: (ret, params, desc) = id.info - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc)) self.indexString(name, desc) if ret[0] != None: if ret[0] == "void": diff --git a/python/generator.py b/python/generator.py index c34cb34..178a415 100755 --- a/python/generator.py +++ b/python/generator.py @@ -44,6 +44,7 @@ if sgmlop: self.finish_starttag = target.start self.finish_endtag = target.end self.handle_data = target.data + self.handle_cdata = target.cdata # activate parser self.parser = sgmlop.XMLParser() @@ -78,6 +79,7 @@ class SlowParser(xmllib.XMLParser): def __init__(self, target): self.unknown_starttag = target.start self.handle_data = target.data + self.handle_cdata = target.cdata self.unknown_endtag = target.end xmllib.XMLParser.__init__(self) @@ -108,6 +110,11 @@ class docParser: print "data %s" % text self._data.append(text) + def cdata(self, text): + if debug: + print "data %s" % text + self._data.append(text) + def start(self, tag, attrs): if debug: print "start %s, %s" % (tag, attrs) @@ -843,20 +850,14 @@ def writeDoc(name, args, indent, output): val = string.replace(val, "NULL", "None"); output.write(indent) output.write('"""') - while len(val) > 60: - if val[0] == " ": - val = val[1:] - continue - str = val[0:60] - i = string.rfind(str, " "); - if i < 0: - i = 60 - str = val[0:i] - val = val[i:] + i = string.find(val, "\n") + while i >= 0: + str = val[0:i+1] + val = val[i+1:] output.write(str) - output.write('\n '); + i = string.find(val, "\n") output.write(indent) - output.write(val); + output.write(val) output.write(' """\n') def buildWrappers(): diff --git a/src/libvirt.c b/src/libvirt.c index 441f308..9d4d94b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -818,7 +818,7 @@ virRegisterStateDriver(virStateDriverPtr driver) * * Initialize all virtualization drivers. * - * Return 0 if all succeed, -1 upon any failure. + * Returns 0 if all succeed, -1 upon any failure. */ int virStateInitialize(int privileged) { int i, ret = 0; @@ -839,7 +839,7 @@ int virStateInitialize(int privileged) { * * Run each virtualization driver's cleanup method. * - * Return 0 if all succeed, -1 upon any failure. + * Returns 0 if all succeed, -1 upon any failure. */ int virStateCleanup(void) { int i, ret = 0; @@ -857,7 +857,7 @@ int virStateCleanup(void) { * * Run each virtualization driver's reload method. * - * Return 0 if all succeed, -1 upon any failure. + * Returns 0 if all succeed, -1 upon any failure. */ int virStateReload(void) { int i, ret = 0; @@ -875,7 +875,7 @@ int virStateReload(void) { * * Run each virtualization driver's "active" method. * - * Return 0 if none are active, 1 if at least one is. + * Returns 0 if none are active, 1 if at least one is. */ int virStateActive(void) { int i, ret = 0; @@ -7044,7 +7044,7 @@ virStoragePoolRef(virStoragePoolPtr pool) * involve communicating with a remote server, and/or initializing * new devices at the OS layer * - * Return 0 if the volume list was refreshed, -1 on failure + * Returns 0 if the volume list was refreshed, -1 on failure */ int virStoragePoolRefresh(virStoragePoolPtr pool, @@ -7089,7 +7089,7 @@ error: * * Fetch the locally unique name of the storage pool * - * Return the name of the pool, or NULL on error + * Returns the name of the pool, or NULL on error */ const char* virStoragePoolGetName(virStoragePoolPtr pool) @@ -7113,7 +7113,7 @@ virStoragePoolGetName(virStoragePoolPtr pool) * * Fetch the globally unique ID of the storage pool * - * Return 0 on success, or -1 on error; + * Returns 0 on success, or -1 on error; */ int virStoragePoolGetUUID(virStoragePoolPtr pool, @@ -7149,7 +7149,7 @@ error: * * Fetch the globally unique ID of the storage pool as a string * - * Return 0 on success, or -1 on error; + * Returns 0 on success, or -1 on error; */ int virStoragePoolGetUUIDString(virStoragePoolPtr pool, @@ -7190,7 +7190,7 @@ error: * Get volatile information about the storage pool * such as free space / usage summary * - * returns 0 on success, or -1 on failure. + * Returns 0 on success, or -1 on failure. */ int virStoragePoolGetInfo(virStoragePoolPtr pool, @@ -7240,7 +7240,7 @@ error: * storage pool. This is suitable for later feeding back * into the virStoragePoolCreateXML method. * - * returns a XML document, or NULL on error + * Returns a XML document, or NULL on error */ char * virStoragePoolGetXMLDesc(virStoragePoolPtr pool, @@ -7287,7 +7287,7 @@ error: * Fetches the value of the autostart flag, which determines * whether the pool is automatically started at boot time * - * return 0 on success, -1 on failure + * Returns 0 on success, -1 on failure */ int virStoragePoolGetAutostart(virStoragePoolPtr pool, @@ -7333,7 +7333,7 @@ error: * * Sets the autostart flag * - * returns 0 on success, -1 on failure + * Returns 0 on success, -1 on failure */ int virStoragePoolSetAutostart(virStoragePoolPtr pool, @@ -7494,7 +7494,7 @@ virStorageVolGetConnect (virStorageVolPtr vol) * Fetch a pointer to a storage volume based on its name * within a pool * - * return a storage volume, or NULL if not found / error + * Returns a storage volume, or NULL if not found / error */ virStorageVolPtr virStorageVolLookupByName(virStoragePoolPtr pool, @@ -7539,7 +7539,7 @@ error: * Fetch a pointer to a storage volume based on its * globally unique key * - * return a storage volume, or NULL if not found / error + * Returns a storage volume, or NULL if not found / error */ virStorageVolPtr virStorageVolLookupByKey(virConnectPtr conn, @@ -7582,7 +7582,7 @@ error: * Fetch a pointer to a storage volume based on its * locally (host) unique path * - * return a storage volume, or NULL if not found / error + * Returns a storage volume, or NULL if not found / error */ virStorageVolPtr virStorageVolLookupByPath(virConnectPtr conn, @@ -7625,7 +7625,7 @@ error: * Fetch the storage volume name. This is unique * within the scope of a pool * - * return the volume name, or NULL on error + * Returns the volume name, or NULL on error */ const char* virStorageVolGetName(virStorageVolPtr vol) @@ -7650,7 +7650,7 @@ virStorageVolGetName(virStorageVolPtr vol) * unique, so the same volume will have the same * key no matter what host it is accessed from * - * return the volume key, or NULL on error + * Returns the volume key, or NULL on error */ const char* virStorageVolGetKey(virStorageVolPtr vol) @@ -7677,7 +7677,7 @@ virStorageVolGetKey(virStorageVolPtr vol) * on an XML description. Not all pools support * creation of volumes * - * return the storage volume, or NULL on error + * Returns the storage volume, or NULL on error */ virStorageVolPtr virStorageVolCreateXML(virStoragePoolPtr pool, @@ -7727,7 +7727,7 @@ error: * volume (name, perms) are passed via a typical volume * XML description. * - * return the storage volume, or NULL on error + * Returns the storage volume, or NULL on error */ virStorageVolPtr virStorageVolCreateXMLFrom(virStoragePoolPtr pool, @@ -7781,7 +7781,7 @@ error: * * Delete the storage volume from the pool * - * Return 0 on success, or -1 on error + * Returns 0 on success, or -1 on error */ int virStorageVolDelete(virStorageVolPtr vol, @@ -7827,7 +7827,7 @@ error: * Release the storage volume handle. The underlying * storage volume continues to exist. * - * Return 0 on success, or -1 on error + * Returns 0 on success, or -1 on error */ int virStorageVolFree(virStorageVolPtr vol) @@ -7885,7 +7885,7 @@ virStorageVolRef(virStorageVolPtr vol) * Fetches volatile information about the storage * volume such as its current allocation * - * Return 0 on success, or -1 on failure + * Returns 0 on success, or -1 on failure */ int virStorageVolGetInfo(virStorageVolPtr vol, @@ -7934,7 +7934,7 @@ error: * Fetch an XML document describing all aspects of * the storage volume * - * Return the XML document, or NULL on error + * Returns the XML document, or NULL on error */ char * virStorageVolGetXMLDesc(virStorageVolPtr vol, @@ -8165,7 +8165,7 @@ error: * Fetch an XML document describing all aspects of * the device. * - * Return the XML document, or NULL on error + * Returns the XML document, or NULL on error */ char *virNodeDeviceGetXMLDesc(virNodeDevicePtr dev, unsigned int flags) { @@ -9381,7 +9381,7 @@ virSecretRef(virSecretPtr secret) * * Release the secret handle. The underlying secret continues to exist. * - * Return 0 on success, or -1 on error + * Returns 0 on success, or -1 on error */ int virSecretFree(virSecretPtr secret) @@ -9852,7 +9852,7 @@ cleanup: * used in conjunction with non-blocking data streams * to integrate into an event loop * - * Return 0 on success, -1 upon error + * Returns 0 on success, -1 upon error */ int virStreamEventAddCallback(virStreamPtr stream, int events, @@ -9934,7 +9934,7 @@ error: * * Remove a event callback from the stream * - * Return 0 on success, -1 on error + * Returns 0 on success, -1 on error */ int virStreamEventRemoveCallback(virStreamPtr stream) { -- 1.6.2.5

On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote:
The python method help docs are copied across from the C funtion comments, but in the process all line breaks and indentation was being lost. This made the resulting text and code examples completely unreadable. Both the API doc extractor and the python generator were destroying whitespace & this fixes them to preserve it exactly.
I meant to include an example of the difference when I sent this. eg, launch python, type 'import libvirt' and then 'help(libvirt)'. For the 'migrate' API currently you see | migrate(self, domain, flags, dname, uri, bandwidth) | Migrate the domain object from its current host to the | destination host given by dconn (a connection to the | destination host). Flags may be one of more of the | following: VIR_MIGRATE_LIVE Attempt a live migration. If | a hypervisor supports renaming domains during migration, | then you may set the dname parameter to the new name | (otherwise it keeps the same name). If this is not | supported by the hypervisor, dname must be None or else you | will get an error. Since typically the two hypervisors | connect directly to each other in order to perform the | migration, you may need to specify a path from the source | to the destination. This is the purpose of the uri | parameter. If uri is None, then libvirt will try to find | the best method. Uri may specify the hostname or IP | address of the destination host as seen from the source. | Or uri may be a URI giving transport, hostname, user, port, | etc. in the usual form. Refer to driver documentation for | the particular URIs supported. The maximum bandwidth (in | Mbps) that will be used to do migration can be specified | with the bandwidth parameter. If set to 0, libvirt will | choose a suitable default. Some hypervisors do not support | this feature and will return an error if bandwidth is not | 0. To see which features are supported by the current | hypervisor, see virConnectGetCapabilities, | /capabilities/host/migration_features. There are many | limitations on migration imposed by the underlying | technology - for example it may not be possible to migrate | between different processors even with the same | architecture, or between different types of hypervisor. After my patch you get | migrate(self, domain, flags, dname, uri, bandwidth) | Migrate the domain object from its current host to the destination | host given by dconn (a connection to the destination host). | | Flags may be one of more of the following: | VIR_MIGRATE_LIVE Attempt a live migration. | | If a hypervisor supports renaming domains during migration, | then you may set the dname parameter to the new name (otherwise | it keeps the same name). If this is not supported by the | hypervisor, dname must be None or else you will get an error. | | Since typically the two hypervisors connect directly to each | other in order to perform the migration, you may need to specify | a path from the source to the destination. This is the purpose | of the uri parameter. If uri is None, then libvirt will try to | find the best method. Uri may specify the hostname or IP address | of the destination host as seen from the source. Or uri may be | a URI giving transport, hostname, user, port, etc. in the usual | form. Refer to driver documentation for the particular URIs | supported. | | The maximum bandwidth (in Mbps) that will be used to do migration | can be specified with the bandwidth parameter. If set to 0, | libvirt will choose a suitable default. Some hypervisors do | not support this feature and will return an error if bandwidth | is not 0. | | To see which features are supported by the current hypervisor, | see virConnectGetCapabilities, /capabilities/host/migration_features. | | There are many limitations on migration imposed by the underlying | technology - for example it may not be possible to migrate between | different processors even with the same architecture, or between | different types of hypervisor. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote:
The python method help docs are copied across from the C funtion comments, but in the process all line breaks and indentation was being lost. This made the resulting text and code examples completely unreadable. Both the API doc extractor and the python generator were destroying whitespace & this fixes them to preserve it exactly.
* docs/apibuild.py: Preserve all whitespace when extracting function comments. Print function comment inside a <![CDATA[ section to fully preserve all whitespace. Look for the word 'returns' to describe return values, instead of 'return' to avoid getting confused with code examples including the C 'return' statement. * python/generator.py: Preserve all whitespace when printing function help docs * src/libvirt.c: Change any return parameter indicated by 'return' to be 'returns', to avoid confusing the API extractor [...] if desc != None and desc != "": - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc))
Ah, okay you're using CDATA !
self.indexString(name, desc) for arg in args: (name, desc) = arg @@ -1760,7 +1771,7 @@ class docBuilder: try: desc = id.extra if desc != None and desc != "": - output.write(">\n <info>%s</info>\n" % (escape(desc))) + output.write(">\n <info><![CDATA[%s]]></info>\n" % (desc)) output.write(" </typedef>\n") else: output.write("/>\n") @@ -1796,7 +1807,7 @@ class docBuilder: output.write(" <cond>%s</cond>\n"% (apstr)); try: (ret, params, desc) = id.info - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc)) self.indexString(name, desc) if ret[0] != None: if ret[0] == "void": diff --git a/python/generator.py b/python/generator.py index c34cb34..178a415 100755 --- a/python/generator.py +++ b/python/generator.py @@ -44,6 +44,7 @@ if sgmlop: self.finish_starttag = target.start self.finish_endtag = target.end self.handle_data = target.data + self.handle_cdata = target.cdata
# activate parser self.parser = sgmlop.XMLParser() @@ -78,6 +79,7 @@ class SlowParser(xmllib.XMLParser): def __init__(self, target): self.unknown_starttag = target.start self.handle_data = target.data + self.handle_cdata = target.cdata self.unknown_endtag = target.end xmllib.XMLParser.__init__(self)
@@ -108,6 +110,11 @@ class docParser: print "data %s" % text self._data.append(text)
+ def cdata(self, text): + if debug: + print "data %s" % text + self._data.append(text) + def start(self, tag, attrs):
Okay makes sense, plus the large amount of return -> Returns changes ACK ! I'm still waiting to see what this gives in the HTML docs :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Fri, Sep 25, 2009 at 03:33:41PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote:
The python method help docs are copied across from the C funtion comments, but in the process all line breaks and indentation was being lost. This made the resulting text and code examples completely unreadable. Both the API doc extractor and the python generator were destroying whitespace & this fixes them to preserve it exactly.
* docs/apibuild.py: Preserve all whitespace when extracting function comments. Print function comment inside a <![CDATA[ section to fully preserve all whitespace. Look for the word 'returns' to describe return values, instead of 'return' to avoid getting confused with code examples including the C 'return' statement. * python/generator.py: Preserve all whitespace when printing function help docs * src/libvirt.c: Change any return parameter indicated by 'return' to be 'returns', to avoid confusing the API extractor [...] if desc != None and desc != "": - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc))
Ah, okay you're using CDATA !
self.indexString(name, desc) for arg in args: (name, desc) = arg @@ -1760,7 +1771,7 @@ class docBuilder: try: desc = id.extra if desc != None and desc != "": - output.write(">\n <info>%s</info>\n" % (escape(desc))) + output.write(">\n <info><![CDATA[%s]]></info>\n" % (desc)) output.write(" </typedef>\n") else: output.write("/>\n") @@ -1796,7 +1807,7 @@ class docBuilder: output.write(" <cond>%s</cond>\n"% (apstr)); try: (ret, params, desc) = id.info - output.write(" <info>%s</info>\n" % (escape(desc))) + output.write(" <info><![CDATA[%s]]></info>\n" % (desc)) self.indexString(name, desc) if ret[0] != None: if ret[0] == "void": diff --git a/python/generator.py b/python/generator.py index c34cb34..178a415 100755 --- a/python/generator.py +++ b/python/generator.py @@ -44,6 +44,7 @@ if sgmlop: self.finish_starttag = target.start self.finish_endtag = target.end self.handle_data = target.data + self.handle_cdata = target.cdata
# activate parser self.parser = sgmlop.XMLParser() @@ -78,6 +79,7 @@ class SlowParser(xmllib.XMLParser): def __init__(self, target): self.unknown_starttag = target.start self.handle_data = target.data + self.handle_cdata = target.cdata self.unknown_endtag = target.end xmllib.XMLParser.__init__(self)
@@ -108,6 +110,11 @@ class docParser: print "data %s" % text self._data.append(text)
+ def cdata(self, text): + if debug: + print "data %s" % text + self._data.append(text) + def start(self, tag, attrs):
Okay makes sense, plus the large amount of return -> Returns changes
ACK !
I'm still waiting to see what this gives in the HTML docs :-)
Hmm, I didn't check that yet, but I guess it shouldn't make any difference, since the HTML will still collapse the whitespace as before - we'd need to insert real <p> breaks & use <pre> during generation of the HTML if we wanted to maintain any kind of sane formatting Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, Sep 25, 2009 at 02:42:47PM +0100, Daniel P. Berrange wrote:
On Fri, Sep 25, 2009 at 03:33:41PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote: I'm still waiting to see what this gives in the HTML docs :-)
Hmm, I didn't check that yet, but I guess it shouldn't make any difference, since the HTML will still collapse the whitespace as before - we'd need to insert real <p> breaks & use <pre> during generation of the HTML if we wanted to maintain any kind of sane formatting
it can be a bit nasty, plus there is some xslt processing :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Fri, Sep 25, 2009 at 03:58:34PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 02:42:47PM +0100, Daniel P. Berrange wrote:
On Fri, Sep 25, 2009 at 03:33:41PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote: I'm still waiting to see what this gives in the HTML docs :-)
Hmm, I didn't check that yet, but I guess it shouldn't make any difference, since the HTML will still collapse the whitespace as before - we'd need to insert real <p> breaks & use <pre> during generation of the HTML if we wanted to maintain any kind of sane formatting
it can be a bit nasty, plus there is some xslt processing :-)
It didn't make the HTML any worse than it is already, so I'll commit this current improvement & we can think about HTML later Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Sep 28, 2009 at 01:42:05PM +0100, Daniel P. Berrange wrote:
On Fri, Sep 25, 2009 at 03:58:34PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 02:42:47PM +0100, Daniel P. Berrange wrote:
On Fri, Sep 25, 2009 at 03:33:41PM +0200, Daniel Veillard wrote:
On Fri, Sep 25, 2009 at 01:28:51PM +0100, Daniel P. Berrange wrote: I'm still waiting to see what this gives in the HTML docs :-)
Hmm, I didn't check that yet, but I guess it shouldn't make any difference, since the HTML will still collapse the whitespace as before - we'd need to insert real <p> breaks & use <pre> during generation of the HTML if we wanted to maintain any kind of sane formatting
it can be a bit nasty, plus there is some xslt processing :-)
It didn't make the HTML any worse than it is already, so I'll commit this current improvement & we can think about HTML later
Sure, no problem ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard