diff options
author | odersky <odersky@gmail.com> | 2012-07-30 05:40:57 -0700 |
---|---|---|
committer | odersky <odersky@gmail.com> | 2012-07-30 05:40:57 -0700 |
commit | e77dbfc774b929df78aa408e86bce7eeec1271ee (patch) | |
tree | f4e9a90c0a4c1bd9e488da865852040081e35fbf /src/library | |
parent | 1ad6e501997d332e2bc0ccc8dd40e3909e728930 (diff) | |
parent | e3bfe109732b7c1cce7493b2869614ed145660f6 (diff) | |
download | scala-e77dbfc774b929df78aa408e86bce7eeec1271ee.tar.gz scala-e77dbfc774b929df78aa408e86bce7eeec1271ee.tar.bz2 scala-e77dbfc774b929df78aa408e86bce7eeec1271ee.zip |
Merge pull request #1005 from odersky/topic/worksheet
IDE improvements, with particular focus on making worksheets work.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/StringContext.scala | 24 | ||||
-rw-r--r-- | src/library/scala/runtime/WorksheetSupport.scala | 87 |
2 files changed, 107 insertions, 4 deletions
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index f11dfb72ae..7d37fa4aa1 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -26,7 +26,7 @@ case class StringContext(parts: String*) { * @param `args` The arguments to be checked. * @throws An `IllegalArgumentException` if this is not the case. */ - def checkLengths(args: Any*): Unit = + def checkLengths(args: Seq[Any]): Unit = if (parts.length != args.length + 1) throw new IllegalArgumentException("wrong number of arguments for interpolated string") @@ -42,11 +42,27 @@ case class StringContext(parts: String*) { * @throws A `StringContext.InvalidEscapeException` if if a `parts` string contains a backslash (`\`) character * that does not start a valid escape sequence. */ - def s(args: Any*): String = { - checkLengths(args: _*) + def s(args: Any*): String = standardInterpolator(treatEscapes, args) + + /** The raw string interpolator. + * + * It inserts its arguments between corresponding parts of the string context. + * As opposed to the simple string interpolator `s`, this one does not treat + * standard escape sequences as defined in the Scala specification. + * @param `args` The arguments to be inserted into the resulting string. + * @throws An `IllegalArgumentException` + * if the number of `parts` in the enclosing `StringContext` does not exceed + * the number of arguments `arg` by exactly 1. + * @throws A `StringContext.InvalidEscapeException` if if a `parts` string contains a backslash (`\`) character + * that does not start a valid escape sequence. + */ + def raw(args: Any*): String = standardInterpolator(identity, args) + + def standardInterpolator(process: String => String, args: Seq[Any]): String = { + checkLengths(args) val pi = parts.iterator val ai = args.iterator - val bldr = new java.lang.StringBuilder(treatEscapes(pi.next())) + val bldr = new java.lang.StringBuilder(process(pi.next())) while (ai.hasNext) { bldr append ai.next bldr append treatEscapes(pi.next()) diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala new file mode 100644 index 0000000000..db6d6359a3 --- /dev/null +++ b/src/library/scala/runtime/WorksheetSupport.scala @@ -0,0 +1,87 @@ +package scala.runtime +import java.io.{OutputStream, PrintStream} +import scala.runtime.ScalaRunTime.stringOf + +/** A utility object that's needed by the code that executes a worksheet. + */ +object WorksheetSupport { + + /** The offset in the source which should be printed */ + private var currentOffset = 0 + + /** A stream that flushes in regular intervals so that output can be captured + * in real time. The flush interval is determined by the field "flushInterval". + * By default it is 30ms. + */ + private class FlushedOutputStream(out: OutputStream) extends OutputStream { + private var lastFlush: Long = 0L + protected val flushInterval = 30000000L // 30ms + private var lastCh: Int = '\n' + override def write(b: Array[Byte], off: Int, len: Int) = { + for (idx <- off until (off + len min b.length)) writeOne(b(idx)) + flush() + } + override def write(c: Int) { + writeOne(c) + flush() + } + override def flush() { + val current = System.nanoTime + if (current - lastFlush >= flushInterval) { + out.flush() + lastFlush = current + } + } + def writeOne(c: Int) { + if (lastCh == '\n') { + lastCh = 0 + write((currentOffset+" ").getBytes) + } + out.write(c) + lastCh = c + } + def ensureNewLine() = if (lastCh != '\n') writeOne('\n') + } + + private val flushedOut = new FlushedOutputStream(System.out) + private val printOut = new PrintStream(flushedOut) + + private def redirected(op: => Unit) = { + val oldSysOut = System.out + val oldSysErr = System.err + val oldConsOut = Console.out + val oldConsErr = Console.err + System.setOut(printOut) + System.setErr(printOut) + Console.setOut(printOut) + Console.setErr(printOut) + try op + finally { + printOut.close() + System.setOut(oldSysOut) + System.setErr(oldSysErr) + Console.setOut(oldConsOut) + Console.setErr(oldConsErr) + } + } + + def $execute(op: => Unit) = redirected { + try op + catch { + case ex: StopException => ; + case ex => ex.printStackTrace() + } + } + + def $skip(n: Int) = { + flushedOut.ensureNewLine() + currentOffset += n + } + + def $stop() = throw new StopException + + def $show(x: Any): String = stringOf(x, scala.Int.MaxValue) +} + +class StopException extends Exception + |