src/Pure/Thy/markdown.ML
changeset 61595 3591274c607e
parent 61461 77c9643a6353
child 62529 8b7bdfc09f3b
--- a/src/Pure/Thy/markdown.ML	Fri Nov 06 23:31:11 2015 +0100
+++ b/src/Pure/Thy/markdown.ML	Fri Nov 06 23:31:50 2015 +0100
@@ -19,9 +19,9 @@
 
 signature MARKDOWN =
 sig
-  val is_control: Symbol.symbol -> bool
   datatype kind = Itemize | Enumerate | Description
   val print_kind: kind -> string
+  val is_control: Symbol.symbol -> bool
   type line
   val line_source: line -> Antiquote.text_antiquote list
   val line_is_item: line -> bool
@@ -39,9 +39,7 @@
 structure Markdown: MARKDOWN =
 struct
 
-(* document lines *)
-
-val is_control = member (op =) ["\\<^item>", "\\<^enum>", "\\<^descr>"];
+(* item kinds *)
 
 datatype kind = Itemize | Enumerate | Description;
 
@@ -49,6 +47,13 @@
   | print_kind Enumerate = "enumerate"
   | print_kind Description = "description";
 
+val kinds = [("item", Itemize), ("enum", Enumerate), ("descr", Description)];
+
+val is_control = member (op =) ["\\<^item>", "\\<^enum>", "\\<^descr>"];
+
+
+(* document lines *)
+
 datatype line =
   Line of
    {source: Antiquote.text_antiquote list,
@@ -84,19 +89,22 @@
 fun is_space ((s, _): Symbol_Pos.T) = s = Symbol.space;
 val is_empty = forall (fn Antiquote.Text ss => forall is_space ss | _ => false);
 
-val scan_marker =
-  Scan.many is_space -- Symbol_Pos.scan_pos --
-  Scan.option
-   (Symbol_Pos.$$ "\\<^item>" >> K Itemize ||
-    Symbol_Pos.$$ "\\<^enum>" >> K Enumerate ||
-    Symbol_Pos.$$ "\\<^descr>" >> K Description) --| Scan.many is_space
-  >> (fn ((sp, pos), item) => (length sp, item, if is_some item then pos else Position.none));
+fun strip_spaces (Antiquote.Text ss :: rest) =
+      let val (sp, ss') = take_prefix is_space ss
+      in (length sp, if null ss' then rest else Antiquote.Text ss' :: rest) end
+  | strip_spaces source = (0, source);
 
-fun read_marker (Antiquote.Text ss :: rest) =
-      (case Scan.finite Symbol_Pos.stopper scan_marker ss of
-        (marker, []) => (marker, rest)
-      | (marker, ss') => (marker, Antiquote.Text ss' :: rest))
-  | read_marker source = ((0, NONE, Position.none), source);
+fun read_marker source =
+  let val (indent, source') = strip_spaces source in
+    (case source' of
+      (control as Antiquote.Control {name = (name, pos), body = [], ...}) :: rest =>
+        let
+          val item = AList.lookup (op =) kinds name;
+          val item_pos = if is_some item then pos else Position.none;
+          val (_, rest') = strip_spaces (if is_some item then rest else control :: rest);
+        in ((indent, item, item_pos), rest') end
+    | _ => ((indent, NONE, Position.none), source'))
+  end;
 
 in