sphinx-to-rst.py 1.9 KB

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