This commit is contained in:
Francesco Mecca 2023-05-11 11:07:49 +02:00
parent 7aaa5663c2
commit a25d3df0f2

View File

@ -1,6 +1,12 @@
import glob import glob
import re
from typing import TypeVar, Iterator
T = TypeVar("T")
class WikiArticle: class WikiArticle:
'''Abstract class that defines an article in the wiki'''
def __init__(self, filename): def __init__(self, filename):
def tags(content): def tags(content):
for line in content: for line in content:
@ -24,12 +30,19 @@ class WikiArticle:
self.title = title(content) self.title = title(content)
self.tags = tags(content) self.tags = tags(content)
self.filename = filename self.filename = filename
def enrich(self, articles: Iterator):
raise NotImplementedError()
def __repr__(self): def __repr__(self):
return f'{type(self).__name__}({self.title}, {self.filename}, {self.tags})' return f'{type(self).__name__}({self.title}, {self.filename}, {self.tags})'
class ContentArticle(WikiArticle): pass class ContentArticle(WikiArticle):
'''The articles we wrote'''
pass
class MetaPage(WikiArticle): class MetaPage(WikiArticle):
'''Wiki article containing code that must be generated by this program'''
def __init__(self, filename): def __init__(self, filename):
self.header = '** Pages in this category' self.header = '** Pages in this category'
super().__init__(filename) super().__init__(filename)
@ -41,14 +54,15 @@ class MetaPage(WikiArticle):
if len(correct_section) != 1: if len(correct_section) != 1:
raise Exception(f'Invalid meta section in {filename}') raise Exception(f'Invalid meta section in {filename}')
def replace_content(self, wikiarticles): def enrich(self, linked_articles: Iterator[WikiArticle]):
'''Generator that returns content that will end up in the document before html conversion'''
content = map(identity, self.content) content = map(identity, self.content)
def rep(): def rep():
for line in content: for line in content:
if line == self.header: break if line == self.header: break
else: yield line else: yield line
yield self.header yield self.header
for w in wikiarticles: for w in linked_articles:
yield f'- [[../{w.filename}][{w.title}]]' yield f'- [[../{w.filename}][{w.title}]]'
return rep() return rep()
@ -64,26 +78,47 @@ def files():
def metafiles(): def metafiles():
return glob.glob('meta/*.org') return glob.glob('meta/*.org')
def invert_map(map_: list[ContentArticle]):
def invert_map(map_: list[WikiArticle]):
'''from {a: [1, 2], b: [2, 3]} to {1: [a], 2: [a, b], 3: [b]}''' '''from {a: [1, 2], b: [2, 3]} to {1: [a], 2: [a, b], 3: [b]}'''
keys = set(i for e in map_ for i in e.tags) keys = set(i for e in map_ for i in e.tags)
res = dict() res: dict[str, list[WikiArticle]] = dict()
for k in keys: for k in keys:
res[k] = res.get(k, []) + [w for w in map_ if k in w.tags] res[k] = res.get(k, []) + [w for w in map_ if k in w.tags]
return res return res
def write_meta_page(m: MetaPage, content: list[str]): def links(article: ContentArticle):
def haslink(line):
return re.findall(r'\[\[(.+?)\]\]', line)
def yield_links(line):
i = 0
while i < len(line)-1:
sub = line[i:]
if sub.startswith('[[./') and ']]' in sub and '.org' in sub: # org link to one org file
ridx = sub.index('.org')
yield sub[:ridx+4]
i += sub.index(']]')
i += 1
for line in article.content:
if haslink(line):
yield from yield_links(line)
def writetodisk(m: WikiArticle, content: list[str]):
with open(m.filename, 'w') as f: with open(m.filename, 'w') as f:
f.writelines(map(lambda l: l+'\n', content)) f.writelines(map(lambda l: l+'\n', content))
if __name__ == '__main__': if __name__ == '__main__':
files = [ContentArticle(f) for f in files()] files_ = [ContentArticle(f) for f in files()]
meta = [MetaPage(f) for f in metafiles()] meta_ = [MetaPage(f) for f in metafiles()]
meta = {m.meta: m for m in meta} meta = {m.meta: m for m in meta_}
print(meta)
tags = invert_map(files) tags = invert_map(files_)
for t, articles in tags.items(): for t, articles in tags.items():
if t in meta: if t in meta:
newcontent = meta[t].replace_content(articles) newcontent = meta[t].enrich(articles)
write_meta_page(meta[t], newcontent) writetodisk(meta[t], newcontent)
for a in files_:
print(a, links(a))