You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
1.9 KiB
73 lines
1.9 KiB
from panflute import Div,Span,Para
|
|
from typing import List
|
|
|
|
# Import local files
|
|
from util import *
|
|
from context import Context
|
|
from mj_show import show
|
|
|
|
class Command:
|
|
pass
|
|
|
|
class InlineCommand(Span, Command):
|
|
def replaceSelf(self, content: List[Element]) -> Span:
|
|
try:
|
|
return Span(*content)
|
|
except TypeError:
|
|
if len(content) == 1 and isinstance(content[0], Para):
|
|
return Span(*content[0].content)
|
|
else:
|
|
raise SyntaxError(f"The command {self.attributes['c']} returned multiple Paragraphs and must be executed using `::: {{c={self.attributes['c']}}}\\n:::`.")
|
|
pass
|
|
|
|
class BlockCommand(Div, Command):
|
|
def replaceSelf(self, content: List[Element]) -> Div:
|
|
return Div(*content)
|
|
pass
|
|
|
|
|
|
def handle_command_define(e: Element, c: Context):
|
|
if "define" in e.attributes:
|
|
if not c.get_command(e.attributes["define"]):
|
|
c.set_command(e.attributes["define"], compile(e.text, '<string>', 'exec'))
|
|
return nullify(e)
|
|
else:
|
|
raise NameError(f"Command already defined: '{e.attributes['define']}'")
|
|
if "redefine" in e.attributes:
|
|
c.set_command(e.attributes["redefine"], compile(e.text, '<string>', 'exec'))
|
|
return nullify(e)
|
|
|
|
|
|
def executeCommand(source, element: Element, ctx: Context) -> List[Element]:
|
|
mode = 'empty'
|
|
text = ""
|
|
content = []
|
|
def print(s: str=""):
|
|
nonlocal mode, text
|
|
if mode == 'elements':
|
|
raise SyntaxError("Cannot use `print` and `appendChild` in one command at the same time.")
|
|
mode = 'text'
|
|
text += s
|
|
|
|
def println(s: str=""):
|
|
print(s+"\n")
|
|
|
|
def appendChild(e: Element):
|
|
nonlocal mode, content
|
|
if mode == 'text':
|
|
raise SyntaxError("Cannot use `print` and `appendChild` in one command at the same time.")
|
|
mode = 'elements'
|
|
content.append(e)
|
|
|
|
def appendChildren(l: List[Element]):
|
|
for e in l:
|
|
appendChild(e)
|
|
|
|
exec(source)
|
|
|
|
if mode == 'text':
|
|
return import_md(text, standalone=False)
|
|
if mode == 'elements':
|
|
return content
|
|
|
|
return []
|
|
|