tools/split.py (79 lines of code) (raw):
import argparse
import os
import re
from typing import TextIO
def get_file_name(path: str) -> str:
idx = path.rfind("/")
return path[idx+1:]
def navigation_bar(f: TextIO, challenges: list[str], idx: int, home_file: str):
prv = get_file_name(challenges[idx - 1]) if idx > 0 else None
nxt = get_file_name(challenges[idx + 1]) if idx < (len(challenges) - 1) else None
oct_start = """<span class="navigation">{% octicon """
oct_end = " height:24 %}</span>"
dot = """<span class="navigation">{% octicon dot-fill %}</span>"""
write(f, "\n")
if prv:
write(f, f"[{oct_start}chevron-left{oct_end}Previous Challenge]({prv}) {dot} ")
write(f, f"**[{oct_start}home{oct_end}]({home_file})**")
if nxt:
write(f, f" {dot} [Next Challenge {oct_start}chevron-right{oct_end}]({nxt})")
write(f, "\n")
def write(f: TextIO, line: str) -> str:
f.write(line)
def process(filename: str, output_dir: str, student: bool):
with open(filename, "r") as f:
contents = iter(f.readlines())
curr_line = next(contents)
challenges_found = False
challenge_files = []
challenge_titles = []
os.makedirs(output_dir, exist_ok=True)
index_file = f"{output_dir}/README.md" if student else f"{output_dir}/solutions.md"
challenges_header = "## Challenges" if student else "## Coach's Guides"
with open(index_file, "w") as f:
while not challenges_found:
if curr_line.startswith(challenges_header):
challenges_found = True
else:
write(f, curr_line)
curr_line = next(contents)
first_challenge_found = False
while not first_challenge_found:
if curr_line.startswith("## Challenge "):
first_challenge_found = True
else:
matches = re.match(r"-\s+Challenge (\d+): (.+)$", curr_line)
if matches:
prefix = f"challenge-" if student else "solution-"
challenge_no = int(matches.group(1))
challenge_file = f"{prefix}{challenge_no:02d}.md"
challenge_title = matches.group(2)
challenge_files.append(f"{output_dir}/{challenge_file}")
challenge_titles.append(f"# Challenge {challenge_no}: {challenge_title}")
write(f, f"- Challenge {challenge_no}: **[{challenge_title}]({challenge_file})**\n")
else:
write(f, curr_line)
curr_line = next(contents)
home_file = "README.md" if student else "solutions.md"
for idx, challenge in enumerate(challenge_files):
with open(challenge, "w") as f:
write(f, f"{challenge_titles[idx]}\n")
# navigation top
navigation_bar(f, challenge_files, idx, home_file)
curr_line = next(contents, None)
next_challenge_found = False
while curr_line is not None and not next_challenge_found:
if curr_line.startswith("## Challenge "):
next_challenge_found = True
break
elif curr_line.startswith("#"):
write(f, curr_line[1:])
else:
write(f, curr_line)
curr_line = next(contents, None)
# navigation bottom
navigation_bar(f, challenge_files, idx, home_file)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--output-dir", default="outputs")
parser.add_argument("filename")
args = parser.parse_args()
process(args.filename, args.output_dir, True)