﻿#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""Converts an XBEL bookmark file into a flat listing in MoinMoin wiki format.
"""

# standard-library modules
import os
import re
import sys
from optparse import OptionParser

# third-party modules
import elementtree.ElementTree as ET

__program__   = "xbel2moin.py"
__author__    = "Christopher Arndt"
__version__   = "0.1"
__revision__  = "$Rev: 142 $"
__date__      = "$Date: 2007-06-13 23:34:39 +0200 (Mi, 13 Jun 2007) $"
__copyright__ = "MIT license"

__usage__ = """\
%prog [OPTIONS] <XBEL file>
"""

FOOTER = """\

----

''generated by [attachment:xbel2moin.py xbel2moin.py] on %(date)s from
[attachment:%(source)s %(source)s]''
"""


def usage():
    optparser.print_help()

mangle_re = re.compile(r'\s+', re.DOTALL)
def manglews(text):
    return mangle_re.sub(u' ', text.strip())

def make_heading(text, lvl):
    return u"%s %s %s\n" % ('=' * lvl, text, '=' * lvl)

def make_bookmark(elem):
    title = elem.find('title')
    if ET.iselement(title):
        titletext = title.text.strip()
    else:
        titletext = u'Unnamed bookmark'
    desc = elem.find('desc')
    if ET.iselement(desc):
        desctext = u'\n\n  ' + manglews(desc.text)
    else:
        desctext = u""
    return u"'''[%s %s]'''%s\n" % (elem.get('href', u'#'), titletext,
      desctext)

def parse_folder(elem, headlvl):
    text = []
    title = elem.find('title')
    if ET.iselement(title):
        text.append(make_heading(title.text, headlvl+1))
    elif headlvl != 0:
        text.append(make_heading(u'Unnamed folder', headlvl+1))
    if headlvl == 0 and options.toc:
        text.append(u'[[TableOfContents([%i])]]\n' % options.tocdepth)
    for subelem in elem:
        if subelem.tag == 'folder':
            text.append(parse_folder(subelem, headlvl+1))
        if subelem.tag == 'bookmark':
            text.append(make_bookmark(subelem))
    return u"\n".join(text)

def xbel2moin(filename):
    tree = ET.parse(filename)
    root = tree.getroot()
    headlvl = 0
    doc = parse_folder(root, headlvl)
    if options.footer:
        import locale
        import time
        locale.setlocale(locale.LC_ALL, '')
        doc += FOOTER % dict(date=time.strftime('%x %X'), source=filename)
    return doc

def main(args):
    global options, optparser

    optparser = OptionParser(prog=__program__, usage=__usage__,
      version=__version__, description=__doc__)
    # optparser.add_option("-v", "--verbose",
      # action="store_true", dest="verbose", default=False,
      # help="Print what's going on to stdout.")
    optparser.add_option("-t", "--toc",
      action="store_true", dest="toc", default=False,
      help="Add a table of contents macro after the first heading.")
    optparser.add_option("-d", "--toc-depth",
      action="store", type="int", dest="tocdepth", default=3,
      help="How many heading levels to display in the TOC (default 3).")
    optparser.add_option("-f", "--add-footer",
      action="store_true", dest="footer", default=False,
      help='Add a footer with a "generated by" notice.')

    (options, args) = optparser.parse_args(args=args)
    if args:
        print xbel2moin(args[0])
    else:
        usage()
        return 2
    return 0

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
