Created
June 16, 2011 00:13
-
-
Save pr1001/1028437 to your computer and use it in GitHub Desktop.
Towards a more friendly DSL for Lift's Javascript representations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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