src/Pure/library.scala
author wenzelm
Mon, 29 Aug 2011 16:38:56 +0200
changeset 45445 51f8895b9ad9
parent 45037 fe6d1ae7a065
child 45500 6ec4a5eb2fc0
permissions -rw-r--r--
some dialog for auto loading of required files (still inactive);
     1 /*  Title:      Pure/library.scala
     2     Author:     Makarius
     3 
     4 Basic library.
     5 */
     6 
     7 package isabelle
     8 
     9 
    10 import java.lang.System
    11 import java.awt.Component
    12 import javax.swing.JOptionPane
    13 
    14 import scala.swing.ComboBox
    15 import scala.swing.event.SelectionChanged
    16 import scala.collection.mutable
    17 
    18 
    19 object Library
    20 {
    21   /* user errors */
    22 
    23   object ERROR
    24   {
    25     def apply(message: String): Throwable = new RuntimeException(message)
    26     def unapply(exn: Throwable): Option[String] =
    27       exn match {
    28         case e: RuntimeException => Some(Exn.message(e))
    29         case _ => None
    30       }
    31   }
    32 
    33   def error(message: String): Nothing = throw ERROR(message)
    34 
    35   def cat_error(msg1: String, msg2: String): Nothing =
    36     if (msg1 == "") error(msg1)
    37     else error(msg1 + "\n" + msg2)
    38 
    39 
    40   /* lists */
    41 
    42   def separate[A](s: A, list: List[A]): List[A] =
    43     list match {
    44       case x :: xs if !xs.isEmpty => x :: s :: separate(s, xs)
    45       case _ => list
    46     }
    47 
    48   def space_explode(sep: Char, str: String): List[String] =
    49     if (str.isEmpty) Nil
    50     else {
    51       val result = new mutable.ListBuffer[String]
    52       var start = 0
    53       var finished = false
    54       while (!finished) {
    55         val i = str.indexOf(sep, start)
    56         if (i == -1) { result += str.substring(start); finished = true }
    57         else { result += str.substring(start, i); start = i + 1 }
    58       }
    59       result.toList
    60     }
    61 
    62   def split_lines(str: String): List[String] = space_explode('\n', str)
    63 
    64 
    65   /* iterate over chunks (cf. space_explode) */
    66 
    67   def chunks(source: CharSequence, sep: Char = '\n') = new Iterator[CharSequence]
    68   {
    69     private val end = source.length
    70     private def next_chunk(i: Int): Option[(CharSequence, Int)] =
    71     {
    72       if (i < end) {
    73         var j = i; do j += 1 while (j < end && source.charAt(j) != sep)
    74         Some((source.subSequence(i + 1, j), j))
    75       }
    76       else None
    77     }
    78     private var state: Option[(CharSequence, Int)] = if (end == 0) None else next_chunk(-1)
    79 
    80     def hasNext(): Boolean = state.isDefined
    81     def next(): CharSequence =
    82       state match {
    83         case Some((s, i)) => { state = next_chunk(i); s }
    84         case None => Iterator.empty.next()
    85       }
    86   }
    87 
    88   def first_line(source: CharSequence): String =
    89   {
    90     val lines = chunks(source)
    91     if (lines.hasNext) lines.next.toString
    92     else ""
    93   }
    94 
    95 
    96   /* strings */
    97 
    98   def quote(s: String): String = "\"" + s + "\""
    99   def commas(ss: Iterable[String]): String = ss.iterator.mkString(", ")
   100   def commas_quote(ss: Iterable[String]): String = ss.iterator.mkString("\"", ", ", "\"")
   101 
   102 
   103   /* reverse CharSequence */
   104 
   105   class Reverse(text: CharSequence, start: Int, end: Int) extends CharSequence
   106   {
   107     require(0 <= start && start <= end && end <= text.length)
   108 
   109     def this(text: CharSequence) = this(text, 0, text.length)
   110 
   111     def length: Int = end - start
   112     def charAt(i: Int): Char = text.charAt(end - i - 1)
   113 
   114     def subSequence(i: Int, j: Int): CharSequence =
   115       if (0 <= i && i <= j && j <= length) new Reverse(text, end - j, end - i)
   116       else throw new IndexOutOfBoundsException
   117 
   118     override def toString: String =
   119     {
   120       val buf = new StringBuilder(length)
   121       for (i <- 0 until length)
   122         buf.append(charAt(i))
   123       buf.toString
   124     }
   125   }
   126 
   127 
   128   /* simple dialogs */
   129 
   130   private def simple_dialog(kind: Int, default_title: String)
   131     (parent: Component, title: String, message: Any*)
   132   {
   133     Swing_Thread.now {
   134       val java_message = message map { case x: scala.swing.Component => x.peer case x => x }
   135       JOptionPane.showMessageDialog(parent,
   136         java_message.toArray.asInstanceOf[Array[AnyRef]],
   137         if (title == null) default_title else title, kind)
   138     }
   139   }
   140 
   141   def dialog = simple_dialog(JOptionPane.PLAIN_MESSAGE, null) _
   142   def warning_dialog = simple_dialog(JOptionPane.WARNING_MESSAGE, "Warning") _
   143   def error_dialog = simple_dialog(JOptionPane.ERROR_MESSAGE, "Error") _
   144 
   145   def confirm_dialog(parent: Component, title: String, option_type: Int, message: Any*): Int =
   146     Swing_Thread.now {
   147       val java_message = message map { case x: scala.swing.Component => x.peer case x => x }
   148       JOptionPane.showConfirmDialog(parent,
   149         java_message.toArray.asInstanceOf[Array[AnyRef]], title,
   150           option_type, JOptionPane.QUESTION_MESSAGE)
   151     }
   152 
   153 
   154   /* zoom box */
   155 
   156   class Zoom_Box(apply_factor: Int => Unit) extends ComboBox[String](
   157     List("50%", "70%", "85%", "100%", "125%", "150%", "175%", "200%", "300%", "400%"))
   158   {
   159     val Factor = "([0-9]+)%?"r
   160     def parse(text: String): Int =
   161       text match {
   162         case Factor(s) =>
   163           val i = Integer.parseInt(s)
   164           if (10 <= i && i <= 1000) i else 100
   165         case _ => 100
   166       }
   167     def print(i: Int): String = i.toString + "%"
   168 
   169     makeEditable()(c => new ComboBox.BuiltInEditor(c)(text => print(parse(text)), x => x))
   170     reactions += {
   171       case SelectionChanged(_) => apply_factor(parse(selection.item))
   172     }
   173     listenTo(selection)
   174     selection.index = 3
   175     prototypeDisplayValue = Some("00000%")
   176   }
   177 
   178 
   179   /* timing */
   180 
   181   def timeit[A](message: String)(e: => A) =
   182   {
   183     val start = System.currentTimeMillis()
   184     val result = Exn.capture(e)
   185     val stop = System.currentTimeMillis()
   186     System.err.println(
   187       (if (message == null || message.isEmpty) "" else message + ": ") +
   188         new Time(stop - start).message + " elapsed time")
   189     Exn.release(result)
   190   }
   191 }
   192 
   193 
   194 class Basic_Library
   195 {
   196   val ERROR = Library.ERROR
   197   val error = Library.error _
   198   val cat_error = Library.cat_error _
   199 
   200   val space_explode = Library.space_explode _
   201   val split_lines = Library.split_lines _
   202 
   203   val quote = Library.quote _
   204   val commas = Library.commas _
   205   val commas_quote = Library.commas_quote _
   206 }