diff options
author | Li Haoyi <haoyi@dropbox.com> | 2014-12-20 22:25:49 -0800 |
---|---|---|
committer | Li Haoyi <haoyi@dropbox.com> | 2014-12-20 22:25:49 -0800 |
commit | e6831705b0216f7504129cc6943e1f23e114b959 (patch) | |
tree | fba42e201c2a3889aea9a5d2bd6be8d90cc5ce8e /src/main/scala/workbench/Plugin.scala | |
parent | 37a33d401fd70c56ff7f411afc07a4605e2e1aa2 (diff) | |
download | workbench-e6831705b0216f7504129cc6943e1f23e114b959.tar.gz workbench-e6831705b0216f7504129cc6943e1f23e114b959.tar.bz2 workbench-e6831705b0216f7504129cc6943e1f23e114b959.zip |
basic Scala.js console works
Diffstat (limited to 'src/main/scala/workbench/Plugin.scala')
-rw-r--r-- | src/main/scala/workbench/Plugin.scala | 128 |
1 files changed, 108 insertions, 20 deletions
diff --git a/src/main/scala/workbench/Plugin.scala b/src/main/scala/workbench/Plugin.scala index 3a1b175..dd3cab9 100644 --- a/src/main/scala/workbench/Plugin.scala +++ b/src/main/scala/workbench/Plugin.scala @@ -1,9 +1,15 @@ package com.lihaoyi.workbench +import scala.concurrent.ExecutionContext.Implicits.global import sbt._ import sbt.Keys._ import autowire._ -import upickle.Js -import scala.concurrent.ExecutionContext.Implicits.global +import scala.scalajs.sbtplugin.ScalaJSPlugin.ScalaJSKeys +import scala.scalajs.tools.io._ +import scala.scalajs.tools.optimizer.ScalaJSOptimizer +import scala.scalajs.sbtplugin.ScalaJSPluginInternal._ +import scala.scalajs.sbtplugin.Implicits._ + +import ScalaJSKeys._ object Plugin extends sbt.Plugin { val refreshBrowsers = taskKey[Unit]("Sends a message to all connected web pages asking them to refresh the page") @@ -15,6 +21,11 @@ object Plugin extends sbt.Plugin { val bootSnippet = settingKey[String]("piece of javascript to make things happen") val updatedJS = taskKey[List[String]]("Provides the addresses of the JS files that have changed") + val sjs = inputKey[Unit]("Run a command via the sjs REPL, which compiles it to Javascript and runs it in the browser") + val replFile = taskKey[File]("The temporary file which holds the source code for the currently executing sjs REPL") + val sjsReset = taskKey[Unit]("Reset the currently executing sjs REPL") + + lazy val replHistory = collection.mutable.Buffer.empty[String] val workbenchSettings = Seq( localUrl := ("localhost", 12345), @@ -77,23 +88,9 @@ object Plugin extends sbt.Plugin { streams.value.log.info("workbench: Splicing " + path) val prefix = "http://localhost:12345/" - var s = IO.read(new sbt.File(path.drop(prefix.length))) - - s = s.replace("\nvar ScalaJS = ", "\nvar ScalaJS = ScalaJS || ") - s = s.replaceAll( - "\n(ScalaJS\\.c\\.[a-zA-Z_$0-9]+\\.prototype) = (.*?\n)", - """ - |$1 = $1 || {} - |(function(){ - | var newProto = $2 - | for (var attrname in newProto) { $1[attrname] = newProto[attrname]; } - |})() - |""".stripMargin - ) - for(char <- Seq("d", "c", "h", "i", "n", "m")){ - s = s.replaceAll("\n(ScalaJS\\." + char + "\\.[a-zA-Z_$0-9]+) = ", "\n$1 = $1 || ") - } - IO.write(new sbt.File(path.drop(prefix.length) + ".js"), s.getBytes) + val s = munge(sbt.IO.read(new sbt.File(path.drop(prefix.length)))) + + sbt.IO.write(new sbt.File(path.drop(prefix.length) + ".js"), s.getBytes) server.value.Wire[Api].run(path + ".js", None).call() } } @@ -103,5 +100,96 @@ object Plugin extends sbt.Plugin { server.value.kill() state }} - ) + ) ++ inConfig(Compile)(Seq( + artifactPath in sjs := crossTarget.value / "repl.js", + replFile := { + val f = sourceManaged.value / "repl.scala" + println("Creating replFile\n" + replHistory.mkString("\n")) + sbt.IO.write(f, replHistory.mkString("\n")) + f + }, + sources in Compile += replFile.value, + sjs <<= Def.inputTaskDyn { + import sbt.complete.Parsers._ + val str = sbt.complete.Parsers.any.*.parsed.mkString + val newSnippet = s""" + @scalajs.js.annotation.JSExport object O${replHistory.length}{ + $str + }; + import O${replHistory.length}._ + """ + replHistory.append(newSnippet) + Def.taskDyn { + // Basically C&Ped from fastOptJS, since we dont want this + // special mode from triggering updateBrowsers or similar + val s = streams.value + val output = (artifactPath in sjs).value + + val taskCache = WritableFileVirtualTextFile(s.cacheDirectory / "fastopt-js") + + sbt.IO.createDirectory(output.getParentFile) + + val relSourceMapBase = + if ((relativeSourceMaps in fastOptJS).value) + Some(output.getParentFile.toURI()) + else None + + import ScalaJSOptimizer._ + + (scalaJSOptimizer in fastOptJS).value.optimizeCP( + Inputs(input = (preLinkClasspath in fastOptJS).value), + OutputConfig( + output = WritableFileVirtualJSFile(output), + cache = None, + wantSourceMap = (emitSourceMaps in fastOptJS).value, + relativizeSourceMapBase = relSourceMapBase, + checkIR = (checkScalaJSIR in fastOptJS).value, + disableInliner = (inliningMode in fastOptJS).value.disabled, + batchInline = (inliningMode in fastOptJS).value.batch), + s.log + ) + // end of C&P + val outPath = sbt.IO.relativize( + baseDirectory.value, + (artifactPath in sjs).value + ).get + + sbt.IO.write( + (artifactPath in sjs).value, + sbt.IO.read(output) + s"\n\nO${replHistory.length - 1}()" + ) + Def.task { + server.value.Wire[Api].run( + s"http://localhost:12345/$outPath", + None + ).call() + () + } + }.dependsOn(packageJSDependencies, packageLauncher, compile) + }, + sjsReset := { + println("Clearing sjs REPL History") + replHistory.clear() + }, + sjsReset <<= sjsReset.triggeredBy(fastOptJS) + )) + + def munge(s0: String) = { + var s = s0 + s = s.replace("\nvar ScalaJS = ", "\nvar ScalaJS = ScalaJS || ") + s = s.replaceAll( + "\n(ScalaJS\\.c\\.[a-zA-Z_$0-9]+\\.prototype) = (.*?\n)", + """ + |$1 = $1 || {} + |(function(){ + | var newProto = $2 + | for (var attrname in newProto) { $1[attrname] = newProto[attrname]; } + |})() + |""".stripMargin + ) + for(char <- Seq("d", "c", "h", "i", "n", "m")){ + s = s.replaceAll("\n(ScalaJS\\." + char + "\\.[a-zA-Z_$0-9]+) = ", "\n$1 = $1 || ") + } + s + } } |