mirror of
				https://github.com/kastdeur/dotfiles.git
				synced 2025-10-31 03:06:35 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			761 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			761 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/python
 | 
						|
r"""
 | 
						|
db2vim [options] file.xml
 | 
						|
 | 
						|
SHORT OPTIONS
 | 
						|
 | 
						|
-d  Prints some debugging information on stderr.
 | 
						|
 | 
						|
-s  If given, the db2vim operates in a 'stict' conversion mode, i.e, any
 | 
						|
    element which does not have a handler defined for them it be
 | 
						|
    completeley ignored including all its children. Otherwise, db2vim will
 | 
						|
    recurse into an unknown tag and process any of its children it
 | 
						|
    recognizes. Since db2vim always recognizes text nodes, not using this
 | 
						|
    option has the effect that all text will be printed out, even if
 | 
						|
    somewhat incorrectly.
 | 
						|
 | 
						|
LONG OPTIONS
 | 
						|
 | 
						|
--prefix=<prefix> 
 | 
						|
    This is a string like "ls_" which will be prepended to the section
 | 
						|
    numbers. Default to 'ls_' if unsupplied.
 | 
						|
"""
 | 
						|
 | 
						|
 | 
						|
import xml.dom.minidom
 | 
						|
import getopt
 | 
						|
import string
 | 
						|
import re
 | 
						|
import sys
 | 
						|
 | 
						|
# Okay. so I import *. Shoot me.
 | 
						|
from textutils import *
 | 
						|
from domutils import *
 | 
						|
 | 
						|
# define a bunch of constants for formatting.
 | 
						|
TEXT_WIDTH = 80
 | 
						|
BLOCK_QUOTE = 4
 | 
						|
COL_SPACE = 2
 | 
						|
 | 
						|
# a bunch of globals used in creating the Table of contents.
 | 
						|
#
 | 
						|
# TOC_HASH['section 1.1 label'] = 'ls_1_1'
 | 
						|
#
 | 
						|
# LEVEL_HASH['section 1.1 label'] = 1 
 | 
						|
#       (top level article has level 0)
 | 
						|
#
 | 
						|
# TITLE_HASH['section 1.1 label'] = 'Title of section 1.1'
 | 
						|
#
 | 
						|
# FILENAME = the name of the file being processed with the last extension
 | 
						|
#            changed to .txt
 | 
						|
#
 | 
						|
# TOC_PREFIX = 'ls_' (the prefix used to create the section labels).
 | 
						|
TOC_HASH = {}
 | 
						|
LEVEL_HASH = {}
 | 
						|
TITLE_HASH = {}
 | 
						|
FILENAME = ''
 | 
						|
TOC_PREFIX = ''
 | 
						|
 | 
						|
ANCHOR_HASH = {}
 | 
						|
URL_HASH = {}
 | 
						|
 | 
						|
# STDERR for printing debugging info.
 | 
						|
DEBUG = 0
 | 
						|
STDERR = sys.stderr
 | 
						|
STRICT = 0
 | 
						|
NUM_ANCHORS = {0:1}
 | 
						|
 | 
						|
################################################################################
 | 
						|
# Miscellaneous utility functions
 | 
						|
################################################################################
 | 
						|
# encodeTo52(num) {{{
 | 
						|
def encodeTo52(num):
 | 
						|
    ret = ''
 | 
						|
 | 
						|
    if num < 26:
 | 
						|
        return unichr(ord('a') + num)
 | 
						|
    elif num < 52:
 | 
						|
        return unichr(ord('A') + num - 26)
 | 
						|
    else:
 | 
						|
        return encodeTo52(int(num/52)) + encodeTo52(num % 52)
 | 
						|
# }}}
 | 
						|
# makeTocHash(rootElement) {{{
 | 
						|
def makeTocHash(rootElement, width, prefix='', level=0):
 | 
						|
    retText = ""
 | 
						|
    sectionsTable = []
 | 
						|
    lastLabelUsed = 0
 | 
						|
 | 
						|
    for section in rootElement.getChildrenByTagName('section'):
 | 
						|
        title = section.getChildrenByTagName('title')[0]
 | 
						|
        titleText = handleElement(title, width)
 | 
						|
        lastLabelUsed += 1
 | 
						|
        thisLabel = TOC_PREFIX + prefix + str(lastLabelUsed)
 | 
						|
 | 
						|
        sectionid = section.getAttribute('id')
 | 
						|
        if not sectionid:
 | 
						|
            section.setAttribute('id', thisLabel)
 | 
						|
            sectionid = thisLabel
 | 
						|
 | 
						|
        NUM_ANCHORS[0] += 1
 | 
						|
        ANCHOR_HASH[sectionid] = TOC_PREFIX + 'a_' + encodeTo52(NUM_ANCHORS[0] + 52)
 | 
						|
 | 
						|
        TOC_HASH[sectionid] = thisLabel
 | 
						|
        LEVEL_HASH[sectionid] = level
 | 
						|
        TITLE_HASH[sectionid] = titleText
 | 
						|
 | 
						|
        if section.getChildrenByTagName('section'):
 | 
						|
            childText = makeTocHash(section, width - 5,
 | 
						|
                prefix = prefix+str(lastLabelUsed) + '_',
 | 
						|
                level = level + 1)
 | 
						|
 | 
						|
# }}}
 | 
						|
# makeAnchorHash(rootElement) {{{
 | 
						|
def makeAnchorHash(rootElement):
 | 
						|
    anchors = rootElement.getElementsByTagName('anchor') + rootElement.getElementsByTagName('note')
 | 
						|
    numAnchors = 0
 | 
						|
    for anchor in anchors:
 | 
						|
        if not anchor.getAttribute('id'):
 | 
						|
            continue
 | 
						|
 | 
						|
        NUM_ANCHORS[0] += 1
 | 
						|
        if ANCHOR_HASH.has_key(anchor.getAttribute('id')) or TOC_HASH.has_key(anchor.getAttribute('id')):
 | 
						|
            print >> STDERR, "Warning: anchor [%s] multiply defined" % anchor.getAttribute('id')
 | 
						|
 | 
						|
        ANCHOR_HASH[anchor.getAttribute('id')] = TOC_PREFIX + 'a_' + encodeTo52(NUM_ANCHORS[0] + 52)
 | 
						|
    
 | 
						|
# }}}
 | 
						|
# makeURLHash(rootElement) {{{
 | 
						|
def makeURLHash(rootElement):
 | 
						|
    urls = rootElement.getElementsByTagName('ulink')
 | 
						|
    numURLs = 0
 | 
						|
    for url in urls:
 | 
						|
        if not url.getAttribute('url') or URL_HASH.has_key(url.getAttribute('url')):
 | 
						|
            continue
 | 
						|
        numURLs += 1
 | 
						|
        URL_HASH[url.getAttribute('url')] = TOC_PREFIX + 'u_' + str(numURLs)
 | 
						|
 | 
						|
# }}}
 | 
						|
# makeTOC(node, width, prefix='', level=0, maxleve=1): {{{
 | 
						|
def makeTOC(node, width, maxlevel=1):
 | 
						|
    retText = ""
 | 
						|
    sectionsTable = []
 | 
						|
    lastLabelUsed = 0
 | 
						|
 | 
						|
    for section in node.getChildrenByTagName('section'):
 | 
						|
 | 
						|
        sectionid = section.getAttribute('id')
 | 
						|
        thisLabel = TOC_HASH.get(sectionid, '')
 | 
						|
        titleText = TITLE_HASH.get(sectionid, '')
 | 
						|
        level = LEVEL_HASH.get(sectionid, 10)
 | 
						|
 | 
						|
        if level <= maxlevel:
 | 
						|
            retText += '|' + thisLabel + '| ' +  titleText + '\n'
 | 
						|
 | 
						|
        if level < maxlevel and section.getChildrenByTagName('section'):
 | 
						|
            childText = makeTOC(section, width-5)
 | 
						|
            retText += VertCatString("    ", 4, childText) + '\n'
 | 
						|
 | 
						|
        retText = re.sub(r'\s+$', r'\n', retText)
 | 
						|
 | 
						|
    return retText
 | 
						|
# }}}
 | 
						|
 | 
						|
################################################################################
 | 
						|
# Generalized function for handling dom elements.
 | 
						|
################################################################################
 | 
						|
# IsInlineTag(self): {{{
 | 
						|
def IsInlineTag(self):
 | 
						|
    if self.nodeType == self.TEXT_NODE:
 | 
						|
        return 1
 | 
						|
    elif inlineTags.get(self.tagName, 0):
 | 
						|
        return 1
 | 
						|
    else:
 | 
						|
        return 0
 | 
						|
 | 
						|
 | 
						|
# }}}
 | 
						|
# getChildrenByTagName(self, name): {{{
 | 
						|
# Description: extension to the xml.dom.minidom.Element class.
 | 
						|
#              returns all direct descendants of this Element.
 | 
						|
def getChildrenByTagName(self, name):
 | 
						|
    nodeList = []
 | 
						|
 | 
						|
    child = self.firstChild
 | 
						|
    while not child is None:
 | 
						|
        if child.nodeType == child.ELEMENT_NODE and child.nodeName == name:
 | 
						|
            nodeList.append(child)
 | 
						|
 | 
						|
        child = child.nextSibling
 | 
						|
 | 
						|
    return nodeList
 | 
						|
 | 
						|
xml.dom.minidom.Element.getChildrenByTagName = getChildrenByTagName
 | 
						|
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleElement(rootElement, width=TEXT_WIDTH): {{{
 | 
						|
def handleElement(rootElement, width=TEXT_WIDTH):
 | 
						|
    """
 | 
						|
    handleElement(rootElement, width=TEXT_WIDTH):
 | 
						|
 | 
						|
    Generalized function to handle an Element node in a DOM tree.
 | 
						|
    """
 | 
						|
 | 
						|
    retText = ""
 | 
						|
    child = rootElement.firstChild
 | 
						|
    while not child is None:
 | 
						|
 | 
						|
        printerr('node type = %d' % child.nodeType)
 | 
						|
        if child.nodeType == child.ELEMENT_NODE:
 | 
						|
            printerr('processing [%s]' % child.tagName)
 | 
						|
 | 
						|
        isinline = IsInlineTag(child)
 | 
						|
 | 
						|
        # if the child is an Element and if a handler exists, then call it.
 | 
						|
        if not isinline \
 | 
						|
        and child.nodeType == child.ELEMENT_NODE \
 | 
						|
        and handlerMaps.has_key(child.tagName):
 | 
						|
            # offset the child text by the current indentation value
 | 
						|
            printerr('making recursive call to known child.')
 | 
						|
            retText += handlerMaps[child.tagName](child, width)
 | 
						|
            child = child.nextSibling
 | 
						|
 | 
						|
        elif not isinline \
 | 
						|
        and child.nodeType == child.PROCESSING_INSTRUCTION_NODE \
 | 
						|
        and child.target == 'vimhelp':
 | 
						|
 | 
						|
            if handlerMaps.has_key(child.data):
 | 
						|
                retText += handlerMaps[child.data](child, width)
 | 
						|
 | 
						|
            child = child.nextSibling
 | 
						|
 | 
						|
        # if its a text node or an inline element node, collect consecutive
 | 
						|
        # text nodes into a single paragraph and indent it.
 | 
						|
        elif isinline:
 | 
						|
 | 
						|
            text = ""
 | 
						|
            while not child is None and IsInlineTag(child):
 | 
						|
                if child.nodeType == child.TEXT_NODE:
 | 
						|
                    text += child.data
 | 
						|
                elif child.nodeType == child.ELEMENT_NODE:
 | 
						|
                    if handlerMaps.has_key(child.tagName):
 | 
						|
                        text += handlerMaps[child.tagName](child, width)
 | 
						|
                    else:
 | 
						|
                        text += GetText(child.childNodes)
 | 
						|
                child = child.nextSibling
 | 
						|
 | 
						|
            retText += IndentParagraphs(text, width)
 | 
						|
 | 
						|
        # If we cannot understand _anything_ about the element, then just
 | 
						|
        # handle its children hoping we have something to gather from
 | 
						|
        # there.
 | 
						|
        elif not STRICT:
 | 
						|
            printerr('making recursive call for unkown child')
 | 
						|
            retText += handleElement(child, width)
 | 
						|
            child = child.nextSibling
 | 
						|
 | 
						|
        else:
 | 
						|
            child = child.nextSibling
 | 
						|
 | 
						|
    return retText
 | 
						|
 | 
						|
# }}}
 | 
						|
 | 
						|
################################################################################
 | 
						|
# Functions for handling various xml tags
 | 
						|
################################################################################
 | 
						|
# handleArticleInfo(articleinfo, width): {{{
 | 
						|
def handleArticleInfo(articleinfo, width):
 | 
						|
 | 
						|
    makeTocHash(articleinfo.parentNode, width)
 | 
						|
    makeAnchorHash(articleinfo.parentNode)
 | 
						|
    makeURLHash(articleinfo.parentNode)
 | 
						|
 | 
						|
    title = articleinfo.getChildrenByTagName('title')
 | 
						|
    if title is None:
 | 
						|
        print("Article should have a title!")
 | 
						|
        sys.exit(1)
 | 
						|
 | 
						|
    name = GetText(title[0].childNodes)
 | 
						|
    authors = articleinfo.getChildrenByTagName('author')
 | 
						|
 | 
						|
    authorText = ''
 | 
						|
    for author in authors:
 | 
						|
        firstname = ''
 | 
						|
        surname = ''
 | 
						|
        if author.getElementsByTagName('firstname'):
 | 
						|
            firstname = GetTextFromElementNode(author, 'firstname')[0]
 | 
						|
        if author.getChildrenByTagName('surname'):
 | 
						|
            surname = GetTextFromElementNode(author, 'surname')[0]
 | 
						|
        if author.getElementsByTagName('email'):
 | 
						|
            email = GetTextFromElementNode(author, 'email')[0]
 | 
						|
        authorText = authorText + firstname + ' ' + surname + ' <' + email + '>\n'
 | 
						|
        
 | 
						|
 | 
						|
    abstractText = ''
 | 
						|
    abstract = articleinfo.getChildrenByTagName('abstract')
 | 
						|
    if abstract is not None:
 | 
						|
        abstractText = '\n\n' + CenterText('Abstract\n========', width)
 | 
						|
        abstractText += handleElement(abstract[0], width) + '\n'
 | 
						|
 | 
						|
 | 
						|
    retText = CenterText(name + '\n*' + FILENAME + '*\n' + authorText, width)
 | 
						|
    retText += abstractText
 | 
						|
 | 
						|
    toc = makeTOC(articleinfo.parentNode, width)
 | 
						|
 | 
						|
    foldwarn = r'''
 | 
						|
================================================================================
 | 
						|
Viewing this file
 | 
						|
 | 
						|
This file can be viewed with all the sections and subsections folded to ease
 | 
						|
navigation. By default, vim does not fold help documents. To create the folds,
 | 
						|
press za now. The folds are created via a foldexpr which can be seen in the
 | 
						|
last section of this file.
 | 
						|
 | 
						|
See |usr_28.txt| for an introduction to folding and |fold-commands| for key
 | 
						|
sequences and commands to work with folds.
 | 
						|
'''
 | 
						|
 | 
						|
    return retText + '\n' + RightJustify('*' + FILENAME + '-toc*', width) + '\n' + toc + foldwarn
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleOption(option, width): {{{
 | 
						|
def handleOption(option, width):
 | 
						|
    retText = ""
 | 
						|
    names = GetTextFromElementNode(option, "name")
 | 
						|
 | 
						|
    for name in names:
 | 
						|
        retText += string.rjust("*"+name+"*", width) + "\n"
 | 
						|
 | 
						|
    nameTexts = ""
 | 
						|
    maxNameLen = -1
 | 
						|
    for name in names:
 | 
						|
        maxNameLen = max(maxNameLen, len(name + "    "))
 | 
						|
        nameTexts += name + "    \n"
 | 
						|
 | 
						|
    desc = option.getChildrenByTagName("desc")[0]
 | 
						|
    descText = handleElement(desc, width=width-maxNameLen)
 | 
						|
 | 
						|
    retText += VertCatString(nameTexts + "    ", None, descText)
 | 
						|
 | 
						|
    return retText + "\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleOptionDefault(default, width): {{{
 | 
						|
def handleOptionDefault(default, width):
 | 
						|
    type = string.join(GetTextFromElementNode(default, "type"), "\n")
 | 
						|
    extra = string.join(GetTextFromElementNode(default, "extra"), "\n")
 | 
						|
    return type + "\t(" + extra + ")"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleTableRoot(root, width): {{{
 | 
						|
def handleTableRoot(root, width):
 | 
						|
    tgroup = root.getChildrenByTagName('tgroup')[0]
 | 
						|
    if tgroup is None:
 | 
						|
        return ''
 | 
						|
 | 
						|
    rows = []
 | 
						|
    numHeadRows = 0
 | 
						|
    if tgroup.getChildrenByTagName('thead'):
 | 
						|
        thead = tgroup.getChildrenByTagName('thead')[0]
 | 
						|
        rows = thead.getChildrenByTagName('row')
 | 
						|
        numHeadRows = len(rows)
 | 
						|
 | 
						|
    tbody = tgroup.getChildrenByTagName('tbody')[0]
 | 
						|
    rows += tbody.getChildrenByTagName('row')
 | 
						|
 | 
						|
    widths, text = calculateColumnWidthsDoublePass(rows, width)
 | 
						|
 | 
						|
    headText = text[0:numHeadRows]
 | 
						|
    bodyText = text[numHeadRows:]
 | 
						|
 | 
						|
    headTable = FormatTable(headText, ROW_SPACE = 1, COL_SPACE =
 | 
						|
                    COL_SPACE, justify = 0, widths = widths)
 | 
						|
    if headTable:
 | 
						|
        headTable = re.sub(r'\n|$', '\g<0>~', headTable)
 | 
						|
    bodyTable = FormatTable(bodyText, ROW_SPACE = 1, COL_SPACE =
 | 
						|
                    COL_SPACE, justify = 0, widths = widths)
 | 
						|
 | 
						|
    return headTable + '\n'+ re.sub(r'\n+$', '', bodyTable) + '\n\n'
 | 
						|
 | 
						|
# calculateColumnWidths(rows, width): {{{
 | 
						|
def calculateColumnWidths(rows, alloc_widths):
 | 
						|
    widths = {}
 | 
						|
    text = []
 | 
						|
    for row in rows:
 | 
						|
        cols = row.getChildrenByTagName("entry")
 | 
						|
        if len(alloc_widths) == 1:
 | 
						|
            alloc_widths *= len(cols)
 | 
						|
 | 
						|
        colwidths = []
 | 
						|
        rowtext = []
 | 
						|
        for col, width in zip(cols, alloc_widths):
 | 
						|
            coltext = handleElement(col, width)
 | 
						|
 | 
						|
            rowtext.append(coltext)
 | 
						|
            # This is the 'width' of the current cell including the
 | 
						|
            # whitespace padding.
 | 
						|
            colwidths.append(max(map(len, coltext.split("\n"))) \
 | 
						|
                                + COL_SPACE)
 | 
						|
 | 
						|
        text.append(rowtext)
 | 
						|
 | 
						|
        # update the widths of the columns by finding the maximum
 | 
						|
        # width of all cells in this column.
 | 
						|
        for i in range(len(colwidths)):
 | 
						|
            widths[i] = max(colwidths[i], widths.get(i, -1))
 | 
						|
 | 
						|
    return widths, text
 | 
						|
 | 
						|
# }}}
 | 
						|
# calculateColumnWidthsDoublePass(rows, width): {{{
 | 
						|
def calculateColumnWidthsDoublePass(rows, width):
 | 
						|
    maxwidths, text = calculateColumnWidths(rows, [width])
 | 
						|
    if reduce(lambda x, y: x+y, maxwidths.values()) <= width:
 | 
						|
        return maxwidths, text
 | 
						|
 | 
						|
    # now find out how many columns exceed the maximum permitted width.
 | 
						|
    # nlarge: number of columns which are too wide.
 | 
						|
    # remainingWidth: width which these large columns can share.
 | 
						|
    nlarge = 0
 | 
						|
    remainingWidth = width
 | 
						|
    for colwidth in maxwidths.values():
 | 
						|
        if colwidth > width/len(maxwidths):
 | 
						|
            nlarge += 1
 | 
						|
        else:
 | 
						|
            remainingWidth += -colwidth
 | 
						|
 | 
						|
    # newmaxwidth: width which each of the large columns is allowed.
 | 
						|
    newmaxwidth = remainingWidth/max(nlarge, 1)
 | 
						|
 | 
						|
    newcolwidths = []
 | 
						|
    for colwidth in maxwidths.values():
 | 
						|
        newcolwidths += [min(colwidth, newmaxwidth)]
 | 
						|
 | 
						|
    # make another run and this time ask each cell to restrict itself to
 | 
						|
    # newmaxwidth as calculated above.
 | 
						|
    newmaxwidth, newtext = calculateColumnWidths(rows, newcolwidths)
 | 
						|
 | 
						|
    return newmaxwidth, newtext
 | 
						|
 | 
						|
# }}}
 | 
						|
# }}}
 | 
						|
# handleCode(code, width): {{{
 | 
						|
def handleCode(code, width):
 | 
						|
    retText =  GetText(code.childNodes)
 | 
						|
    return " &codebegin;\n" + VertCatString("    ", 4, retText) + "&codeend;"
 | 
						|
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleList(list, width, marker=0): {{{
 | 
						|
def handleList(list, width, marker=0):
 | 
						|
    if list.tagName == 'simplelist':
 | 
						|
        child = 'member'
 | 
						|
        decoration = ''
 | 
						|
    elif list.tagName == 'orderedlist':
 | 
						|
        child = 'listitem'
 | 
						|
    else:
 | 
						|
        child = 'member'
 | 
						|
        decoration = '- '
 | 
						|
 | 
						|
    retText = ""
 | 
						|
    items = list.getChildrenByTagName(child)
 | 
						|
    i = 1
 | 
						|
 | 
						|
    for item in items:
 | 
						|
        if list.tagName == 'orderedlist':
 | 
						|
            decoration = str(i) + '. '
 | 
						|
            i = i + 1
 | 
						|
        itemText = handleElement(item, width - len(decoration))
 | 
						|
        itemText = VertCatString(decoration, None, itemText)
 | 
						|
 | 
						|
        retText += '\n' + re.sub(r'\s+$', '', itemText) + "\n"
 | 
						|
 | 
						|
    return retText
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleNote(note, width): {{{
 | 
						|
def handleNote(note, width):
 | 
						|
    title = None
 | 
						|
    if note.getChildrenByTagName('title'):
 | 
						|
        title = note.getChildrenByTagName('title')[0]
 | 
						|
        name = GetText(title.childNodes)
 | 
						|
        note.removeChild(title)
 | 
						|
 | 
						|
    noteid = ''
 | 
						|
    if note.getAttribute('id'):
 | 
						|
        noteTagText = '*' + note.getAttribute('id') + '* '
 | 
						|
        noteTagText += '*' + ANCHOR_HASH[note.getAttribute('id')] + '*'
 | 
						|
        noteTagText = IndentParagraphs(noteTagText, width/2)
 | 
						|
        noteid = RightJustify(noteTagText, width) + '\n'
 | 
						|
 | 
						|
    noteText = handleElement(note, width-len("NOTE: "))
 | 
						|
    if title is not None:
 | 
						|
        noteText = name + '\n' +('-' * len(name)) + '\n' + noteText
 | 
						|
 | 
						|
    noteText = noteid + VertCatString("NOTE: ", None, noteText)
 | 
						|
 | 
						|
    return noteText + "\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleParagraph(paragraph, width): {{{
 | 
						|
def handleParagraph(paragraph, width):
 | 
						|
    partext = handleElement(paragraph, width)
 | 
						|
 | 
						|
    partext = re.sub(r'\n+$', '', partext)
 | 
						|
    partext = re.sub(r'^\n+', '', partext)
 | 
						|
 | 
						|
    return partext + "\n\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleFormalParagraph(paragraph, width): {{{
 | 
						|
def handleFormalParagraph(formalparagraph, width):
 | 
						|
    title = None
 | 
						|
    if formalparagraph.getChildrenByTagName('title'):
 | 
						|
        title = formalparagraph.getChildrenByTagName('title')[0]
 | 
						|
        name = GetText(title.childNodes)
 | 
						|
        formalparagraph.removeChild(title)
 | 
						|
 | 
						|
    partext = handleElement(formalparagraph, width)
 | 
						|
 | 
						|
    partext = re.sub(r'\n+$', '', partext)
 | 
						|
    partext = re.sub(r'^\n+', '', partext)
 | 
						|
    if title is not None:
 | 
						|
        partext = name + '\n' + ('-' * len(name)) + '\n' + partext
 | 
						|
 | 
						|
    return partext + "\n\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleBlockQuote(block, width): {{{
 | 
						|
def handleBlockQuote(block, width):
 | 
						|
    text = handleElement(block, width - BLOCK_QUOTE)
 | 
						|
    text = VertCatString(" "*BLOCK_QUOTE,  \
 | 
						|
                         BLOCK_QUOTE, text)
 | 
						|
 | 
						|
    return text + "\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleLink(link, width): {{{
 | 
						|
def handleLink(link, width):
 | 
						|
    linkend = link.getAttribute('linkend')
 | 
						|
    if not ANCHOR_HASH.has_key(linkend):
 | 
						|
        print >> STDERR, "Warning: Link ID [%s] not found in TOC" % linkend
 | 
						|
    text = handleElement(link, width)
 | 
						|
    anchorpt = ANCHOR_HASH.get(linkend)
 | 
						|
    if not anchorpt:
 | 
						|
        anchorpt = ''
 | 
						|
 | 
						|
    return text + ' [|' + anchorpt + '|]'
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleAnchor(anchor, width): {{{
 | 
						|
def handleAnchor(anchor, width):
 | 
						|
    anchorText = '*'+anchor.getAttribute('id')+'* '
 | 
						|
    anchorText += '*'+ANCHOR_HASH[anchor.getAttribute('id')]+'*'
 | 
						|
    return RightJustify(anchorText, width) \
 | 
						|
        + "\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleSection(section, width): {{{
 | 
						|
def handleSection(section, width):
 | 
						|
    title = section.getChildrenByTagName('title')[0]
 | 
						|
    name = handleElement(title, width)
 | 
						|
 | 
						|
    sectionid = section.getAttribute('id')
 | 
						|
    tagsformatted = ''
 | 
						|
    if TOC_HASH.has_key(sectionid):
 | 
						|
        tagsformatted = '*%s* ' % TOC_HASH[sectionid]
 | 
						|
 | 
						|
    if ANCHOR_HASH.has_key(sectionid):
 | 
						|
        tagsformatted += '*%s* ' % ANCHOR_HASH[sectionid]
 | 
						|
 | 
						|
    if sectionid and TOC_HASH.has_key(sectionid) and sectionid != TOC_HASH[sectionid]:
 | 
						|
        tagsformatted += '*%s*' % sectionid
 | 
						|
 | 
						|
    # try to indent to a width of 20
 | 
						|
    tagsformatted = RightJustify(IndentParagraphs(tagsformatted, 30), 0)
 | 
						|
    tagswidth = TextWidth(tagsformatted)
 | 
						|
 | 
						|
    # width(name) + nspaces + width(tags) = 80
 | 
						|
    if len(tagsformatted) > 2:
 | 
						|
        header = VertCatString(name, 80-tagswidth, tagsformatted)
 | 
						|
    else:
 | 
						|
        header = name
 | 
						|
 | 
						|
    section.removeChild(title)
 | 
						|
    text = handleElement(section, width)
 | 
						|
 | 
						|
    thislevel = LEVEL_HASH.get(sectionid, -1)
 | 
						|
    if thislevel == 0:
 | 
						|
        delim = '='
 | 
						|
        newlines = '\n\n'
 | 
						|
    elif thislevel == 1:
 | 
						|
        delim = '-'
 | 
						|
        newlines = '\n'
 | 
						|
    else:
 | 
						|
        delim = ''
 | 
						|
        newlines = '\n'
 | 
						|
 | 
						|
    thisTOC = ''
 | 
						|
    if thislevel <= 1:
 | 
						|
        thisTOC = makeTOC(section, width, maxlevel=1)
 | 
						|
 | 
						|
    return "\n" + (delim * TEXT_WIDTH) + \
 | 
						|
        "\n" + header + newlines + thisTOC + newlines + re.sub(r'\n+$', '', text) + "\n"
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleUlink(ulink, width) {{{
 | 
						|
def handleUlink(ulink, width):
 | 
						|
    url = ulink.getAttribute('url')
 | 
						|
    text = handleElement(ulink)
 | 
						|
    # URL_HASH is created at the very beginning
 | 
						|
    if url:
 | 
						|
        return text + ' |%s|' % URL_HASH[url]
 | 
						|
    else:
 | 
						|
        print >> STDERR, "Warning: url attribute empty for [%s]" % text
 | 
						|
        return text
 | 
						|
 | 
						|
# }}}
 | 
						|
# handleIndexTerm(indexterm, width)  {{{
 | 
						|
def handleIndexTerm(indexterm, width) :
 | 
						|
    return ''
 | 
						|
# }}}
 | 
						|
# handleEmphasis(emphasis, width) {{{
 | 
						|
def handleEmphasis(emphasis, width):
 | 
						|
    return '_' + GetText(emphasis.childNodes) + '_'
 | 
						|
# }}}
 | 
						|
 | 
						|
################################################################################
 | 
						|
# A dictionary for mapping xml tags to functions.
 | 
						|
################################################################################
 | 
						|
# {{{
 | 
						|
handlerMaps = {
 | 
						|
    'articleinfo': handleArticleInfo,
 | 
						|
    'table': handleTableRoot,
 | 
						|
    'informaltable': handleTableRoot,
 | 
						|
    'code': handleCode,
 | 
						|
    'programlisting': handleCode,
 | 
						|
    'list': handleList,
 | 
						|
    'simplelist': handleList,
 | 
						|
    'orderedlist': handleList,
 | 
						|
    'para': handleParagraph,
 | 
						|
    'formalpara': handleFormalParagraph,
 | 
						|
    'note': handleNote,
 | 
						|
    'link': handleLink,
 | 
						|
    'anchor': handleAnchor,
 | 
						|
    'section': handleSection,
 | 
						|
    'blockquote': handleBlockQuote,
 | 
						|
    'ulink': handleUlink,
 | 
						|
    'emphasis': handleEmphasis,
 | 
						|
    'indexterm': handleIndexTerm
 | 
						|
}
 | 
						|
inlineTags = {'tag':1, 'literal':1, 'link':1, 
 | 
						|
    'ulink':1, 'citetitle':1, 'indexterm':1,
 | 
						|
    'emphasis':1, 'filename':1 }
 | 
						|
# }}}
 | 
						|
 | 
						|
# helper functions for usage() and printerr() {{{
 | 
						|
def usage():
 | 
						|
    print __doc__
 | 
						|
 | 
						|
def printerr(statement):
 | 
						|
    if DEBUG:
 | 
						|
        print >> STDERR, statement
 | 
						|
 | 
						|
# }}}
 | 
						|
# replaceComment(matchobj) {{{
 | 
						|
def replaceComment(matchobj):
 | 
						|
    initspace = matchobj.group(1)
 | 
						|
    firstsent = matchobj.group(2)
 | 
						|
    code = matchobj.group(3)
 | 
						|
 | 
						|
    if len(initspace) > 0:
 | 
						|
        if initspace[0] == '<':
 | 
						|
            lastspace = initspace
 | 
						|
        else:
 | 
						|
            lastspace = '<' + initspace[:-1]
 | 
						|
    else:
 | 
						|
	lastspace = initspace
 | 
						|
 | 
						|
    return '\n' + initspace + firstsent + ' >\n' + code + '\n' + lastspace
 | 
						|
    
 | 
						|
# }}}
 | 
						|
# main function {{{
 | 
						|
if __name__ == "__main__":
 | 
						|
    option = {}
 | 
						|
    try:
 | 
						|
        opts, args = getopt.getopt(sys.argv[1:], 'ds', ['prefix=', 'help'])
 | 
						|
        for oa, ov in opts:
 | 
						|
            option[oa] = ov
 | 
						|
 | 
						|
    except getopt.GetoptError:
 | 
						|
        print >> STDERR, "Usage error: db2vim --help for usage"
 | 
						|
        sys.exit(1)
 | 
						|
 | 
						|
    if option.has_key('--help'):
 | 
						|
        usage();
 | 
						|
        sys.exit(0);
 | 
						|
 | 
						|
    TOC_PREFIX = option.get('--prefix', 'ls_')
 | 
						|
    DEBUG = option.has_key('-d')
 | 
						|
 | 
						|
    if len(args) != 1:
 | 
						|
        print >> STDERR, "Usage error: db2vim --help for usage"
 | 
						|
        sys.exit(1)
 | 
						|
 | 
						|
    fileName = args[0]
 | 
						|
    FILENAME = re.sub(r'\.\w+$', r'.txt', fileName)
 | 
						|
 | 
						|
    try:
 | 
						|
        fp = open(fileName)
 | 
						|
    except:
 | 
						|
        print "Error opening xml file"
 | 
						|
 | 
						|
    dom = xml.dom.minidom.parse(fp) 
 | 
						|
 | 
						|
    modeline = r'''
 | 
						|
================================================================================
 | 
						|
About this file
 | 
						|
 | 
						|
This file was created automatically from its XML variant using db2vim. db2vim is
 | 
						|
a python script which understands a very limited subset of the Docbook XML 4.2
 | 
						|
DTD and outputs a plain text file in vim help format.
 | 
						|
 | 
						|
db2vim can be obtained via anonymous CVS from sourceforge.net. Use
 | 
						|
 | 
						|
cvs -d:pserver:anonymous@cvs.vim-latex.sf.net:/cvsroot/vim-latex co db2vim
 | 
						|
 | 
						|
Or you can visit the web-interface to sourceforge CVS at:
 | 
						|
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/vim-latex/db2vim/
 | 
						|
 | 
						|
The following modelines should nicely fold up this help manual.
 | 
						|
 | 
						|
vim:ft=help:fdm=expr:nowrap
 | 
						|
vim:foldexpr=getline(v\:lnum-1)=~'-\\{80}'?'>2'\:getline(v\:lnum-1)=~'=\\{80}'?'>1'\:getline(v\:lnum)=~'=\\{80}'?'0'\:getline(v\:lnum)=~'-\\{80}'?'1'\:'='
 | 
						|
vim:foldtext=substitute(v\:folddashes.substitute(getline(v\:foldstart),'\\s*\\*.*',"",""),'^--','\ \ \ \ \ \ ','')
 | 
						|
================================================================================'''
 | 
						|
 | 
						|
    STRICT = option.has_key('-s')
 | 
						|
 | 
						|
    pattern = re.compile(r'\n([< ]*)([^\n]+)&codebegin;\n(.*?)&codeend;', re.DOTALL)
 | 
						|
 | 
						|
    processedDoc = handleElement(dom.documentElement)
 | 
						|
    while re.search('&codebegin;', processedDoc):
 | 
						|
        processedDoc = re.sub(pattern, replaceComment, processedDoc)
 | 
						|
 | 
						|
    urlsection = r"""
 | 
						|
================================================================================
 | 
						|
URLs used in this file
 | 
						|
 | 
						|
"""
 | 
						|
    labels = zip(URL_HASH.values(), URL_HASH.keys())
 | 
						|
    labels.sort()
 | 
						|
    for label, url in labels:
 | 
						|
        urlsection += '*%s* : %s\n' % (label, url)
 | 
						|
 | 
						|
    processedDoc = processedDoc + urlsection + modeline
 | 
						|
    print processedDoc.encode('iso-8859-1')
 | 
						|
 | 
						|
# }}}
 | 
						|
# vim:et:sts=4:fdm=marker
 |