# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright (c) 2007 Andrés J. Díaz López   <ajdiaz@udc.es>
# Copyright (c) 2007 Adrián Pérez de Castro <adrianperez@udc.es>
# Copyright (c) 2007 Pablo Saavedra Rodiño  <psaavedra@udc.es>
#
# Distributed under terms of the MIT license.

"""
Defines a reStructuredText interpreted text role for inline macro expansion.

Example usage::

    The server's ``fstab`` has
    :macro:`LocalFile(wc -l /etc/fstab, execute+raw)` lines.
"""

from MoinMoin import wikimacro
from MoinMoin.parser import rst
import threading

# XXX We will use TLS to keep track of the current parser being used... Just
#     remember that we may be running inside a threaded environment (i.e.
#     Apache with the worker MPM and mod_python, the CherryPy WSGI server
#     and so on...)
#
current = threading.local()
current.__dict__.setdefault('parser', None)


# This will attached as method of MoinMoin.parser.rst.Parser, so we can
# access the Parser instance being used (needed to create wikimacro.Macro
# instances).
#
def macro_role(name, rawtext, text, lineno, inliner, options={}, content={}):
    from docutils import nodes

    if not len(text.strip()):
        msg = inliner.reporter.error("Macro cannot be empty", line=lineno)
        prb = inliner.problematic(rawtext, rawtext, msg)
        return [prb], [msg]

    text = text.strip()
    if "(" in text:
        macro, args = text.split("(")
        assert args[-1] == ")"
        args = args[:-1]
    else:
        macro = text
        args  = ""

    if current.parser is None:
        msg = inliner.reporter.error("No parser for the current thread!")
        return [], [msg]
    
    result = wikimacro.Macro(current.parser).execute(macro, args)
    return [nodes.inline(rawtext, result)], []


macro_role.options = { "class": None }
macro_role.content = True


# Save the original constructor (will be called by our hijacked one)
original__init__ = rst.Parser.__init__

def hacked__init__(self, raw, request, **kw):
    original__init__(self, raw, request, **kw)
    current.parser = self


from mmpp import hook

@hook
def patch_macro_role():
    try:
        from docutils.parsers.rst import roles
    except ImportError:
        return
   
    # Perform actual hijacking...
    rst.Parser.__init__ = hacked__init__
    roles.register_local_role("macro", macro_role)

