src/Pure/System/progress.scala
changeset 83266 2f75f2495e3e
parent 83229 ad2b6030cb9c
child 83269 f6de20fbf55f
--- a/src/Pure/System/progress.scala	Sat Oct 11 16:19:16 2025 +0200
+++ b/src/Pure/System/progress.scala	Sun Oct 12 15:11:29 2025 +0200
@@ -8,6 +8,7 @@
 
 
 import java.util.{Map => JMap}
+import scala.collection.mutable
 
 
 object Progress {
@@ -57,10 +58,6 @@
     session: String = "",
     old: Option[Document_Status.Nodes_Status] = None
   ) {
-    def message: Message =
-      Message(Kind.writeln, cat_lines(domain.map(name => theory(name).message.text)),
-        verbose = true)
-
     def apply(name: Document.Node.Name): Document_Status.Node_Status =
       document_status(name)
 
@@ -70,6 +67,61 @@
         percentage = Some(node_status.percentage),
         total_time = node_status.total_timing.elapsed)
     }
+
+    def theory_progress(name: Document.Node.Name, check: (Int, Int) => Boolean): Option[Theory] = {
+      val old_percentage = if (old.isEmpty) 0 else old.get(name).percentage
+      val thy = theory(name)
+      if (check(old_percentage, thy.percentage.getOrElse(0))) Some(thy) else None
+    }
+
+    def completed_theories: List[Theory] =
+      domain.flatMap(theory_progress(_, (p0, p) => p0 != p && p == 100))
+
+    def status_theories: List[Theory] = {
+      val res = new mutable.ListBuffer[Theory]
+      // pending theories
+      for (name <- domain; thy <- theory_progress(name, (p0, p) => p0 == p && p > 0)) res += thy
+      // running theories
+      for (name <- domain; thy <- theory_progress(name, (p0, p) => p0 != p && p < 100)) res += thy
+      res.toList
+    }
+  }
+
+
+  /* status lines (e.g. at bottom of output) */
+
+  trait Status extends Progress {
+    def status_enabled: Boolean = false
+    def status_hide(theories: List[Theory]): Unit = ()
+
+    protected var status_theories: List[Theory] = Nil
+
+    def status_clear(): List[Theory] = synchronized {
+      val theories = status_theories
+      status_theories = Nil
+      status_hide(theories)
+      theories
+    }
+
+    def status_output(theories: List[Theory]): Unit = synchronized {
+      status_theories = Nil
+      theories.foreach(theory)
+      status_theories = theories
+    }
+
+    override def output(message: Progress.Message): Unit = synchronized {
+      if (do_output(message)) {
+        val theories = status_clear()
+        super.output(message)
+        status_output(theories)
+      }
+    }
+
+    override def nodes_status(nodes_status: Progress.Nodes_Status): Unit = synchronized {
+      status_clear()
+      nodes_status.completed_theories.foreach(theory)
+      status_output(if (status_enabled) nodes_status.status_theories else Nil)
+    }
   }
 }
 
@@ -136,8 +188,16 @@
   }
 }
 
-class Console_Progress(override val verbose: Boolean = false, stderr: Boolean = false)
-extends Progress {
+class Console_Progress(
+  override val verbose: Boolean = false,
+  detailed: Boolean = false,
+  stderr: Boolean = false)
+extends Progress with Progress.Status {
+  override def status_enabled: Boolean = detailed
+  override def status_hide(theories: List[Progress.Theory]): Unit = synchronized {
+    Output.delete_lines(theories.length, stdout = !stderr)
+  }
+
   override def output(message: Progress.Message): Unit = synchronized {
     if (do_output(message)) {
       Output.output(message.output_text, stdout = !stderr, include_empty = true)