more general / abstract Command.Markups, with separate index for status elements;
authorwenzelm
Fri, 21 Feb 2014 15:12:50 +0100 (2014-02-21)
changeset 55649 1532ab0dc67b
parent 55648 38f264741609
child 55650 349afd0fa0c4
more general / abstract Command.Markups, with separate index for status elements; slightly faster Rendering.overview_color;
src/Pure/PIDE/command.scala
src/Pure/PIDE/document.scala
src/Tools/jEdit/src/rendering.scala
--- a/src/Pure/PIDE/command.scala	Fri Feb 21 13:36:40 2014 +0100
+++ b/src/Pure/PIDE/command.scala	Fri Feb 21 15:12:50 2014 +0100
@@ -56,18 +56,59 @@
   }
 
 
+  /* markup */
+
+  object Markup_Index
+  {
+    val markup: Markup_Index = Markup_Index(false, "")
+  }
+
+  sealed case class Markup_Index(status: Boolean, file_name: String)
+
+  object Markups
+  {
+    val empty: Markups = new Markups(Map.empty)
+
+    def init(markup: Markup_Tree): Markups =
+      new Markups(Map(Markup_Index.markup -> markup))
+  }
+
+  final class Markups private(private val rep: Map[Markup_Index, Markup_Tree])
+  {
+    def apply(index: Markup_Index): Markup_Tree =
+      rep.getOrElse(index, Markup_Tree.empty)
+
+    def add(index: Markup_Index, markup: Text.Markup): Markups =
+      new Markups(rep + (index -> (this(index) + markup)))
+
+    def ++ (other: Markups): Markups =
+      new Markups(
+        (rep.keySet ++ other.rep.keySet)
+          .map(index => index -> (this(index) ++ other(index))).toMap)
+
+    override def hashCode: Int = rep.hashCode
+    override def equals(that: Any): Boolean =
+      that match {
+        case other: Markups => rep == other.rep
+        case _ => false
+      }
+    override def toString: String = rep.iterator.mkString("Markups(", ", ", ")")
+  }
+
+
   /* state */
 
   sealed case class State(
     command: Command,
     status: List[Markup] = Nil,
     results: Results = Results.empty,
-    markups: Map[String, Markup_Tree] = Map.empty)
+    markups: Markups = Markups.empty)
   {
-    def get_markup(file_name: String): Markup_Tree =
-      markups.getOrElse(file_name, Markup_Tree.empty)
+    /* markup */
 
-    def markup: Markup_Tree = get_markup("")
+    def get_markup(index: Markup_Index): Markup_Tree = markups(index)
+
+    def markup: Markup_Tree = get_markup(Markup_Index.markup)
 
     def markup_to_XML(filter: XML.Elem => Boolean): XML.Body =
       markup.to_XML(command.range, command.source, filter)
@@ -81,10 +122,17 @@
       results == other.results &&
       markups == other.markups
 
-    private def add_status(st: Markup): State = copy(status = st :: status)
+    private def add_status(st: Markup): State =
+      copy(status = st :: status)
 
-    private def add_markup(file_name: String, m: Text.Markup): State =
-      copy(markups = markups + (file_name -> (get_markup(file_name) + m)))
+    private def add_markup(status: Boolean, file_name: String, m: Text.Markup): State =
+    {
+      val markups1 =
+        if (status || Protocol.status_elements(m.info.name))
+          markups.add(Markup_Index(true, file_name), m)
+        else markups
+      copy(markups = markups1.add(Markup_Index(false, file_name), m))
+    }
 
     def + (alt_id: Document_ID.Generic, message: XML.Elem): State =
       message match {
@@ -92,8 +140,9 @@
           (this /: msgs)((state, msg) =>
             msg match {
               case elem @ XML.Elem(markup, Nil) =>
-                state.add_status(markup).add_markup("", Text.Info(command.proper_range, elem))
-
+                state.
+                  add_status(markup).
+                  add_markup(true, "", Text.Info(command.proper_range, elem))
               case _ =>
                 System.err.println("Ignored status message: " + msg)
                 state
@@ -113,8 +162,8 @@
                         case Some(range) =>
                           if (!range.is_singularity) {
                             val props = Position.purge(atts)
-                            state.add_markup(file_name,
-                              Text.Info(range, XML.Elem(Markup(name, props), args)))
+                            val info = Text.Info(range, XML.Elem(Markup(name, props), args))
+                            state.add_markup(false, file_name, info)
                           }
                           else state
                         case None => bad(); state
@@ -127,7 +176,7 @@
                   val range = command.proper_range
                   val props = Position.purge(atts)
                   val info: Text.Markup = Text.Info(range, XML.Elem(Markup(name, props), args))
-                  state.add_markup("", info)
+                  state.add_markup(false, "", info)
 
                 case _ => /* FIXME bad(); */ state
               }
@@ -143,7 +192,7 @@
                 for {
                   (file_name, chunk) <- command.chunks
                   range <- Protocol.message_positions(command.id, alt_id, chunk, message)
-                } st = st.add_markup(file_name, Text.Info(range, message2))
+                } st = st.add_markup(false, file_name, Text.Info(range, message2))
               }
               st
 
@@ -157,9 +206,7 @@
       copy(
         status = other.status ::: status,
         results = results ++ other.results,
-        markups =
-          (markups.keySet ++ other.markups.keySet)
-            .map(a => a -> (get_markup(a) ++ other.get_markup(a))).toMap
+        markups = markups ++ other.markups
       )
   }
 
@@ -324,7 +371,7 @@
   /* accumulated results */
 
   val init_state: Command.State =
-    Command.State(this, results = init_results, markups = Map("" -> init_markup))
+    Command.State(this, results = init_results, markups = Command.Markups.init(init_markup))
 
   val empty_state: Command.State = Command.State(this)
 }
--- a/src/Pure/PIDE/document.scala	Fri Feb 21 13:36:40 2014 +0100
+++ b/src/Pure/PIDE/document.scala	Fri Feb 21 15:12:50 2014 +0100
@@ -357,6 +357,7 @@
     val state: State
     val version: Version
     val is_outdated: Boolean
+
     def convert(i: Text.Offset): Text.Offset
     def revert(i: Text.Offset): Text.Offset
     def convert(range: Text.Range): Text.Range
@@ -366,6 +367,16 @@
     val node: Node
     val thy_load_commands: List[Command]
     def eq_content(other: Snapshot): Boolean
+
+    def cumulate_status[A](
+      range: Text.Range,
+      info: A,
+      elements: String => Boolean,
+      result: Command.State => (A, Text.Markup) => Option[A]): List[Text.Info[A]]
+    def select_status[A](
+      range: Text.Range,
+      elements: String => Boolean,
+      result: Command.State => Text.Markup => Option[A]): List[Text.Info[A]]
     def cumulate_markup[A](
       range: Text.Range,
       info: A,
@@ -601,14 +612,14 @@
         val version = stable.version.get_finished
         val is_outdated = !(pending_edits.isEmpty && latest == stable)
 
+
+        /* local node content */
+
         def convert(offset: Text.Offset) = (offset /: edits)((i, edit) => edit.convert(i))
         def revert(offset: Text.Offset) = (offset /: reverse_edits)((i, edit) => edit.revert(i))
         def convert(range: Text.Range) = (range /: edits)((r, edit) => edit.convert(r))
         def revert(range: Text.Range) = (range /: reverse_edits)((r, edit) => edit.revert(r))
 
-
-        /* local node content */
-
         val node_name = name
         val node = version.nodes(name)
 
@@ -629,37 +640,47 @@
           (thy_load_commands zip other.thy_load_commands).forall(eq_commands)
         }
 
-        def cumulate_markup[A](range: Text.Range, info: A, elements: String => Boolean,
+
+        /* cumulate markup */
+
+        private def cumulate[A](
+          status: Boolean,
+          range: Text.Range,
+          info: A,
+          elements: String => Boolean,
           result: Command.State => (A, Text.Markup) => Option[A]): List[Text.Info[A]] =
         {
           val former_range = revert(range)
           thy_load_commands match {
             case thy_load_command :: _ =>
               val file_name = node_name.node
+              val markup_index = Command.Markup_Index(status, file_name)
               (for {
                 chunk <- thy_load_command.chunks.get(file_name).iterator
                 st = state.command_state(version, thy_load_command)
                 res = result(st)
-                Text.Info(r0, a) <- st.get_markup(file_name).cumulate[A](
+                Text.Info(r0, a) <- st.get_markup(markup_index).cumulate[A](
                   former_range.restrict(chunk.range), info, elements,
                   { case (a, Text.Info(r0, b)) => res(a, Text.Info(convert(r0), b)) }
                 ).iterator
               } yield Text.Info(convert(r0), a)).toList
 
             case _ =>
+              val markup_index = Command.Markup_Index(status, "")
               (for {
                 (command, command_start) <- node.command_range(former_range)
                 st = state.command_state(version, command)
                 res = result(st)
-                Text.Info(r0, a) <- st.markup.cumulate[A](
+                Text.Info(r0, a) <- st.get_markup(markup_index).cumulate[A](
                   (former_range - command_start).restrict(command.range), info, elements,
-                  { case (a, Text.Info(r0, b)) => res(a, Text.Info(convert(r0 + command_start), b)) }
-                ).iterator
+                  {
+                    case (a, Text.Info(r0, b)) => res(a, Text.Info(convert(r0 + command_start), b))
+                  }).iterator
               } yield Text.Info(convert(r0 + command_start), a)).toList
           }
         }
 
-        def select_markup[A](range: Text.Range, elements: String => Boolean,
+        private def select[A](status: Boolean, range: Text.Range, elements: String => Boolean,
           result: Command.State => Text.Markup => Option[A]): List[Text.Info[A]] =
         {
           def result1(st: Command.State): (Option[A], Text.Markup) => Option[Option[A]] =
@@ -674,6 +695,22 @@
           for (Text.Info(r, Some(x)) <- cumulate_markup(range, None, elements, result1 _))
             yield Text.Info(r, x)
         }
+
+        def cumulate_status[A](range: Text.Range, info: A, elements: String => Boolean,
+            result: Command.State => (A, Text.Markup) => Option[A]): List[Text.Info[A]] =
+          cumulate(true, range, info, elements, result)
+
+        def select_status[A](range: Text.Range, elements: String => Boolean,
+            result: Command.State => Text.Markup => Option[A]): List[Text.Info[A]] =
+          select(true, range, elements, result)
+
+        def cumulate_markup[A](range: Text.Range, info: A, elements: String => Boolean,
+            result: Command.State => (A, Text.Markup) => Option[A]): List[Text.Info[A]] =
+          cumulate(false, range, info, elements, result)
+
+        def select_markup[A](range: Text.Range, elements: String => Boolean,
+            result: Command.State => Text.Markup => Option[A]): List[Text.Info[A]] =
+          select(false, range, elements, result)
       }
     }
   }
--- a/src/Tools/jEdit/src/rendering.scala	Fri Feb 21 13:36:40 2014 +0100
+++ b/src/Tools/jEdit/src/rendering.scala	Fri Feb 21 15:12:50 2014 +0100
@@ -301,7 +301,7 @@
     if (snapshot.is_outdated) None
     else {
       val results =
-        snapshot.cumulate_markup[(Protocol.Status, Int)](
+        snapshot.cumulate_status[(Protocol.Status, Int)](
           range, (Protocol.Status.init, 0), Protocol.status_elements, _ =>
           {
             case ((status, pri), Text.Info(_, elem)) =>