render_examples.sh (3358B)
1 #!/usr/bin/env bash 2 set -euo pipefail 3 4 README_FILE="${1:-README.md}" 5 6 if [[ ! -f "${README_FILE}" ]]; then 7 echo "README file not found: ${README_FILE}" >&2 8 exit 1 9 fi 10 11 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 12 REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" 13 EXAMPLES_DIR="${REPO_ROOT}/examples" 14 15 python3 - "$README_FILE" "$EXAMPLES_DIR" <<'PY' 16 import sys 17 import os 18 from pathlib import Path 19 20 readme_path = Path(sys.argv[1]) 21 examples_dir = Path(sys.argv[2]) 22 23 # --------------------------------------------------------------------------- 24 # Build a tree-style listing for a given directory (mirrors `tree .` output). 25 # Hidden files/dirs (dot-prefixed) are included since .jci is relevant. 26 # --------------------------------------------------------------------------- 27 def build_tree(root: Path) -> str: 28 lines = ["."] 29 30 def walk(directory: Path, prefix: str): 31 entries = sorted( 32 directory.iterdir(), 33 key=lambda p: (p.is_file(), p.name), 34 ) 35 for idx, entry in enumerate(entries): 36 connector = "└── " if idx == len(entries) - 1 else "├── " 37 lines.append(f"{prefix}{connector}{entry.name}") 38 if entry.is_dir(): 39 extension = " " if idx == len(entries) - 1 else "│ " 40 walk(entry, prefix + extension) 41 42 walk(root, "") 43 return "\n".join(lines) 44 45 46 # --------------------------------------------------------------------------- 47 # Collect examples 48 # --------------------------------------------------------------------------- 49 examples = sorted( 50 [d for d in examples_dir.iterdir() if d.is_dir()], 51 key=lambda d: d.name, 52 ) 53 54 section_lines = ["## Examples", ""] 55 56 for example in examples: 57 # Header: derive a readable title from the folder name 58 name = example.name 59 # Strip leading digits+dash prefix (e.g. "00-", "13-") for the title 60 parts = name.split("-", 1) 61 title = parts[1].replace("-", " ").title() if len(parts) == 2 and parts[0].isdigit() else name 62 section_lines.append(f"### {title}") 63 section_lines.append("") 64 65 run_sh = example / ".jci" / "run.sh" 66 67 # Single fenced block with tree output + run.sh contents 68 section_lines.append("```") 69 section_lines.append("$ tree .") 70 section_lines.append(build_tree(example)) 71 72 if run_sh.exists(): 73 section_lines.append("") 74 section_lines.append("") 75 section_lines.append("$ cat .jci/run.sh") 76 section_lines.append(run_sh.read_text(encoding="utf-8").rstrip()) 77 78 section_lines.append("```") 79 section_lines.append("") 80 81 # --------------------------------------------------------------------------- 82 # Replace the ## Examples section (everything from that heading to EOF) 83 # --------------------------------------------------------------------------- 84 text = readme_path.read_text(encoding="utf-8") 85 lines = text.splitlines() 86 87 examples_heading_idx = next( 88 (i for i, l in enumerate(lines) if l.strip() == "## Examples"), 89 None, 90 ) 91 if examples_heading_idx is None: 92 raise SystemExit("Could not find '## Examples' heading in README") 93 94 new_lines = lines[:examples_heading_idx] + section_lines 95 new_text = "\n".join(new_lines) 96 if not new_text.endswith("\n"): 97 new_text += "\n" 98 99 readme_path.write_text(new_text, encoding="utf-8") 100 print(f"Rendered {len(examples)} examples into {readme_path}") 101 PY