Skip to content

Commit

Permalink
feat: checking cross-references
Browse files Browse the repository at this point in the history
  • Loading branch information
gvwilson committed Apr 5, 2024
1 parent 0bf7586 commit 6f74504
Showing 1 changed file with 42 additions and 16 deletions.
58 changes: 42 additions & 16 deletions lib/mccole/bin/lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import ark
import importlib.util
from pathlib import Path
import re
import shortcodes
Expand All @@ -10,47 +11,44 @@

def main():
options = parse_args()
options.config = load_config(options)
found = collect_actual(options)
for func in [
check_bib,
check_fig,
check_gloss,
check_tbl,
check_xref,
]:
func(options, found)


def check_bib(options, found):
"""Check bibliography citations."""
expected = get_bib_keys(options)
check_keys("bibliography", expected, found["bib"])
compare_keys("bibliography", expected, found["bib"])


def check_fig(options, found):
"""Check figure definitions and citations."""
check_keys("figure", set(found["fig_def"].keys()), found["fig_ref"])
compare_keys("figure", set(found["fig_def"].keys()), found["fig_ref"])


def check_gloss(options, found):
"""Check glossary citations."""
expected = get_gloss_keys(options)
check_keys("gloss", expected, found["gloss"])


def check_keys(kind, expected, actual):
"""Check two sets of keys."""
for key, slugs in actual.items():
if key not in expected:
print(f"unknown {kind} key {key} used in {listify(slugs)}")
else:
expected.remove(key)
if expected:
print(f"unused {kind} keys {listify(expected)}")
compare_keys("gloss", expected, found["gloss"])


def check_tbl(options, found):
"""Check table definitions and citations."""
check_keys("table", set(found["tbl_def"].keys()), found["tbl_ref"])
compare_keys("table", set(found["tbl_def"].keys()), found["tbl_ref"])


def check_xref(options, found):
"""Check chapter/appendix cross-references."""
expected = options.config.chapters + options.config.appendices
compare_keys("cross-ref", expected, found["xref"], unused=False)


def collect_actual(options):
Expand All @@ -62,13 +60,15 @@ def collect_actual(options):
parser.register(collect_gloss, "g")
parser.register(collect_tbl_def, "table")
parser.register(collect_tbl_ref, "t")
parser.register(collect_xref, "x")
collected = {
"bib": {},
"fig_def": {},
"fig_ref": {},
"gloss": {},
"tbl_def": {},
"tbl_ref": {},
"xref": {},
}
ark.nodes.root().walk(
lambda node: collect_visitor(node, parser, collected)
Expand Down Expand Up @@ -114,6 +114,11 @@ def collect_tbl_ref(pargs, kwargs, found):
found["tbl_ref"].add(pargs[0])


def collect_xref(pargs, kwargs, found):
"""Collect data from a cross-reference shortcode."""
found["xref"].add(pargs[0])


def collect_visitor(node, parser, collected):
"""Visit each node, collecting data."""
found = {
Expand All @@ -123,12 +128,24 @@ def collect_visitor(node, parser, collected):
"gloss": set(),
"tbl_def": set(),
"tbl_ref": set(),
"xref": set(),
}
parser.parse(node.text, found)
for kind in found:
reorganize_found(node, kind, collected, found)


def compare_keys(kind, expected, actual, unused=True):
"""Check two sets of keys."""
for key, slugs in actual.items():
if key not in expected:
print(f"unknown {kind} key {key} used in {listify(slugs)}")
else:
expected.remove(key)
if unused and expected:
print(f"unused {kind} keys {listify(expected)}")


def get_bib_keys(options):
"""Get actual bibliography keys."""
text = Path(options.root, "info", "bibliography.bib").read_text()
Expand All @@ -149,6 +166,15 @@ def listify(values):
return ", ".join(sorted(list(values)))


def load_config(options):
"""Load configuration file as module."""
filename = Path(options.root, "config.py")
spec = importlib.util.spec_from_file_location("config", filename)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


def parse_args():
"""Parse arguments."""
parser = argparse.ArgumentParser()
Expand All @@ -163,7 +189,7 @@ def reorganize_found(node, kind, collected, found):
for key in found[kind]:
if key not in collected[kind]:
collected[kind][key] = set()
collected[kind][key].add(node.slug)
collected[kind][key].add(node.slug if node.slug else "@root")


if __name__ == "__main__":
Expand Down

0 comments on commit 6f74504

Please sign in to comment.