| author | wenzelm | 
| Fri, 04 Apr 2025 16:35:05 +0200 | |
| changeset 82432 | 314d6b215f90 | 
| parent 81392 | 92aa6f7b470c | 
| child 83269 | f6de20fbf55f | 
| permissions | -rw-r--r-- | 
| 79873 | 1 | /* Title: Pure/System/program_progress.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Structured program progress. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 10 | object Program_Progress {
 | |
| 11 |   class Program private[Program_Progress](heading: String, title: String) {
 | |
| 12 | private val output_buffer = new StringBuffer(256) // synchronized | |
| 13 | ||
| 14 |     def output(message: Progress.Message): Unit = synchronized {
 | |
| 15 |       if (output_buffer.length() > 0) output_buffer.append('\n')
 | |
| 16 | output_buffer.append(message.output_text) | |
| 17 | } | |
| 18 | ||
| 19 | val start_time: Time = Time.now() | |
| 20 | private var stop_time: Option[Time] = None | |
| 21 |     def stop_now(): Unit = synchronized { stop_time = Some(Time.now()) }
 | |
| 22 | ||
| 81392 
92aa6f7b470c
clarified output representation: postpone Pretty.separate;
 wenzelm parents: 
79873diff
changeset | 23 |     def output(): (Command.Results, XML.Elem) = synchronized {
 | 
| 79873 | 24 | val output_text = output_buffer.toString | 
| 25 | val elapsed_time = stop_time.map(t => t - start_time) | |
| 26 | ||
| 27 | val message_prefix = heading + " " | |
| 28 | val message_suffix = | |
| 29 |         elapsed_time match {
 | |
| 30 | case None => " ..." | |
| 31 |           case Some(t) => " ... (" + t.message + " elapsed time)"
 | |
| 32 | } | |
| 33 | ||
| 34 | val (results, message) = | |
| 35 |         if (output_text.isEmpty) {
 | |
| 36 | (Command.Results.empty, XML.string(message_prefix + title + message_suffix)) | |
| 37 | } | |
| 38 |         else {
 | |
| 39 | val i = Document_ID.make() | |
| 40 | val results = Command.Results.make(List(i -> Protocol.writeln_message(output_text))) | |
| 41 | val message = | |
| 42 | XML.string(message_prefix) ::: | |
| 43 | List(XML.Elem(Markup(Markup.WRITELN, Markup.Serial(i)), XML.string(title))) ::: | |
| 44 | XML.string(message_suffix) | |
| 45 | (results, message) | |
| 46 | } | |
| 47 | ||
| 81392 
92aa6f7b470c
clarified output representation: postpone Pretty.separate;
 wenzelm parents: 
79873diff
changeset | 48 | (results, XML.elem(Markup.TRACING_MESSAGE, message)) | 
| 79873 | 49 | } | 
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | abstract class Program_Progress( | |
| 54 | default_heading: String = "Running", | |
| 55 | default_title: String = "program", | |
| 56 | override val verbose: Boolean = false | |
| 57 | ) extends Progress {
 | |
| 58 | private var _finished_programs: List[Program_Progress.Program] = Nil | |
| 59 | private var _running_program: Option[Program_Progress.Program] = None | |
| 60 | ||
| 81392 
92aa6f7b470c
clarified output representation: postpone Pretty.separate;
 wenzelm parents: 
79873diff
changeset | 61 |   def output(): (Command.Results, List[XML.Elem]) = synchronized {
 | 
| 79873 | 62 | val programs = (_running_program.toList ::: _finished_programs).reverse | 
| 63 | val programs_output = programs.map(_.output()) | |
| 64 | val results = Command.Results.merge(programs_output.map(_._1)) | |
| 81392 
92aa6f7b470c
clarified output representation: postpone Pretty.separate;
 wenzelm parents: 
79873diff
changeset | 65 | (results, programs_output.map(_._2)) | 
| 79873 | 66 | } | 
| 67 | ||
| 68 |   private def start_program(heading: String, title: String): Unit = synchronized {
 | |
| 69 | _running_program = Some(new Program_Progress.Program(heading, title)) | |
| 70 | } | |
| 71 | ||
| 72 |   def stop_program(): Unit = synchronized {
 | |
| 73 |     _running_program match {
 | |
| 74 | case Some(program) => | |
| 75 | program.stop_now() | |
| 76 | _finished_programs ::= program | |
| 77 | _running_program = None | |
| 78 | case None => | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | def detect_program(s: String): Option[String] | |
| 83 | ||
| 84 |   override def output(message: Progress.Message): Unit = synchronized {
 | |
| 85 | val writeln_msg = if (message.kind == Progress.Kind.writeln) message.text else "" | |
| 86 |     detect_program(writeln_msg).map(Word.explode) match {
 | |
| 87 | case Some(a :: bs) => | |
| 88 | stop_program() | |
| 89 | start_program(a, Word.implode(bs)) | |
| 90 | case _ => | |
| 91 | if (_running_program.isEmpty) start_program(default_heading, default_title) | |
| 92 | if (do_output(message)) _running_program.get.output(message) | |
| 93 | } | |
| 94 | } | |
| 95 | } |