src/Pure/System/progress.scala
author wenzelm
Mon, 20 May 2024 15:43:51 +0200
changeset 80182 29f2b8ff84f3
parent 79887 17220dc05991
child 80224 db92e0b6a11a
permissions -rw-r--r--
proper support for "isabelle update -D DIR": avoid accidental exclusion of select_dirs (amending e5dafe9e120f);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
61276
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/System/progress.scala
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     3
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     4
Progress context for system processes.
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     5
*/
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     6
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     7
package isabelle
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     8
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
     9
73897
0ddb5de0506e clarified signature: prefer Java interfaces;
wenzelm
parents: 73367
diff changeset
    10
import java.util.{Map => JMap}
64201
wenzelm
parents: 64117
diff changeset
    11
import java.io.{File => JFile}
wenzelm
parents: 64117
diff changeset
    12
wenzelm
parents: 64117
diff changeset
    13
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73897
diff changeset
    14
object Progress {
78503
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    15
  /* output */
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    16
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    17
  sealed abstract class Output { def message: Message }
78155
54d6b2f75806 support for Database_Progress;
wenzelm
parents: 77524
diff changeset
    18
78611
7b80cc4701c2 clarified signature: prefer enum types;
wenzelm
parents: 78586
diff changeset
    19
  enum Kind { case writeln, warning, error_message }
78503
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    20
  sealed case class Message(
78611
7b80cc4701c2 clarified signature: prefer enum types;
wenzelm
parents: 78586
diff changeset
    21
    kind: Kind,
78503
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    22
    text: String,
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    23
    verbose: Boolean = false
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    24
  ) extends Output {
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    25
    override def message: Message = this
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    26
77502
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    27
    def output_text: String =
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    28
      kind match {
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    29
        case Kind.writeln => Output.writeln_text(text)
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    30
        case Kind.warning => Output.warning_text(text)
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    31
        case Kind.error_message => Output.error_message_text(text)
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    32
      }
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    33
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    34
    override def toString: String = output_text
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    35
  }
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    36
78503
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    37
  sealed case class Theory(
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    38
    theory: String,
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    39
    session: String = "",
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    40
    percentage: Option[Int] = None
6dc1ea827870 clarified signature: more explicit types;
wenzelm
parents: 78432
diff changeset
    41
  ) extends Output {
77502
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    42
    def message: Message =
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    43
      Message(Kind.writeln, print_session + print_theory + print_percentage, verbose = true)
68987
e86d6e869b96 tuned signature;
wenzelm
parents: 68957
diff changeset
    44
77504
wenzelm
parents: 77503
diff changeset
    45
    def print_session: String = if_proper(session, session + ": ")
68987
e86d6e869b96 tuned signature;
wenzelm
parents: 68957
diff changeset
    46
    def print_theory: String = "theory " + theory
e86d6e869b96 tuned signature;
wenzelm
parents: 68957
diff changeset
    47
    def print_percentage: String =
e86d6e869b96 tuned signature;
wenzelm
parents: 68957
diff changeset
    48
      percentage match { case None => "" case Some(p) => " " + p + "%" }
68957
eef4e983fd9d clarified theory progress;
wenzelm
parents: 68951
diff changeset
    49
  }
68410
4e27f5c361d2 clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents: 68330
diff changeset
    50
}
4e27f5c361d2 clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents: 68330
diff changeset
    51
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73897
diff changeset
    52
class Progress {
78876
4222955f3b69 clarified signature: explicit Progress date;
wenzelm
parents: 78874
diff changeset
    53
  def now(): Date = Date.now()
4222955f3b69 clarified signature: explicit Progress date;
wenzelm
parents: 78874
diff changeset
    54
  val start: Date = now()
4222955f3b69 clarified signature: explicit Progress date;
wenzelm
parents: 78874
diff changeset
    55
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    56
  def verbose: Boolean = false
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    57
  final def do_output(message: Progress.Message): Boolean = !message.verbose || verbose
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    58
78432
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    59
  def output(message: Progress.Message): Unit = {}
77502
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    60
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    61
  final def echo(msg: String, verbose: Boolean = false): Unit =
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    62
    output(Progress.Message(Progress.Kind.writeln, msg, verbose = verbose))
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    63
  final def echo_warning(msg: String, verbose: Boolean = false): Unit =
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    64
    output(Progress.Message(Progress.Kind.warning, msg, verbose = verbose))
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    65
  final def echo_error_message(msg: String, verbose: Boolean = false): Unit =
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    66
    output(Progress.Message(Progress.Kind.error_message, msg, verbose = verbose))
77502
2e2b2bd6b2d2 clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents: 77499
diff changeset
    67
77506
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    68
  final def echo_if(cond: Boolean, msg: String): Unit = if (cond) echo(msg)
77499
8fc94efa954a clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents: 77498
diff changeset
    69
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    70
  def theory(theory: Progress.Theory): Unit = output(theory.message)
73340
0ffcad1f6130 tuned --- fewer warnings;
wenzelm
parents: 72699
diff changeset
    71
  def nodes_status(nodes_status: Document_Status.Nodes_Status): Unit = {}
64909
8007f10195af tuned signature;
wenzelm
parents: 64201
diff changeset
    72
78432
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    73
  final def capture[A](e: => A, msg: String, err: Throwable => String): Exn.Result[A] = {
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    74
    echo(msg)
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    75
    try { Exn.Res(e) }
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    76
    catch { case exn: Throwable => echo_error_message(err(exn)); Exn.Exn[A](exn) }
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    77
  }
ee5d9ecc6a0a tuned signature;
wenzelm
parents: 78396
diff changeset
    78
77506
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    79
  final def timeit[A](
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    80
    body: => A,
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    81
    message: Exn.Result[A] => String = null,
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    82
    enabled: Boolean = true
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
    83
  ): A = Timing.timeit(body, message = message, enabled = enabled, output = echo(_))
65921
5b42937d3b2d more operations;
wenzelm
parents: 65910
diff changeset
    84
77524
a3dda42cd110 more robust: disallow override;
wenzelm
parents: 77509
diff changeset
    85
  @volatile private var is_stopped = false
73367
77ef8bef0593 clarified signature --- fewer warnings;
wenzelm
parents: 73340
diff changeset
    86
  def stop(): Unit = { is_stopped = true }
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73897
diff changeset
    87
  def stopped: Boolean = {
73367
77ef8bef0593 clarified signature --- fewer warnings;
wenzelm
parents: 73340
diff changeset
    88
    if (Thread.interrupted()) is_stopped = true
71726
a5fda30edae2 clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents: 71601
diff changeset
    89
    is_stopped
a5fda30edae2 clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents: 71601
diff changeset
    90
  }
a5fda30edae2 clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents: 71601
diff changeset
    91
77506
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    92
  final def interrupt_handler[A](e: => A): A = POSIX_Interrupt.handler { stop() } { e }
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    93
  final def expose_interrupt(): Unit = if (stopped) throw Exn.Interrupt()
61276
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
    94
  override def toString: String = if (stopped) "Progress(stopped)" else "Progress"
64201
wenzelm
parents: 64117
diff changeset
    95
77506
a8175b950173 more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents: 77504
diff changeset
    96
  final def bash(script: String,
64201
wenzelm
parents: 64117
diff changeset
    97
    cwd: JFile = null,
73897
0ddb5de0506e clarified signature: prefer Java interfaces;
wenzelm
parents: 73367
diff changeset
    98
    env: JMap[String, String] = Isabelle_System.settings(),
64201
wenzelm
parents: 64117
diff changeset
    99
    redirect: Boolean = false,
65930
9a28fc03c3fe tuned signature;
wenzelm
parents: 65921
diff changeset
   100
    echo: Boolean = false,
72599
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   101
    watchdog: Time = Time.zero,
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73897
diff changeset
   102
    strict: Boolean = true
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73897
diff changeset
   103
  ): Process_Result = {
72599
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   104
    val result =
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   105
      Isabelle_System.bash(script, cwd = cwd, env = env, redirect = redirect,
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   106
        progress_stdout = echo_if(echo, _),
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   107
        progress_stderr = echo_if(echo, _),
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   108
        watchdog = if (watchdog.is_zero) None else Some((watchdog, _ => stopped)),
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   109
        strict = strict)
76550282267f more interrupts, notably for running latex;
wenzelm
parents: 72574
diff changeset
   110
    if (strict && stopped) throw Exn.Interrupt() else result
64201
wenzelm
parents: 64117
diff changeset
   111
  }
61276
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
   112
}
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
   113
77499
8fc94efa954a clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents: 77498
diff changeset
   114
class Console_Progress(override val verbose: Boolean = false, stderr: Boolean = false)
8fc94efa954a clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents: 77498
diff changeset
   115
extends Progress {
78874
162ce304955e more robust: support concurrent output;
wenzelm
parents: 78611
diff changeset
   116
  override def output(message: Progress.Message): Unit = synchronized {
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
   117
    if (do_output(message)) {
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
   118
      Output.output(message.output_text, stdout = !stderr, include_empty = true)
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
   119
    }
78874
162ce304955e more robust: support concurrent output;
wenzelm
parents: 78611
diff changeset
   120
  }
77503
daf632e9ce7e tuned messages;
wenzelm
parents: 77502
diff changeset
   121
daf632e9ce7e tuned messages;
wenzelm
parents: 77502
diff changeset
   122
  override def toString: String = super.toString + ": console"
61276
8a4bd05c1735 clarified modules;
wenzelm
parents:
diff changeset
   123
}
65888
29a31cf0b4bc more Progress variations;
wenzelm
parents: 65828
diff changeset
   124
77507
8dfe2fbc98e7 tuned whitespace;
wenzelm
parents: 77506
diff changeset
   125
class File_Progress(path: Path, override val verbose: Boolean = false)
8dfe2fbc98e7 tuned whitespace;
wenzelm
parents: 77506
diff changeset
   126
extends Progress {
78874
162ce304955e more robust: support concurrent output;
wenzelm
parents: 78611
diff changeset
   127
  override def output(message: Progress.Message): Unit = synchronized {
77509
3bc49507bae5 clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents: 77507
diff changeset
   128
    if (do_output(message)) File.append(path, message.output_text + "\n")
78874
162ce304955e more robust: support concurrent output;
wenzelm
parents: 78611
diff changeset
   129
  }
65888
29a31cf0b4bc more Progress variations;
wenzelm
parents: 65828
diff changeset
   130
77503
daf632e9ce7e tuned messages;
wenzelm
parents: 77502
diff changeset
   131
  override def toString: String = super.toString + ": " + path.toString
65888
29a31cf0b4bc more Progress variations;
wenzelm
parents: 65828
diff changeset
   132
}