sphinx-to-rst.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #!/usr/bin/env python
  2. import os
  3. import re
  4. import sys
  5. dirname = ""
  6. RE_CODE_BLOCK = re.compile(r'.. code-block:: (.+?)\s*$')
  7. RE_INCLUDE = re.compile(r'.. include:: (.+?)\s*$')
  8. RE_REFERENCE = re.compile(r':(.+?):`(.+?)`')
  9. def include_file(lines, pos, match):
  10. global dirname
  11. orig_filename = match.groups()[0]
  12. filename = os.path.join(dirname, orig_filename)
  13. fh = open(filename)
  14. try:
  15. old_dirname = dirname
  16. dirname = os.path.dirname(orig_filename)
  17. try:
  18. lines[pos] = sphinx_to_rst(fh)
  19. finally:
  20. dirname = old_dirname
  21. finally:
  22. fh.close()
  23. def replace_code_block(lines, pos, match):
  24. lines[pos] = ""
  25. curpos = pos - 1
  26. # Find the first previous line with text to append "::" to it.
  27. while True:
  28. prev_line = lines[curpos]
  29. if not prev_line.isspace():
  30. prev_line_with_text = curpos
  31. break
  32. curpos -= 1
  33. if lines[prev_line_with_text].endswith(":"):
  34. lines[prev_line_with_text] += ":"
  35. else:
  36. lines[prev_line_with_text] += "::"
  37. TO_RST_MAP = {RE_CODE_BLOCK: replace_code_block,
  38. RE_REFERENCE: r'``\2``',
  39. RE_INCLUDE: include_file}
  40. def _process(lines):
  41. lines = list(lines) # non-destructive
  42. for i, line in enumerate(lines):
  43. for regex, alt in TO_RST_MAP.items():
  44. if callable(alt):
  45. match = regex.match(line)
  46. if match:
  47. alt(lines, i, match)
  48. line = lines[i]
  49. else:
  50. lines[i] = regex.sub(alt, line)
  51. return lines
  52. def sphinx_to_rst(fh):
  53. return "".join(_process(fh))
  54. if __name__ == "__main__":
  55. global dirname
  56. dirname = os.path.dirname(sys.argv[1])
  57. fh = open(sys.argv[1])
  58. try:
  59. print(sphinx_to_rst(fh))
  60. finally:
  61. fh.close()