diff --git a/Makefile b/Makefile index 36a67c193cf39daa27af48e522ea672faeb09c88..cf85308e4ebcf5fe2fb883977baa445ca7ed3169 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: output output: - python -m muppet --env ~/puppet/generated-environments/production/modules/ + python -m muppet --env ~/puppet/generated-environments/test/modules/ check: flake8 muppet diff --git a/muppet/format.py b/muppet/format.py index 4065136284aafc1fb896f3174e74cdfbdb873942..b0e7e2a54f6fb26d2fe78b05811930cb1270aeaf 100644 --- a/muppet/format.py +++ b/muppet/format.py @@ -47,7 +47,7 @@ class Tag: inner: str if isinstance(self.item, str): inner = self.item - elif isinstance(self.item, Tag): + elif isinstance(self.item, Markup): inner = str(self.item) else: inner = ''.join(str(i) for i in self.item) @@ -56,16 +56,71 @@ class Tag: return f'<span class="{tags}">{inner}</span>' +@dataclass +class Link: + """An item which should link somewhere.""" + + item: Any + target: str + + def __str__(self) -> str: + return f'<a href="{self.target}">{self.item}</a>' + + +@dataclass +class ID: + """Item with an ID attached.""" + + item: Any + id: str + + def __str__(self) -> str: + return f'<span id="{self.id}">{self.item}</span>' + + +@dataclass +class Documentation: + """Attach documentation to a given item.""" + + item: Any + documentation: str + + def __str__(self) -> str: + s = '<span class="documentation-anchor">' + s += str(self.item) + s += f'<div class="documentation">{self.documentation}</div>' + s += '</span>' + return s + + +Markup: TypeAlias = Tag | Link | ID | Documentation + + all_tags: set[str] = set() -def tag(item: str | Tag | Sequence[str | Tag], *tags: str) -> Tag: +def tag(item: str | Markup | Sequence[str | Markup], *tags: str) -> Tag: """Tag item with tags.""" global all_tags all_tags |= set(tags) return Tag(item, tags=tags) +def link(item: str | Markup, target: str) -> Link: + """Create a new link element.""" + return Link(item, target) + + +def id(item: str | Markup, id: str) -> ID: + """Attach an id to an item.""" + return ID(item, id) + + +def doc(item: str | Markup, documentation: str) -> Documentation: + """Attach documentation to an item.""" + return Documentation(item, documentation) + + def ind(level: int) -> str: """Returnu a string for indentation.""" return ' '*level*2 @@ -128,11 +183,17 @@ def print_var(x: str, dollar: bool = True) -> Tag: If there should be a dollar prefix. """ dol = '$' if dollar else '' - if doc := param_doc.get(x): - s = f'{dol}{x}<div class="documentation">{doc}</div>' - return tag(s, 'var') + if docs := param_doc.get(x): + s = f'{dol}{x}' + return link(doc(tag(s, 'var'), docs), f'#{x}') else: - return tag(f'{dol}{x}', 'var') + return link(tag(f'{dol}{x}', 'var'), f'#{x}') + + +def declare_var(x: str) -> Tag: + """Returna a tag declaring that this variable exists.""" + return tag(id(f"${x}", x), 'var') + # TODO strip leading colons when looking up documentation @@ -356,7 +417,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag: 'type'), ' '] # print(f'<span class="var">${name}</span>', end='') - items += [print_var(name)] + items += [declare_var(name)] if 'value' in data: items += [ ' = ', @@ -775,7 +836,10 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag: case ['var', x]: # TODO how does this work with deeply nested expressions # in strings? - return print_var(x, context[0] != 'str') + if context[0] == 'declaration': + return declare_var(x) + else: + return print_var(x, context[0] != 'str') case ['virtual-query', q]: return tag([ @@ -914,10 +978,10 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag: case ['=', field, value]: return tag([ - parse(field, indent, context), + parse(field, indent, ['declaration'] + context), ' ', '=', ' ', parse(value, indent, context), - ]) + ], 'declaration') case ['==', a, b]: return tag([ @@ -931,7 +995,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag: parse(a, indent, context), ' ', '=~', ' ', parse(b, indent, context), - ]) + ], 'declaration') case ['!~', a, b]: return tag([ diff --git a/static/style.css b/static/style.css index a62934bd1cebd76b0cf731a9a28b55792a8df1ca..01ca608250a9a9f47fa82be10d393cac9a671b4d 100644 --- a/static/style.css +++ b/static/style.css @@ -49,3 +49,7 @@ h2 { code.json { font-size: 80%; } + +:target { + background-color: yellow; +}