From 435267714fd9be710945d5d6c2d0ee1f18294e12 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Fri, 17 Mar 2017 03:36:17 -0400 Subject: Add Scalatex plugin --- libraries/scalatex/AbstractMain.scala | 34 ++++++++++++++++ libraries/scalatex/build/build.scala | 16 ++++++++ libraries/scalatex/lib.scala | 76 +++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 libraries/scalatex/AbstractMain.scala create mode 100644 libraries/scalatex/build/build.scala create mode 100644 libraries/scalatex/lib.scala (limited to 'libraries') diff --git a/libraries/scalatex/AbstractMain.scala b/libraries/scalatex/AbstractMain.scala new file mode 100644 index 0000000..ab876d9 --- /dev/null +++ b/libraries/scalatex/AbstractMain.scala @@ -0,0 +1,34 @@ +package cbt.plugins.scalatex.runtime + +import java.io.File +import java.nio.file.{ Files, Paths } +import scalatags.Text.all._ +trait AbstractMain{ + def dependencyClasspath: Seq[File] + def files: Seq[(String,SeqFrag[Frag])] + def htmlTarget: File + def render: SeqFrag[Frag] => String => String + def main(args: Array[String]): Unit = { + val changed = files.flatMap{ + case (name, contents) => + val path = htmlTarget.toPath.resolve(name + ".html") + import Files._ + createDirectories(path.getParent) + val newContents = render(contents)(name) + if( !exists(path) || new String( Files.readAllBytes( path ) ) != newContents ){ + write( path, newContents.getBytes ) + Some( path ) + } else None + } + if( args.lift(0).map(_=="open").getOrElse(false) ) + changed.headOption.foreach{ file => + System.out.println(file) + val old = Option(System.getProperty("apple.awt.UIElement")) + System.setProperty("apple.awt.UIElement", "true") + java.awt.Desktop.getDesktop().open(file.toFile) + old.foreach(System.setProperty("apple.awt.UIElement", _)) + } + else System.out.println(changed.mkString("\\n")) + } + val repl = new cbt.plugins.scalatex.runtime.repl( this.getClass.getClassLoader, dependencyClasspath: _* ) +} diff --git a/libraries/scalatex/build/build.scala b/libraries/scalatex/build/build.scala new file mode 100644 index 0000000..0ca9b76 --- /dev/null +++ b/libraries/scalatex/build/build.scala @@ -0,0 +1,16 @@ +package scalatex_build +import cbt._ +class Build(val context: Context) extends BaseBuild{ + override def dependencies = ( + super.dependencies ++ // don't forget super.dependencies here for scala-library, etc. + Seq( + libraries.cbt.eval + ) ++ + Resolver( mavenCentral, sonatypeReleases ).bind( + ScalaDependency( "com.lihaoyi", "scalatex-api", "0.3.7" ), + ScalaDependency( "com.lihaoyi", "scalatex-site", "0.3.7" ), + ScalaDependency("org.cvogt","scala-extensions","0.5.0"), + ScalaDependency("org.scalameta", "scalameta", "1.6.0") + ) + ) +} diff --git a/libraries/scalatex/lib.scala b/libraries/scalatex/lib.scala new file mode 100644 index 0000000..018329a --- /dev/null +++ b/libraries/scalatex/lib.scala @@ -0,0 +1,76 @@ +package cbt.plugins.scalatex.runtime + +import scalatags.Text.TypedTag +import scalatags.Text.all._ + +import cbt.eval.Eval +import java.net._ +import java.io._ +import org.cvogt.scala._ + +object hl extends scalatex.site.Highlighter + +object `package`{ + def comment(any: =>Any): Unit = () + def plain = span(fontFamily:="monospace") + def highlight(code: String) = + raw( """
""" ++ code.stripIndent.trim ++ "
" ) + def layout: SeqFrag[Frag] => String => String = { contents => path => + import scalatex._ + import scalatags.Text.tags2._ + import java.nio.file.{Paths, Files} + import scalatags.stylesheet._ + val parts = path.split(File.separator) + val base = ("../" * (parts.size - 1)).mkString + val classes = parts.inits.toList.reverse.drop(1).map( parts => "path-" ++ parts.mkString("-") ).mkString(" ") + html( + head( + link(rel:="stylesheet", `type`:="text/css", href := base+"style.css") + ), + body( + `class` := classes, + raw("\n"), contents, raw("\n") + ) + ).render + } +} + +class repl(classLoader: ClassLoader, dependencyClasspath: java.io.File*) { repl => + private val eval = new Eval(){ + override lazy val impliedClassPath: List[String] = dependencyClasspath.map(_.toString).to + override def classLoader = repl.classLoader + } + /** + * repl session, inspired by tut. + * + * Example: code="1 + 1" returns + * "scala> 1 + 1 + * res0: Int = 2" + */ + def apply(code: String) = { + // adapted from https://github.com/olafurpg/scalafmt/blob/a12141b5ce285a60886abab0d96044c617e20b51/readme/Readme.scala + import scala.meta._ + import scala.util._ + val expressions = s"{$code}".parse[Stat].get.asInstanceOf[Term.Block].stats + val output = Try(eval[Any](code)) match { + case Success( value ) => "res0: " ++ value.getClass.getName ++ " = " ++ (value match { + case v: String => "\"" ++ v ++ "\"" + case other => other.toString + }) + case Failure( e ) => e.getMessage + } + + val lineSeparator = String.format("%n") + val prefix = code.lines.filterNot("\t ".contains).mkString(lineSeparator).commonLinePrefix + val result = ( + expressions + .map(prefix ++ _.toString) + .map("scala> " ++ _.stripIndent.prefixLines(" ").trimLeft) + .mkString("\n") + ++ + "\n" ++ output.trim + ) + + hl.scala(result) + } +} -- cgit v1.2.3