Browse Source

Some changes to allow commands to touch the rest of the tree they're currently in. This shall only be done on parts of the tree not yet transformed, otherwise, very weird things can happen.

master
Jan Černohorský 2 months ago
parent
commit
3ce0b5037b
  1. 8
      src/formatitko/nop_processor.py
  2. 4
      src/formatitko/output_generator.py
  3. 27
      src/formatitko/transform_processor.py

8
src/formatitko/nop_processor.py

@ -127,13 +127,17 @@ class NOPProcessor:
raise FormatitkoRecursiveError(e, self.context) from err
def transform_list(self, e: list[Union[Element, ListContainer]]) -> list[Union[Element, ListContainer]]:
for i in range(len(e)):
i = 0
while i < len(e): # The length of the list can change mid-transformation, so we need to check the length each time
e[i] = self.transform(e[i])
i-=-1
return e
def transform_ListContainer(self, e: ListContainer) -> ListContainer:
for i in range(len(e)):
i = 0
while i < len(e): # The length of the list can change mid-transformation, so we need to check the length each time
e[i] = self.transform(e[i])
i-=-1
return e

4
src/formatitko/output_generator.py

@ -31,7 +31,7 @@ class FormatitkoRecursiveError(Exception):
def add_element(self, e: Union[Element, ListContainer, list[Union[Element, ListContainer]]]):
self.elements.append(e)
def pretty_print(self):
def pretty_print(self, tracebacklimit: int=0):
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
@ -49,7 +49,7 @@ class FormatitkoRecursiveError(Exception):
eprint('on line: "' + stringify(line).strip() + '"', end="")
eprint()
eprint("in element: " + str(self.elements[0]).replace("\n", "\\n"))
sys.tracebacklimit = 0
sys.tracebacklimit = tracebacklimit
raise self.__cause__ from None

27
src/formatitko/transform_processor.py

@ -3,6 +3,7 @@ from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quote
from panflute import BlockQuote, BulletList, Citation, CodeBlock, Definition, DefinitionItem, DefinitionList, Div, Figure, Header, HorizontalRule, LineBlock, LineItem, ListItem, MetaBlocks, MetaBool, MetaInlines, MetaList, MetaMap, MetaString, Null, OrderedList, Para, Plain, RawBlock, Table, TableBody, TableFoot, TableHead
from panflute import TableRow, TableCell, Caption, Doc
from panflute import MetaValue
from panflute.containers import attach
from typing import Union, Callable
from types import ModuleType
@ -75,8 +76,8 @@ class TransformProcessor(NOPProcessor):
self.context = Context(e, self.root_file_path)
for module, module_name in self._command_modules:
self.context.add_commands_from_module(module, module_name)
e.content = self.transform(e.content)
e.content = [BlockGroup(*e.content, context=self.context)]
e.content = self.transform(e.content)
return e
@ -136,8 +137,9 @@ class TransformProcessor(NOPProcessor):
# Commands can be called multiple ways, this handles the following syntax:
# :::{c=commandname}
# :::
e = BlockCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e)
command = BlockCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
attach(command, e.parent, e.location, e.index)
return self.transform(command)
if "partial" in e.attributes:
# `partial` attribute
@ -195,14 +197,16 @@ class TransformProcessor(NOPProcessor):
if "c" in e.attributes:
# Commands can be called multiple ways, this handles the following syntax:
# []{c=commandname} and
e = InlineCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e)
command = InlineCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
attach(command, e.parent, e.location, e.index)
return self.transform(command)
if len(e.content) == 1 and isinstance(e.content[0], Str):
## Handle special command shorthand [!commandname]{}
if re.match(r"^![\w.]+$", e.content[0].text):
e = InlineCommand(identifier=e.identifier, classes=e.classes, attributes={**e.attributes, "c": e.content[0].text[1:]})
return self.transform(e)
command = InlineCommand(identifier=e.identifier, classes=e.classes, attributes={**e.attributes, "c": e.content[0].text[1:]})
attach(command, e.parent, e.location, e.index)
return self.transform(command)
## Handle import [#ksp_formatitko as ksp]{}, [#ksp_formatitko]{type=module} or [#path/file.md]{type=md}
# Import a python module as commands (type=module, the default) or
@ -255,8 +259,9 @@ class TransformProcessor(NOPProcessor):
if not self.context.trusted:
return nullify(e)
command_output = parse_command(e.text)(BlockCommand(), self.context, self)
e = BlockCommand().replaceSelf(*([] if command_output is None else command_output))
return self.transform(e)
command = BlockCommand().replaceSelf(*([] if command_output is None else command_output))
attach(command, e.parent, e.location, e.index)
return self.transform(command)
if "python" in e.classes and ("define" in e.attributes or "redefine" in e.attributes):
if not self.context.trusted:
@ -264,7 +269,9 @@ class TransformProcessor(NOPProcessor):
return handle_command_define(e, self.context)
if "c" in e.attributes:
return self.transform(CodeCommand(e.text, identifier=e.identifier, classes=e.classes, attributes=e.attributes))
command = CodeCommand(e.text, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
attach(command, e.parent, e.location, e.index)
return self.transform(command)
# Pass down metadata 'highlight' and 'highlight_style' as attribute to CodeBlocks
# OG now has Context so this is not needed per se, but I'm keeping this here for the handling of attribute > context > default value

Loading…
Cancel
Save