verify_markdown_cpp.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/env python3
  2. """Compile every standalone C++ fenced block in course Markdown files."""
  3. from __future__ import annotations
  4. import re
  5. import subprocess
  6. import sys
  7. import tempfile
  8. from pathlib import Path
  9. def main() -> int:
  10. root = Path(sys.argv[1] if len(sys.argv) > 1 else "课程")
  11. documents = sorted(root.rglob("*.md"))
  12. failed = 0
  13. compiled = 0
  14. snippets = 0
  15. with tempfile.TemporaryDirectory(prefix="course-cpp-") as temp:
  16. directory = Path(temp)
  17. for source in sorted(Path("参考实现").rglob("*.cpp")):
  18. compiled += 1
  19. output = directory / f"attachment-{compiled}"
  20. result = subprocess.run(
  21. [
  22. "g++",
  23. "-std=c++17",
  24. "-Wall",
  25. "-Wextra",
  26. "-Wpedantic",
  27. str(source),
  28. "-o",
  29. str(output),
  30. ],
  31. text=True,
  32. capture_output=True,
  33. check=False,
  34. )
  35. if result.returncode != 0:
  36. failed += 1
  37. print(f"FAIL {source}", file=sys.stderr)
  38. print(result.stderr, file=sys.stderr)
  39. for document in documents:
  40. text = document.read_text(encoding="utf-8")
  41. blocks = re.findall(r"```(?:cpp|c\+\+)\n(.*?)```", text, flags=re.DOTALL)
  42. for index, code in enumerate(blocks, 1):
  43. if not re.search(r"\bint\s+main\s*\(", code):
  44. snippets += 1
  45. continue
  46. compiled += 1
  47. source = directory / f"block-{compiled}.cpp"
  48. output = directory / f"block-{compiled}"
  49. source.write_text(code, encoding="utf-8")
  50. result = subprocess.run(
  51. [
  52. "g++",
  53. "-std=c++17",
  54. "-Wall",
  55. "-Wextra",
  56. "-Wpedantic",
  57. str(source),
  58. "-o",
  59. str(output),
  60. ],
  61. text=True,
  62. capture_output=True,
  63. check=False,
  64. )
  65. if result.returncode != 0:
  66. failed += 1
  67. print(f"FAIL {document}:{index}", file=sys.stderr)
  68. print(result.stderr, file=sys.stderr)
  69. print(f"compiled={compiled} snippets_skipped={snippets} failed={failed}")
  70. return 1 if failed else 0
  71. if __name__ == "__main__":
  72. raise SystemExit(main())