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