From de007e333fcb855829088bf3f5fdb6b84bb14b43 Mon Sep 17 00:00:00 2001
From: Frank Sauerburger <frank@sauerburger.com>
Date: Thu, 3 Aug 2017 23:10:57 +0200
Subject: [PATCH] Implement executable script

Implement the doxec executable. In order to use nice callbacks between document
run() and doxec, a monitor function has been introduced.
---
 bin/doxec         | 30 +++++++++++++++++++++++++++++-
 doxec/__init__.py | 21 ++++++++++++++++++---
 2 files changed, 47 insertions(+), 4 deletions(-)
 mode change 100644 => 100755 bin/doxec

diff --git a/bin/doxec b/bin/doxec
old mode 100644
new mode 100755
index 5ca34f6..fa2f556
--- a/bin/doxec
+++ b/bin/doxec
@@ -1,6 +1,34 @@
 #!/usr/bin/env python3
 
 import argparse
+import doxec
 
 if __name__ == "__main__":
-    print("hello world.")
+    parser = argparse.ArgumentParser(
+        description="""
+        Run code examples written in a documentation file to ensure the
+        validity of the examples.
+        """)
+
+    parser.add_argument("--syntax", choices=doxec.parser.keys(),
+        default="markdown",
+        help="The syntax parser to be used for the listed files.")
+
+    parser.add_argument("documents", metavar="DOCUMENT", nargs="+", default=[],
+        help="A document from which the code examples should be parsed and "
+            "executed")
+
+    args = parser.parse_args()
+
+    parser = doxec.parser[args.syntax]
+
+    def monitor(op, exception):
+        print("running %s(%s) ... " % (op.command, op.args))
+        if exception is not None:
+            print(chr(27) + "[31m", end="")
+            print(exception, end="")
+            print(chr(27) + "[0m")
+
+    for doc_path in args.documents:
+        doc = doxec.Document(doc_path, syntax=parser)
+        doc.run(monitor=monitor)
diff --git a/doxec/__init__.py b/doxec/__init__.py
index 60b09d4..6c8c677 100644
--- a/doxec/__init__.py
+++ b/doxec/__init__.py
@@ -261,6 +261,9 @@ class Markdown(DoxecSyntax):
         # there was no end
         return None
 
+parser = {
+    "markdown": Markdown
+}
 
 class Document:
     """
@@ -295,9 +298,21 @@ class Document:
             self.operations.append(op_obj)
 
 
-    def run(self):
+    def run(self, monitor=None):
         """
-        Runs all operations stored attached to this object.
+        Runs all operations stored attached to this object. The monitor object
+        is called after every iteration. The first argument of monitor is the
+        operation object, the second argument is None or the exception that
+        occurred.
         """
         for op in self.operations:
-            op.execute()
+            try:
+                op.execute()
+            except TestException as e:
+                if callable(monitor):
+                    monitor(op, e)
+                else:
+                    raise e
+            else:
+                if callable(monitor):
+                    monitor(op, None)
-- 
GitLab