From 4f239ea0d745a1bced322a77990dd997fb9f1ea7 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Sun, 13 Nov 2022 11:37:23 -0800 Subject: [PATCH] wikilink with semantic syntax :) --- tests/test_patterns/test_wikilinks.py | 20 ++++++++++-- wiki_postbot/patterns/wikilink.py | 46 +++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/tests/test_patterns/test_wikilinks.py b/tests/test_patterns/test_wikilinks.py index f4a0859..06fb591 100644 --- a/tests/test_patterns/test_wikilinks.py +++ b/tests/test_patterns/test_wikilinks.py @@ -41,6 +41,14 @@ class TestStr: "[[^{1,3}Link#With section]]", Wikilink("Link", nback=NBack(1,3), section="With section") ) + implicit = ( + "[[Predicate:singlecol::Object]]", + Wikilink(predicate="Predicate:singlecol", object="Object") + ) + explicit = ( + "[[Link#Section::Predicate:singlecol::Object]]", + Wikilink(link="Link", section="Section", predicate="Predicate:singlecol", object="Object") + ) def pad_garbage(string:str) -> str: @@ -135,9 +143,15 @@ def test_section(test_string, expected): assert len(wl) == 1 assert wl[0] == expected - -def test_triplet_full(): - pass +@pytest.mark.parametrize( + "test_string,expected", + [TestStr.implicit, TestStr.explicit]) +def test_triplets(test_string, expected): + test_string = pad_garbage(test_string) + wl = Wikilink.parse(test_string) + # pdb.set_trace() + assert len(wl) == 1 + assert wl[0] == expected def test_triplet_implicit_single(): """Test an implicit triplet in a single message""" diff --git a/wiki_postbot/patterns/wikilink.py b/wiki_postbot/patterns/wikilink.py index 7ad4ff2..0f2d838 100644 --- a/wiki_postbot/patterns/wikilink.py +++ b/wiki_postbot/patterns/wikilink.py @@ -62,13 +62,17 @@ class NBack: # combine into matches nb_wildcard = caret.suppress() + "*" + nb_wildcard.set_name("NBack - Wildcard") # start or end can be omitted if comma is present nb_full = nb_range + pp.Optional(integer("start")) + comma + pp.Optional(integer("end")) + rcurly + nb_full.set_name("NBack - Fully Specified") # if no comma present, it's just an end nb_end = nb_range + integer("end") + rcurly + nb_end.set_name("NBack - End Specified") # combine into full nback parser nback = pp.Group(nb_wildcard('wildcard') | nb_full | nb_end | caret("one")).set_results_name("nback") + nback.set_name("NBack Prefix") return nback def __eq__(self, other:'NBack'): @@ -123,7 +127,7 @@ class Wikilink(Pattern): def __init__( self, - link: str, + link: Optional[str] = None, nback: Optional[Union[NBack, tuple, dict]] = None, predicate: Optional[str] = None, object: Optional[str] = None, @@ -160,14 +164,50 @@ class Wikilink(Pattern): nback = NBack.make_parser() # main wikilink subject text - link = pp.Word(pp.printables+ " ", excludeChars="#[]{}|") + #link = pp.Word(pp.printables+ " ", excludeChars="#[]{}|:") + pp.Optional(pp.Literal(':')) + pp.Optional(pp.Word(pp.printables+ " ", excludeChars="#[]{}|:")) + # allow single, but not double colons + # "Look for a printable character and an optional colon that isn't a double colon, + # combine those. Then look for one or more instances of that, and combine that." + link = pp.Combine( + pp.OneOrMore( + pp.Combine( + pp.Word(pp.printables+ " ", excludeChars="#[]{}|:").set_name("Link Body") + \ + pp.Optional( + pp.Literal(':')+ ~pp.Literal(':') + ).set_name('Single Colon') + ) + ) + ) + link.set_name("Wikilink - Body") + # optional page section hash = pp.Literal("#").suppress() section = hash + link + section.set_name("Section") + + # combined they make a fully qualified link#section link + link_full = link("link") + pp.Optional(section("section")) + link_full.set_name("Wikilink - Full") + + #### SMW + # Predicate::Object with implicit subject + smw_delimiter = pp.Literal('::').suppress() + implicit_semantic = link("predicate") + smw_delimiter + link("object") + + # or + # Link::Predicate::Object with explicit subject + explicit_semantic = link_full + smw_delimiter + implicit_semantic + + ### Combine link bodies + # optionally matching depending on the form + link_bodies = explicit_semantic.set_name('Explicit Semantic Link') | implicit_semantic.set_name('Implicit Semantic Link') | link_full + # link_bodies = implicit_semantic # Combine all - parser = lbracket + pp.Optional(nback) + link("link") + pp.Optional(section("section")) + rbracket + #parser = lbracket + pp.Optional(nback) + link_full + rbracket + parser = lbracket + pp.Optional(nback) + link_bodies + rbracket + parser.set_name('Wikilink Parser') return parser @classmethod