diff --git a/redstring/library.py b/redstring/library.py index 30f38d7..6982937 100644 --- a/redstring/library.py +++ b/redstring/library.py @@ -2,7 +2,6 @@ Logic for operations that depend on a whole collection of documents. """ import os -from pathlib import Path from redstring.parser import load, TagOptions, DocumentTag, TabOptions, DocumentTab, Document @@ -11,16 +10,60 @@ def generate_index_document(directory: str) -> Document: """ Generate a document describing a document collection. """ - dirpath = Path(directory) - document_info: list = [] - for filename in os.listdir(dirpath): - with open(dirpath / filename) as f: - document = load(f) - document_id = document.get('id') - title = document.get('title') - document_info.append((document_id, title)) + categories: dict = {} - tag: DocumentTag = DocumentTag('Unsorted', str(document_info), TagOptions(), []) - tab: DocumentTab = DocumentTab('index', [tag], TabOptions()) - doc: Document = Document([tab]) - return doc + for filename in os.listdir(directory): + with open(os.path.join(directory, filename)) as f: + document: Document = load(f) + + # Check if this document specifies a tab, and create it if necessary. + category = document.get_tag('category') + if not category: + category = 'index' + if category not in categories: + categories[category] = {} + category_tab = categories[category] + + # Check if this document specifies a topic, and create it if necessary. + topic = document.get_tag('topic') + if not topic: + topic = 'uncategorized' + if '.' in topic: + topic, subtopic = topic.split('.', maxsplit=1) + else: + subtopic = None + if topic not in category_tab: + category_tab[topic] = [] + topic_tag = category_tab[topic] + + # Save the title and id. + doc_id = document.get_tag('id').value + if doc_title_tag := document.get_tag('title'): + doc_title = doc_title_tag.value + else: + doc_title = None + + topic_tag.append((doc_id, doc_title)) + + # Build an index document + def document_link(info): + doc_id, doc_title = info + return ( + f'{doc_title} ({doc_id})' + if doc_title else + f'{doc_id}' + ) + + built_tabs: list = [] + for category in sorted(categories.keys()): + built_tags: list = [] + + for topic in sorted(categories[category].keys()): + docs = sorted(categories[category][topic], key=lambda x: x[0]) + doc_links = map(document_link, docs) + value = '- ' + '
- '.join(doc_links) + built_tags.append(DocumentTag(topic, value, TagOptions(), [])) + + built_tabs.append(DocumentTab(category, built_tags, TabOptions())) + + return Document(built_tabs) diff --git a/redstring/parser.py b/redstring/parser.py index 8c4b920..7e23d92 100644 --- a/redstring/parser.py +++ b/redstring/parser.py @@ -130,6 +130,12 @@ class DocumentTab: self.tags: List[DocumentTag] = tags self.options: TabOptions = options + def get_tag(self, name: str): + for tag in self.tags: + if tag.name == name: + return tag + return None + class Document: """ @@ -141,7 +147,13 @@ class Document: def __iter__(self): return self.tabs.__iter__() - def get(self, name: str): + def get_tab(self, name: str): + for tab in self.tabs: + if tab.name == name: + return tab + return None + + def get_tag(self, name: str): for tab in self.tabs: for tag in tab.tags: if tag.name == name: