Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatically generate both namespace index modules and the main index file (meaning the long list in `SUMMARY.md`) as part of `pre-commit`. The namespace index modules are generated by - Create a file if it does not exist - If there is no title, use the namespace but capitalize the first word and replace dashes with spaces. E.g. `orthogonal-factorization-systems` becomes "Orthogonal factorization systems" - If there is no Agda-block, create one, otherwise, capture the last Agda block in the file. (this is to preserve possible `OPTION` pragmas as in the case of `type-theories`. - Declare the namespace module, and import all files in the namespace folder publically and in alphabetic ordering. This assures that if there is a custom title or other text in the namespace index module from before (as in the case of `univalent-combinatorics`), then this is preserved. The main index file is generated as follows - Overwrite the previous file - Add title "Formalisation in Agda" - Add entry lists for each namespace. The title of a module is used for the entry, and the lists are sorted by title as well. Resolves #448. Written in collaboration with @jonaprieto. --------- Co-authored-by: Jonathan Cubides <jonaprieto@users.noreply.github.com>
- Loading branch information
1 parent
69530ce
commit ab482fc
Showing
31 changed files
with
1,290 additions
and
1,038 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#!/usr/bin/env python3 | ||
# Run this script: | ||
# $ python3 hooks/generate_main_index_file.py | ||
|
||
import os | ||
import sys | ||
import utils | ||
|
||
STATUS_FLAG_NO_TITLE = 1 | ||
STATUS_FLAG_DUPLICATE_TITLE = 2 | ||
|
||
entry_template = '- [{title}]({mdfile})' | ||
|
||
def generate_namespace_entry_list(namespace): | ||
status = 0 | ||
modules = sorted(os.listdir(os.path.join(root, namespace))) | ||
module_titles = tuple(map(lambda m: utils.get_lagda_file_title( | ||
os.path.join(root, namespace, m)), modules)) | ||
module_mdfiles = tuple( | ||
map(lambda m: utils.get_module_mdfile(namespace, m), modules)) | ||
|
||
# Check for missing titles | ||
for title, module in zip(module_titles, modules): | ||
if title is None: | ||
status |= STATUS_FLAG_NO_TITLE | ||
print(f"WARNING! {namespace}.{module} no title was found") | ||
|
||
# Check duplicate titles | ||
equal_titles = utils.get_equivalence_classes( | ||
lambda tf1, tf2: tf1[0] == tf2[0], zip(module_titles, modules)) | ||
equal_titles = tuple(filter(lambda ec: len( | ||
ec) > 1 and ec[0][0] is not None, equal_titles)) | ||
|
||
if (len(equal_titles) > 0): | ||
status |= STATUS_FLAG_DUPLICATE_TITLE | ||
print(f"WARNING! Duplicate titles in {namespace}:") | ||
for ec in equal_titles: | ||
print( | ||
f" Title '{ec[0][0]}': {', '.join(m[1][:m.rfind('.lagda.md')] for m in ec)}") | ||
|
||
module_titles_and_mdfiles = sorted( | ||
zip(module_titles, module_mdfiles), key=lambda tm: (tm[0].casefold(), tm[1])) | ||
|
||
entry_list = (' ' + entry_template.format(title=t, mdfile=md) | ||
for t, md in module_titles_and_mdfiles) | ||
|
||
namespace_title = utils.get_lagda_file_title( | ||
os.path.join(root, namespace) + ".lagda.md") | ||
namespace_entry = entry_template.format( | ||
title=namespace_title, mdfile=namespace + ".md") | ||
|
||
namespace_entry_list = namespace_entry + "\n" + "\n".join(entry_list) | ||
return namespace_entry_list, status | ||
|
||
def generate_index(root, header): | ||
status = 0 | ||
entry_lists = [] | ||
for namespace in sorted(utils.get_subdirectories_recursive(root)): | ||
entry_list, s = generate_namespace_entry_list(namespace) | ||
entry_lists.append(entry_list) | ||
status |= s | ||
|
||
index = f"{header}\n\n" + "\n\n".join(entry_lists) + "\n" | ||
return index, status | ||
|
||
if __name__ == "__main__": | ||
|
||
status = 0 | ||
root = "src" | ||
|
||
index_path = "MODULE-INDEX.md" | ||
index_header = "# Formalisation in Agda" | ||
|
||
index_content, status = generate_index(root, index_header) | ||
|
||
with open(index_path, "w") as index_file: | ||
index_file.write(index_content) | ||
|
||
sys.exit(status) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#!/usr/bin/env python3 | ||
# Run this script: | ||
# $ python3 hooks/generate_namespace_index_modules.py | ||
|
||
import os | ||
import pathlib | ||
import sys | ||
import utils | ||
|
||
def generate_title(namespace): | ||
return "# " + namespace.capitalize().replace("-", " ") + "\n" | ||
|
||
def generate_imports(root, namespace): | ||
namespace_path = os.path.join(root, namespace) | ||
agda_file_filter = lambda f: utils.isAgdaFile(pathlib.Path(os.path.join(namespace_path, f))) | ||
namespace_files = filter(agda_file_filter, os.listdir(namespace_path)) | ||
|
||
import_statements = (utils.get_import_statement(namespace, module_file, public=True) for module_file in namespace_files) | ||
return "\n".join(sorted(import_statements)) | ||
|
||
agda_block_template = \ | ||
'''```agda | ||
module {namespace} where | ||
{imports} | ||
``` | ||
''' | ||
|
||
def generate_agda_block(root, namespace): | ||
return agda_block_template.format(namespace=namespace, imports=generate_imports(root, namespace)) | ||
|
||
if __name__ == "__main__": | ||
|
||
status = 0 | ||
root = "src" | ||
|
||
for namespace in utils.get_subdirectories_recursive(root): | ||
namespace_filename = os.path.join(root, namespace) + ".lagda.md" | ||
with open(namespace_filename, "a+") as namespace_file: | ||
pass | ||
with open(namespace_filename, "r+") as namespace_file: | ||
contents = namespace_file.read() | ||
|
||
oldcontents = contents | ||
|
||
title_index = contents.find("# ") | ||
if title_index > 0: | ||
print( | ||
f"Warning! Namespace file {namespace_filename} has title after first line.") | ||
elif title_index == -1: # Missing title. Generate it | ||
contents = generate_title(namespace) + contents | ||
|
||
agda_block_start = contents.rfind("```agda\n") | ||
|
||
if agda_block_start == -1: | ||
# Must add agda block | ||
# Add at the end of the file | ||
contents += "\n" + generate_agda_block(root, namespace) | ||
else: | ||
agda_block_end = contents.find( | ||
"\n```\n", agda_block_start + len("```agda\n")) | ||
generated_block = generate_agda_block(root, namespace) | ||
|
||
if agda_block_end == -1: | ||
# An agda block is opened but not closed. | ||
# This is an error, but we can fix it | ||
print( | ||
f"WARNING! agda-block was opened but not closed in {namespace_filename}.") | ||
contents = contents[:agda_block_start] + generated_block | ||
else: | ||
agda_block_end += len("\n```\n") | ||
contents = contents[:agda_block_start] + generated_block + contents[agda_block_end:] | ||
|
||
if oldcontents != contents: | ||
status |= 1 | ||
with open(namespace_filename, "w") as f: | ||
f.write(contents) | ||
|
||
sys.exit(status) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.