Skip to content

Commit

Permalink
feat: support overlays
Browse files Browse the repository at this point in the history
  • Loading branch information
vberlier committed Oct 9, 2023
1 parent aba1411 commit 518f3c9
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 9 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,24 @@ Finally, there's a `strip_final_newline` modifier that removes the final newline
say This function doesn't have a final newline.
```

## Overlays

You can use the `@overlay` directive to make the following directives apply to a specific pack overlay (introduced in [Java Edition 1.20.2](https://minecraft.wiki/w/Java_Edition_1.20.2)).

`@overlay({"min_inclusive": 16, "max_inclusive": 17}) dummy_overlay`

You can specify the `formats` supported by this overlay as a modifier. From now, on all the directives will apply to the overlay `dummy_overlay`.

`@function tutorial:greeting`

```mcfunction
say Hello from overlay!
```

You can switch to another overlay at any time by using the `@overlay` directive again. To go back to the main pack, use the `@endoverlay` directive.

`@endoverlay`

## Command-line utility

```bash
Expand Down
37 changes: 34 additions & 3 deletions lectern/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
]


import json
import re
from dataclasses import replace
from itertools import islice
Expand All @@ -21,6 +22,7 @@
List,
Mapping,
Optional,
Set,
Tuple,
Union,
)
Expand Down Expand Up @@ -54,16 +56,22 @@ def __init__(self, cache: Optional[Cache] = None):
self.escaped_regex = None
self.cache = cache

def generate_directives(self) -> str:
names = list(self.directives)
names.append("overlay")
names.append("endoverlay")
return "|".join(names)

def generate_regex(self) -> str:
"""Return a regex that can match the current directives."""
names = "|".join(self.directives)
names = self.generate_directives()
modifier = r"(?:\((?P<modifier>[^)]*)\)|\b)"
arguments = r"(?P<arguments>.*)"
return f"@(?P<name>{names}){modifier}{arguments}"

def generate_escaped_regex(self) -> str:
"""Return a regex that can match escaped fragments."""
names = "|".join(self.directives)
names = self.generate_directives()
return rf"(@@+(?:{names})\b.*)"

def compile_regex(self, regex: str) -> "re.Pattern[str]":
Expand Down Expand Up @@ -121,13 +129,36 @@ def apply_directives(
loaders: Iterable[FragmentLoader] = (),
):
"""Apply directives into a blank data pack and a blank resource pack."""
original_packs = assets, data
added_overlays: Set[str] = set()

for fragment in fragments:
for loader in loaders:
fragment = loader(fragment, directives)
if not fragment:
break
if fragment:
directives[fragment.directive](fragment, assets, data)
if fragment.directive == "overlay":
directory = fragment.expect("directory")
formats: Any = (
json.loads(fragment.modifier) if fragment.modifier else None
)
assets = assets.overlays.setdefault(
directory, supported_formats=formats
)
data = data.overlays.setdefault(
directory, supported_formats=formats
)
added_overlays.add(directory)
elif fragment.directive == "endoverlay":
assets, data = original_packs
else:
directives[fragment.directive](fragment, assets, data)

for pack in original_packs:
for directory in added_overlays:
if not pack.overlays[directory]:
del pack.overlays[directory]

def parse_fragments(
self,
Expand Down
68 changes: 62 additions & 6 deletions lectern/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@
Dict,
Iterable,
Iterator,
List,
Mapping,
Optional,
Type,
Union,
)
from urllib.parse import urlparse

from beet import DataPack, File, NamespaceFile, ResourcePack, TextFileBase
from beet import DataPack, File, NamespaceFile, ResourcePack, TextFile, TextFileBase
from beet.core.utils import normalize_string

EXTENSION_HIGHLIGHTING = {
Expand Down Expand Up @@ -166,6 +167,36 @@ def serialize(
mapping: Mapping[Type[NamespaceFile], str],
) -> str:
"""Return the serialized representation."""
result: List[str] = []

for pack, extra_directive in [
(assets, "resource_pack"),
(data, "data_pack"),
]:
if not self.pack_filter(pack):
continue

result.append(self.serialize_pack(pack, extra_directive, mapping))

if pack.overlay_parent is None:
should_end = False
for overlay in pack.overlays.values():
if overlay:
should_end = True
result.append(
self.serialize_pack(overlay, extra_directive, mapping)
)
if should_end:
result.append("@endoverlay\n")

return "\n".join(result)

def serialize_pack(
self,
pack: Union[DataPack, ResourcePack],
extra_directive: str,
mapping: Mapping[Type[NamespaceFile], str],
) -> str:
escaped_regex = self.get_escaped_regex(mapping)

return "\n".join(
Expand All @@ -176,15 +207,19 @@ def serialize(
+ b64encode(content).decode()
+ "\n"
)
for pack, extra_directive in [
(assets, "resource_pack"),
(data, "data_pack"),
]
if self.pack_filter(pack)
for directive_name, argument, file_instance in chain(
(
[("overlay", pack.overlay_name, TextFile())]
if pack.overlay_name is not None
else []
),
(
(extra_directive, path, file_instance)
for path, file_instance in pack.extra.items()
if not (
pack.overlay_parent is not None
and path in ("pack.mcmeta", "pack.png")
)
),
(
(
Expand Down Expand Up @@ -286,7 +321,12 @@ def serialize_pack(
"""Yield markdown chunks for the given pack."""
yield f"## {title}"

if pack.overlay_name is not None:
yield f"\n`@overlay {pack.overlay_name}`"

for path, file_instance in pack.extra.items():
if pack.overlay_parent is not None and path in ("pack.mcmeta", "pack.png"):
continue
yield from self.format_serialized_file(
self.serialize_file_instance(
pack_directive,
Expand Down Expand Up @@ -338,6 +378,22 @@ def serialize_pack(
)
yield ""

if pack.overlay_parent is None:
should_end = False
for directory, overlay in pack.overlays.items():
if overlay:
should_end = True
yield from self.serialize_pack(
f"Overlay `{directory}`",
pack_directive,
overlay,
mapping,
external_files,
external_prefix,
)
if should_end:
yield "`@endoverlay`\n"

def format_serialized_file(self, chunks: Iterable[str]) -> Iterator[str]:
"""Format the markdown chunks for serializing file instances."""
if self.flat:
Expand Down
25 changes: 25 additions & 0 deletions tests/snapshots/examples__markdown_README_md__0.pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
"pack": {
"pack_format": 18,
"description": ""
},
"overlays": {
"entries": [
{
"formats": {
"min_inclusive": 16,
"max_inclusive": 17
},
"directory": "dummy_overlay"
}
]
}
}
```
Expand Down Expand Up @@ -203,3 +214,17 @@ say foo
```mcfunction
say foo
```

## Overlay `dummy_overlay`

`@overlay dummy_overlay`

### tutorial

`@function tutorial:greeting`

```mcfunction
say Hello from overlay!
```

`@endoverlay`
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
"pack": {
"pack_format": 18,
"description": ""
},
"overlays": {
"entries": [
{
"formats": {
"min_inclusive": 16,
"max_inclusive": 17
},
"directory": "dummy_overlay"
}
]
}
}
```
Expand Down Expand Up @@ -203,3 +214,17 @@ say foo
```mcfunction
say foo
```

## Overlay `dummy_overlay`

`@overlay dummy_overlay`

### tutorial

`@function tutorial:greeting`

```mcfunction
say Hello from overlay!
```

`@endoverlay`
18 changes: 18 additions & 0 deletions tests/snapshots/examples__text_README_md__0.pack.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
"pack": {
"pack_format": 18,
"description": ""
},
"overlays": {
"entries": [
{
"formats": {
"min_inclusive": 16,
"max_inclusive": 17
},
"directory": "dummy_overlay"
}
]
}
}

Expand Down Expand Up @@ -151,3 +162,10 @@ say foo

@function text_in_block:foo
say foo

@overlay dummy_overlay

@function tutorial:greeting
say Hello from overlay!

@endoverlay

0 comments on commit 518f3c9

Please sign in to comment.