Permalink
Browse files

The plugin now again invokes LiftyEngine to produce effects

I had disabled it when I worked on the parsers. I also got the change
to remove a lot of code from Lifty because the plugin now takes care
of all of the parsing.
  • Loading branch information...
mads-hartmann committed Dec 5, 2011
1 parent fc56ab9 commit ca034f15aab143917fdd8136ea408eb4854f6ef8

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,148 @@
package org.lifty.engine
import org.lifty.engine.io._
import java.net.{ URL, URI }
import scalaz._
import scalaz.effects._
import Scalaz._
import org.fusesource.scalate.{ TemplateEngine }
object LiftyEngine {
def runCommand(cmd: String, args: List[String]): Validation[Error, String] = {
// Because of the way the parsers are defined, we know exactly how many elements
// are in the list in each case.
cmd match {
case "create" => create(args(0), args(1))
case "templates" => templates(args(0))
case "learn" => learn(args(0),args(1))
case "delete" => delete(args(0))
case "upgrade" => upgrade(args(0))
case "recipes" => recipes()
case "help" => help()
}
}
def create(recipe: String, templateName: String): Validation[Error,String] = {
descriptionOfRecipe(recipe).flatMap { description =>
val template = templateOfRecipe(description, templateName)
requestArguments(recipe,template,description).flatMap { env =>
Scalate.run(env, description, None).success
}
}
}
def templates(recipe: String): Validation[Error, String] = {
descriptionOfRecipe(recipe).flatMap { description =>
val max = description.templates.map(_.name.length).max
(for {
template <- description.templates
output = "%s%s%s".format(
template.name,
(0 to (max - template.name.length + 3)).map( _ => " ").mkString, // 3 for extra spacing
template.description)
} yield output).mkString("\n").success
}
}
def learn(name: String, url: String): Validation[Error, String] = {
Storage
.storeRecipe(name, new URL(url)).unsafePerformIO
.map( recipe => learnMsg(name,url, recipe) )
}
def delete(recipe: String): Validation[Error, String] = {
Storage.deleteRecipe(recipe).unsafePerformIO
}
def upgrade(recipe: String): Validation[Error, String] = {
Storage.recipe(recipe).unsafePerformIO.flatMap( s =>
DescriptionLoader.load(s.descriptor).unsafePerformIO.fold(
(e) => Error("Wasn't able to parse the local .json file. Please uninstall and re-learn the recipe.").fail,
(s) => {
val origin = new URL(s.origin)
val version = s.version
DescriptionLoader.load(origin).unsafePerformIO.fold(
(e) => e.fail,
(s) => if (s.version > version) {
Storage.storeRecipe(recipe, origin).unsafePerformIO.fold(
(e) => e.fail,
(s) => "Successfully updated the recipe.".format(version).success
)
} else {
"You have the most recent version of the recipe installed.".success
}
)}))
}
def recipes(): Validation[Error, String] = {
(
"The following recipes are installed: " ::
"" ::
Storage.allRecipes.unsafePerformIO.map(_.name).mkString("\n") :: Nil).mkString("\n").success
}
def help(): Validation[Error, String] = {
(
"help Shows this message" ::
"create <recipe> <template> Create a template from the given recipe" ::
"templates <recipe> List all the templates defined by the recipe" ::
"learn <name> <url> Learn the recipe at the given URL and store it locally under the given name" ::
"delete <name> Deletes a recipe. " ::
"recipes Lists all installed recipes" ::
"update <recipe> Update the recipe if a new version exists" :: Nil).mkString("\n").success
}
private def descriptionOfRecipe(recipeName: String): Validation[Error,Description] = {
Storage.recipe(recipeName).unsafePerformIO.flatMap { recipe =>
DescriptionLoader.load(recipe.descriptor).unsafePerformIO
}
}
private def templateOfRecipe(description: Description, templateName: String): Template = {
description.templates.filter( _.name == templateName ).head
}
def learnMsg(name: String, url: String, recipe: Recipe) = {
"Lifty successfully installed recipe with name '%s'. \n".format(name) +
"\n"+
"Run 'lifty templates %s' for information about the newly installed templates. \n".format(name) +
"\n" +
"Happy hacking."
}
/**
* Will request values for each for the arguments of the template and dependent templates.
*/
def requestArguments(recipe: String, template: Template, description: Description): Validation[Error, Environment] = {
val Pattern = """\$\{(.*)\}(.*)""".r
// request input for an argument that is missing
val requestInputForMissingArgument = (previous: Map[String,String], argument: Argument) => {
// see if there's a previous value to replace
val default = argument.default.map{ dflt =>
(for { matched <- Pattern.findFirstMatchIn(dflt)
name = matched.group(1)
rest = matched.group(2)
tobe <- previous.get(name)
} yield tobe+rest) getOrElse dflt
}.getOrElse("")
val value = InputReaderComponent
.requestInput("Enter value for %s%s: ".format(argument.name, argument.default.map(_=>"["+default+"]").getOrElse("")),default)
.unsafePerformIO
(argument.name, value)
}
val kvs = description.allArguments(template).foldLeft(Nil: List[(String,String)]) { (xs,c) =>
requestInputForMissingArgument(Map(xs: _*), c) :: xs
}
Environment(recipe, template, Map(kvs: _*)).success
}
}
Oops, something went wrong.

0 comments on commit ca034f1

Please sign in to comment.