src/Pure/PIDE/protocol_message.scala
changeset 59713 6da3efec20ca
child 71620 5a4ccef7f310
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/PIDE/protocol_message.scala	Mon Mar 16 11:07:56 2015 +0100
@@ -0,0 +1,84 @@
+/*  Title:      Pure/PIDE/protocol_message.scala
+    Author:     Makarius
+
+Auxiliary operations on protocol messages.
+*/
+
+package isabelle
+
+
+object Protocol_Message
+{
+  /* inlined reports */
+
+  private val report_elements =
+    Markup.Elements(Markup.REPORT, Markup.NO_REPORT)
+
+  def clean_reports(body: XML.Body): XML.Body =
+    body filter {
+      case XML.Wrapped_Elem(Markup(name, _), _, _) => !report_elements(name)
+      case XML.Elem(Markup(name, _), _) => !report_elements(name)
+      case _ => true
+    } map {
+      case XML.Wrapped_Elem(markup, body, ts) => XML.Wrapped_Elem(markup, body, clean_reports(ts))
+      case XML.Elem(markup, ts) => XML.Elem(markup, clean_reports(ts))
+      case t => t
+    }
+
+  def reports(props: Properties.T, body: XML.Body): List[XML.Elem] =
+    body flatMap {
+      case XML.Wrapped_Elem(Markup(Markup.REPORT, ps), body, ts) =>
+        List(XML.Wrapped_Elem(Markup(Markup.REPORT, props ::: ps), body, ts))
+      case XML.Elem(Markup(Markup.REPORT, ps), ts) =>
+        List(XML.Elem(Markup(Markup.REPORT, props ::: ps), ts))
+      case XML.Wrapped_Elem(_, _, ts) => reports(props, ts)
+      case XML.Elem(_, ts) => reports(props, ts)
+      case XML.Text(_) => Nil
+    }
+
+
+  /* reported positions */
+
+  private val position_elements =
+    Markup.Elements(Markup.BINDING, Markup.ENTITY, Markup.REPORT, Markup.POSITION)
+
+  def positions(
+    self_id: Document_ID.Generic => Boolean,
+    command_position: Position.T,
+    chunk_name: Symbol.Text_Chunk.Name,
+    chunk: Symbol.Text_Chunk,
+    message: XML.Elem): Set[Text.Range] =
+  {
+    def elem(props: Properties.T, set: Set[Text.Range]): Set[Text.Range] =
+      props match {
+        case Position.Identified(id, name) if self_id(id) && name == chunk_name =>
+          val opt_range =
+            Position.Range.unapply(props) orElse {
+              if (name == Symbol.Text_Chunk.Default)
+                Position.Range.unapply(command_position)
+              else None
+            }
+          opt_range match {
+            case Some(symbol_range) =>
+              chunk.incorporate(symbol_range) match {
+                case Some(range) => set + range
+                case _ => set
+              }
+            case None => set
+          }
+        case _ => set
+      }
+    def tree(set: Set[Text.Range], t: XML.Tree): Set[Text.Range] =
+      t match {
+        case XML.Wrapped_Elem(Markup(name, props), _, body) =>
+          body.foldLeft(if (position_elements(name)) elem(props, set) else set)(tree)
+        case XML.Elem(Markup(name, props), body) =>
+          body.foldLeft(if (position_elements(name)) elem(props, set) else set)(tree)
+        case XML.Text(_) => set
+      }
+
+    val set = tree(Set.empty, message)
+    if (set.isEmpty) elem(message.markup.properties, set)
+    else set
+  }
+}