Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Towards a more friendly DSL for Lift's Javascript representations
val test = j_var ("test") := j_true
val test2 = j_var ('test2) := j_false
1 j_< 2
JsVar("k") j_<= 10
val a: JsVar = 'a
a++
val clause1 = j_if (j_true) {
j_return (j_false)
} j_else {
j_return (j_true)
}
val clause2 = j_if (j_true) {
j_return()
} j_else {
j_return (j_true)
}
val k: JsVar = 'k
val console_log = JsVar("console", "log")
val c = j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {
console_log(k)
}
import net.liftweb.common.{Box, Empty, Failure, Full}
import net.liftweb.http.js._
import net.liftweb.http.js.JsCmds._
import net.liftweb.http.js.JsCmds.{
JsBreak => j_break,
JsContinue => j_continue,
JsReturn => j_return
}
import net.liftweb.http.js.JE._
import net.liftweb.http.js.JE.{
JsTrue => j_true,
JsFalse => j_false
}
import net.liftweb.json.JValue
object Implicits {
implicit def fromJsExp(in: JsExp) = new RichJsExp(in)
implicit def fromJValue(in: JValue) = new RichJsExp(JsExp.jValueToJsExp(in))
implicit def fromString(in: String) = new RichJsExp(JsExp.strToJsExp(in))
implicit def fromBoolean(in: Boolean) = new RichJsExp(JsExp.boolToJsExp(in))
implicit def fromInt(in: Int) = new RichJsExp(JsExp.intToJsExp(in))
implicit def fromLong(in: Long) = new RichJsExp(JsExp.longToJsExp(in))
implicit def fromDouble(in: Double) = new RichJsExp(JsExp.doubleToJsExp(in))
implicit def fromFloat(in: Float) = new RichJsExp(JsExp.floatToJsExp(in))
implicit def fromJENum(in: JE.Num) = new RichJsExp(JsExp.numToJValue(in))
implicit def fromJEStr(in: JE.Str) = new RichJsExp(JsExp.strToJValue(in))
implicit def fromSymbol(in: Symbol) = new RichJsExp(JsVar(in.name))
implicit def jsVartoRichJsVar(in: JsVar) = new RichJsVar(in)
implicit def symbolToJsVar(s: Symbol) = JsVar(s.name)
// it's really annoying in general that JsExp -> JsCmd but not JsCmd -> JsExp
// the difference between the two is still not apparent to me
// not sure if this implicit is dangerous or not
implicit def JsCmdtoJsExp(in: JsCmd) = new JsExp {
def toJsCmd = in.toJsCmd
}
}
import Implicits._
case class j_if(condition: JsExp, if_body: JsCmd, else_body: Box[JsCmd] = Empty) extends JsExp {
def toJsCmd = if (else_body.isDefined) {
"if ( " + condition.toJsCmd + " ) { " + if_body.toJsCmd + " } else { " + else_body.open_!.toJsCmd + " }"
} else {
"if ( " + condition.toJsCmd + " ) { " + if_body.toJsCmd + " }"
}
def j_else(in: JsCmd) = this.copy(else_body = Full(in))
}
object j_if {
def apply(condition: JsExp)(body: JsCmd) = new j_if(condition, body)
}
object j_for {
def apply(initialExp: JsExp, condition: JsExp, incrementExp: JsExp)(body: JsExp) = JsFor(initialExp, condition, incrementExp, body)
}
case class j_var(name: String, right: Box[JsExp] = Empty) extends JsExp {
def toJsCmd = if (right.isDefined) {
"var " + name + " = " + right.open_!.toJsCmd
} else {
"var " + name
}
def :=(in: JsExp) = this.copy(right = Full(in))
}
object j_var {
def apply(name: Symbol) = new j_var(name.name)
def apply(name: JsVar) = new j_var(name.varName)
}
/*
Unfortunately the parentheses around the variable can't be omitted
j_var ('test) := j_true
j_var ("test") := j_true
j_var ('test)
*/
class RichJsExp(left: JsExp) {
def j_<(right: JsExp) = JsLt(left, right)
def j_>(right: JsExp) = JsGt(left, right)
def j_<=(right: JsExp) = JsLtEq(left, right)
def j_>=(right: JsExp) = JsGtEq(left, right)
}
/*
1 j_< 2
JsVar("k") j_<= 10
*/
class RichJsVar(left: JsVar) {
def ++ = JE.JsRaw(left.toJsCmd + "++")
def -- = JE.JsRaw(left.toJsCmd + "--")
def +=(right: JsExp) = JE.JsRaw(left.toJsCmd + " += " + right.toJsCmd)
def -=(right: JsExp) = JE.JsRaw(left.toJsCmd + " -= " + right.toJsCmd)
def apply(params: JsExp*) = Call(left.toJsCmd, params :_*)
}
case class RichCall(js_var: JsVar, params: JsExp*) extends JsExp {
def toJsCmd = Call(js_var.toJsCmd, params :_*).toJsCmd
}
/*
val a: JsVar = 'a
a++
*/
/*
Putting it all together:
val a = j_if (j_true) {
j_return (j_false)
} j_else {
j_return (j_true)
}
val b = j_if (j_true) {
j_return()
} j_else {
j_return (j_true)
}
val k: JsVar = 'k
val console_log = JsVar("console", "log")
val c = j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {
console_log(k)
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.