author | wenzelm |
Wed, 12 Mar 2025 11:39:00 +0100 | |
changeset 82265 | 4b875a4c83b0 |
parent 81392 | 92aa6f7b470c |
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:
79873
diff
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:
79873
diff
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:
79873
diff
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:
79873
diff
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 |
} |