From da65b68f1f3a806fc000743b88dd6f56fb44ceb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= <hugo@lysator.liu.se> Date: Tue, 19 Sep 2023 07:08:05 +0200 Subject: [PATCH] Emit puppet code instead of match objects. As a steping stone, the raw match data was emited to the frontend. This just properly renders it. --- muppet/format.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/muppet/format.py b/muppet/format.py index 9e5be76..7294f66 100644 --- a/muppet/format.py +++ b/muppet/format.py @@ -11,7 +11,9 @@ import html import re from typing import ( Tuple, + Any, ) +import types from .puppet.parser import puppet_parser import logging @@ -28,7 +30,11 @@ from .puppet.strings import ( ) from muppet.puppet.ast import build_ast # from muppet.puppet.format import to_string -from muppet.parser_combinator import ParserCombinator, ParseError +from muppet.parser_combinator import ( + ParserCombinator, + ParseError, + MatchCompound, +) from muppet.puppet.format.parser import ParserFormatter @@ -39,6 +45,47 @@ logger = logging.getLogger(__name__) param_doc: dict[str, str] = {} +def reserialize(obj: Any) -> str: + """ + Reconstruct puppet code after parsing it. + + After building the parser, and parsing the puppet code into a tree + of MatchObjects; this procedure returns it into puppet code. + Difference being that we now have metadata, meaning that syntax + highlighting and variable hyperlinks can be inserted. + + :param obj: + Should be assumed to be a list of MatchObject's, or something similar. + + MatchCompound objects are serialized as + + .. code-block:: html + + <span class="{type}">{body}</span> + + strings as themselves, and lists have reserialize mapped over them. + + """ + out: list[str] = [] + # logger.info("obj = %a", obj) + match obj: + case str(s): + out += [s] + case MatchCompound(type=type, matched=xs): + # logger.warning("xs = %a", xs) + body = ''.join(reserialize(x) for x in xs) + out += [f'<span class="{type}">{body}</span>'] + case [*xs]: + out += [reserialize(x for x in xs)] + case rest: + if isinstance(rest, types.GeneratorType): + out += [reserialize(x) for x in rest] + else: + logger.error("Unknown type: %a", rest) + + return ''.join(out) + + def parse_puppet(source: str, file: str) -> str: """ Parse and syntax highlight the given puppet source. @@ -56,7 +103,7 @@ def parse_puppet(source: str, file: str) -> str: # Run the generatefd parser, giving us a list of match objects match_objects = ParserCombinator(source, file).get(parser) # logger.error("match_objects: %a", match_objects) - return '\n'.join(repr(m) for m in match_objects) + return reserialize(match_objects) # -------------------------------------------------- -- GitLab