parse.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env python
  2. """
  3. CLI interface to markdown-it-py
  4. Parse one or more markdown files, convert each to HTML, and print to stdout.
  5. """
  6. from __future__ import annotations
  7. import argparse
  8. from collections.abc import Iterable, Sequence
  9. import sys
  10. from markdown_it import __version__
  11. from markdown_it.main import MarkdownIt
  12. version_str = "markdown-it-py [version {}]".format(__version__)
  13. def main(args: Sequence[str] | None = None) -> int:
  14. namespace = parse_args(args)
  15. if namespace.filenames:
  16. convert(namespace.filenames)
  17. else:
  18. interactive()
  19. return 0
  20. def convert(filenames: Iterable[str]) -> None:
  21. for filename in filenames:
  22. convert_file(filename)
  23. def convert_file(filename: str) -> None:
  24. """
  25. Parse a Markdown file and dump the output to stdout.
  26. """
  27. try:
  28. with open(filename, "r", encoding="utf8", errors="ignore") as fin:
  29. rendered = MarkdownIt().render(fin.read())
  30. print(rendered, end="")
  31. except OSError:
  32. sys.stderr.write(f'Cannot open file "{filename}".\n')
  33. sys.exit(1)
  34. def interactive() -> None:
  35. """
  36. Parse user input, dump to stdout, rinse and repeat.
  37. Python REPL style.
  38. """
  39. print_heading()
  40. contents = []
  41. more = False
  42. while True:
  43. try:
  44. prompt, more = ("... ", True) if more else (">>> ", True)
  45. contents.append(input(prompt) + "\n")
  46. except EOFError:
  47. print("\n" + MarkdownIt().render("\n".join(contents)), end="")
  48. more = False
  49. contents = []
  50. except KeyboardInterrupt:
  51. print("\nExiting.")
  52. break
  53. def parse_args(args: Sequence[str] | None) -> argparse.Namespace:
  54. """Parse input CLI arguments."""
  55. parser = argparse.ArgumentParser(
  56. description="Parse one or more markdown files, "
  57. "convert each to HTML, and print to stdout",
  58. # NOTE: Remember to update README.md w/ the output of `markdown-it -h`
  59. epilog=(
  60. f"""
  61. Interactive:
  62. $ markdown-it
  63. markdown-it-py [version {__version__}] (interactive)
  64. Type Ctrl-D to complete input, or Ctrl-C to exit.
  65. >>> # Example
  66. ... > markdown *input*
  67. ...
  68. <h1>Example</h1>
  69. <blockquote>
  70. <p>markdown <em>input</em></p>
  71. </blockquote>
  72. Batch:
  73. $ markdown-it README.md README.footer.md > index.html
  74. """
  75. ),
  76. formatter_class=argparse.RawDescriptionHelpFormatter,
  77. )
  78. parser.add_argument("-v", "--version", action="version", version=version_str)
  79. parser.add_argument(
  80. "filenames", nargs="*", help="specify an optional list of files to convert"
  81. )
  82. return parser.parse_args(args)
  83. def print_heading() -> None:
  84. print("{} (interactive)".format(version_str))
  85. print("Type Ctrl-D to complete input, or Ctrl-C to exit.")
  86. if __name__ == "__main__":
  87. exit_code = main(sys.argv[1:])
  88. sys.exit(exit_code)