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ý 9 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 raise FormatitkoRecursiveError(e, self.context) from err
def transform_list(self, e: list[Union[Element, ListContainer]]) -> list[Union[Element, ListContainer]]: 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]) e[i] = self.transform(e[i])
i-=-1
return e return e
def transform_ListContainer(self, e: ListContainer) -> ListContainer: 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]) e[i] = self.transform(e[i])
i-=-1
return e 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]]]): def add_element(self, e: Union[Element, ListContainer, list[Union[Element, ListContainer]]]):
self.elements.append(e) self.elements.append(e)
def pretty_print(self): def pretty_print(self, tracebacklimit: int=0):
def eprint(*args, **kwargs): def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs) print(*args, file=sys.stderr, **kwargs)
@ -49,7 +49,7 @@ class FormatitkoRecursiveError(Exception):
eprint('on line: "' + stringify(line).strip() + '"', end="") eprint('on line: "' + stringify(line).strip() + '"', end="")
eprint() eprint()
eprint("in element: " + str(self.elements[0]).replace("\n", "\\n")) eprint("in element: " + str(self.elements[0]).replace("\n", "\\n"))
sys.tracebacklimit = 0 sys.tracebacklimit = tracebacklimit
raise self.__cause__ from None 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 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 TableRow, TableCell, Caption, Doc
from panflute import MetaValue from panflute import MetaValue
from panflute.containers import attach
from typing import Union, Callable from typing import Union, Callable
from types import ModuleType from types import ModuleType
@ -75,8 +76,8 @@ class TransformProcessor(NOPProcessor):
self.context = Context(e, self.root_file_path) self.context = Context(e, self.root_file_path)
for module, module_name in self._command_modules: for module, module_name in self._command_modules:
self.context.add_commands_from_module(module, module_name) 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 = [BlockGroup(*e.content, context=self.context)]
e.content = self.transform(e.content)
return e return e
@ -136,8 +137,9 @@ class TransformProcessor(NOPProcessor):
# Commands can be called multiple ways, this handles the following syntax: # Commands can be called multiple ways, this handles the following syntax:
# :::{c=commandname} # :::{c=commandname}
# ::: # :::
e = BlockCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes) command = BlockCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e) attach(command, e.parent, e.location, e.index)
return self.transform(command)
if "partial" in e.attributes: if "partial" in e.attributes:
# `partial` attribute # `partial` attribute
@ -195,14 +197,16 @@ class TransformProcessor(NOPProcessor):
if "c" in e.attributes: if "c" in e.attributes:
# Commands can be called multiple ways, this handles the following syntax: # Commands can be called multiple ways, this handles the following syntax:
# []{c=commandname} and # []{c=commandname} and
e = InlineCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes) command = InlineCommand(*e.content, identifier=e.identifier, classes=e.classes, attributes=e.attributes)
return self.transform(e) attach(command, e.parent, e.location, e.index)
return self.transform(command)
if len(e.content) == 1 and isinstance(e.content[0], Str): if len(e.content) == 1 and isinstance(e.content[0], Str):
## Handle special command shorthand [!commandname]{} ## Handle special command shorthand [!commandname]{}
if re.match(r"^![\w.]+$", e.content[0].text): 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:]}) command = InlineCommand(identifier=e.identifier, classes=e.classes, attributes={**e.attributes, "c": e.content[0].text[1:]})
return self.transform(e) 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} ## 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 # Import a python module as commands (type=module, the default) or
@ -255,8 +259,9 @@ class TransformProcessor(NOPProcessor):
if not self.context.trusted: if not self.context.trusted:
return nullify(e) return nullify(e)
command_output = parse_command(e.text)(BlockCommand(), self.context, self) command_output = parse_command(e.text)(BlockCommand(), self.context, self)
e = BlockCommand().replaceSelf(*([] if command_output is None else command_output)) command = BlockCommand().replaceSelf(*([] if command_output is None else command_output))
return self.transform(e) 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 "python" in e.classes and ("define" in e.attributes or "redefine" in e.attributes):
if not self.context.trusted: if not self.context.trusted:
@ -264,7 +269,9 @@ class TransformProcessor(NOPProcessor):
return handle_command_define(e, self.context) return handle_command_define(e, self.context)
if "c" in e.attributes: 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 # 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 # 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