Skip to content
This repository has been archived by the owner on Jan 16, 2019. It is now read-only.

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
starzu committed Feb 25, 2016
1 parent 26bf583 commit 0fbf121
Show file tree
Hide file tree
Showing 42 changed files with 2,234 additions and 0 deletions.
132 changes: 132 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Created by .ignore support plugin (hsz.mobi)
### Eclipse template
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath

# Eclipse Core
.project

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# JDT-specific (Eclipse Java Development Tools)
.classpath

# Java annotation processor (APT)
.factorypath

# PDT-specific
.buildpath

# sbteclipse plugin
.target

# TeXlipse plugin
.texlipse
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Java template
*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Scala template
*.class
*.log

# sbt specific
.cache
.history
.lib/
dist/*
!dist/run.bat
!dist/run.sh
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/

# Scala-IDE specific
.scala_dependencies
.worksheet

7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: scala

scala:
- 2.11.7

script:
- ./test.sh
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Udash Generator [![Build Status](https://travis-ci.org/UdashFramework/udash-generator.svg?branch=master)](https://travis-ci.org/UdashFramework/udash-generator) [![Join the chat at https://gitter.im/UdashFramework/udash-generator](https://badges.gitter.im/UdashFramework/udash-generator.svg)](https://gitter.im/UdashFramework/udash-generator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [<img align="right" height="50px" src="http://www.avsystem.com/avsystem_logo.png">](http://www.avsystem.com/)

Project generator for the Udash framework.
19 changes: 19 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name := "udash-generator"

version in ThisBuild := "0.1.0"
organization in ThisBuild := "io.udash"
scalaVersion in ThisBuild := "2.11.7"

lazy val generator = project.in(file("."))
.aggregate(core, cmd)
.settings(publishArtifact := false)

lazy val core = project.in(file("core"))
.settings(libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.0-M15" % Test)

lazy val cmd = project.in(file("cmd"))
.dependsOn(core)
.settings(
assemblyJarName in assembly := "udash-generator.jar",
mainClass in assembly := Some("io.udash.generator.Launcher")
)
85 changes: 85 additions & 0 deletions cmd/src/main/scala/io/udash/generator/CmdDecisionMaker.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.udash.generator

import java.io.File

import io.udash.generator.configuration._
import io.udash.generator.exceptions.InvalidConfigDecisionResponse

import scala.io.StdIn

class CmdDecisionMaker extends DecisionMaker {
private val yesAnswers = Seq("yes", "y", "true", "t")

override def makeDecision[T](d: Decision[T]): Decision[T] = {
try {
val response: Decision[T] = d match {
case decision@RootDirectory(_) =>
RootDirectory(Some(askForFile("Project root directory", decision.default)))
case decision@ClearRootDirectory(_) =>
ClearRootDirectory(Some(askForBoolean("Clear root directory", decision.default)))
case decision@ProjectName(_) =>
ProjectName(Some(askForString("Project name", decision.default)))
case decision@Organization(_) =>
Organization(Some(askForString("Organization", decision.default)))
case decision@RootPackage(_) =>
RootPackage(Some(askForPackage("Root package", decision.default)))
case decision@ProjectTypeSelect(_) =>
ProjectTypeSelect(Some(askForSelection("Project type", decision.default, decision.options)))
case decision@StdProjectTypeModulesSelect(_) =>
val backend = askForString("Backend module name", decision.default.backend)
val shared = askForString("Shared module name", decision.default.shared)
val frontend = askForString("Frontend module name", decision.default.frontend)
StdProjectTypeModulesSelect(Some(StandardProject(backend, shared, frontend)))
case decision@CreateBasicFrontendApp(_) =>
CreateBasicFrontendApp(Some(askForBoolean("Create basic frontend application", decision.default)))
case decision@CreateFrontendDemos(_) =>
CreateFrontendDemos(Some(askForBoolean("Create frontend demo views", decision.default)))
case decision@CreateScalaCSSDemos(_) =>
CreateScalaCSSDemos(Some(askForBoolean("Create ScalaCSS demo views", decision.default)))
case decision@CreateJettyLauncher(_) =>
CreateJettyLauncher(Some(askForBoolean("Create Jetty launcher", decision.default)))
case decision@CreateRPC(_) =>
CreateRPC(Some(askForBoolean("Create RPC communication layer", decision.default)))
case decision@CreateRPCDemos(_) =>
CreateRPCDemos(Some(askForBoolean("Create RPC communication layer demos", decision.default)))
case decision@RunGenerator(_) =>
RunGenerator(Some(askForBoolean("Start generation", decision.default)))
}
for (errors <- response.validator()) throw InvalidConfigDecisionResponse(errors)
response
} catch {
case InvalidConfigDecisionResponse(ex) =>
println(ex)
makeDecision(d)
case _: Exception =>
makeDecision(d)
}
}

private def ask[T](prompt: String, default: T)(converter: String => T): T = {
val response = StdIn.readLine(prompt).trim
if (response.isEmpty) default else converter(response)
}

private def askWithDefault[T](prompt: String, default: T)(converter: String => T): T =
ask(s"$prompt [$default]: ", default)(converter)

private def askForString(prompt: String, default: String): String =
askWithDefault(prompt, default)(s => s)

private def askForBoolean(prompt: String, default: Boolean): Boolean =
askWithDefault(prompt, default)(r => yesAnswers.contains(r.toLowerCase))

private def askForPackage(prompt: String, default: Seq[String]): Seq[String] =
ask(s"$prompt [${default.mkString(".")}]: ", default)(s => s.split("\\."))

private def askForFile(prompt: String, default: File): File =
ask(s"$prompt [${default.getAbsolutePath}]: ", default)(r => new File(r))

private def askForSelection[T](prompt: String, default: T, options: Seq[T]): T = {
val optionsPresentation = options.zipWithIndex.map{
case decision@(opt, idx) => s" ${idx+1}. $opt \n"
}.mkString
ask(s"$prompt [${options.indexOf(default)}]:\n${optionsPresentation}Select: ", default)(r => options(Integer.parseInt(r) - 1))
}
}
13 changes: 13 additions & 0 deletions cmd/src/main/scala/io/udash/generator/Launcher.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.udash.generator

import io.udash.generator.configuration.ConfigurationBuilder

object Launcher {
def main(args: Array[String]) {
val generator = new Generator
val configBuilder = new ConfigurationBuilder(new CmdDecisionMaker)
val config = configBuilder.build()

generator.start(config.plugins, config.settings)
}
}
17 changes: 17 additions & 0 deletions core/src/main/scala/io/udash/generator/Generator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.udash.generator

import io.udash.generator.utils.FileOps

class Generator extends FileOps {
/**
* Starts project generation process.
*
* @param plugins Sequence of generator plugins, which will be fired.
* @param settings Initial project settings.
*/
def start(plugins: Seq[GeneratorPlugin], settings: GeneratorSettings): GeneratorSettings = {
if (settings.shouldRemoveExistingData) removeFileOrDir(settings.rootDirectory)
settings.rootDirectory.mkdirs()
plugins.foldLeft(settings)((settings: GeneratorSettings, plugin: GeneratorPlugin) => plugin.run(settings))
}
}
11 changes: 11 additions & 0 deletions core/src/main/scala/io/udash/generator/GeneratorPlugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.udash.generator

import io.udash.generator.utils.FileOps

/** Part of generation chain. */
trait GeneratorPlugin extends FileOps {
/** Starts plugins work with current project settings.
*
* @return Project settings which will be passed to next plugin in generator sequence. */
def run(settings: GeneratorSettings): GeneratorSettings
}
66 changes: 66 additions & 0 deletions core/src/main/scala/io/udash/generator/GeneratorSettings.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.udash.generator

import java.io.File

/**
* Basic project configuration.
*
* @param rootDirectory Root directory of whole project.
* @param shouldRemoveExistingData If `true`, generator will remove whole data from rootDirectory.
* @param rootPackage Root package of sources.
* @param projectType Project modules configuration.
* @param organization Organization name.
* @param projectName Project name.
*/
case class GeneratorSettings(rootDirectory: File,
shouldRemoveExistingData: Boolean,
projectName: String,
organization: String,
projectType: ProjectType,
rootPackage: Seq[String]) {
/** Root package of views in frontend. */
def viewsSubPackage: Seq[String] = Seq("views")
/** Root package of styles in frontend. */
def stylesSubPackage: Seq[String] = Seq("styles")

def scalaVersion: String = "2.11.7"
def sbtVersion: String = "0.13.9"
def scalaJSVersion: String = "0.6.7"
def scalaCSSVersion: String = "0.4.0"
def udashCoreVersion: String = "0.1.0"
def udashRPCVersion: String = "0.1.0"
def jettyVersion: String = "9.3.7.v20160115"
def logbackVersion: String = "1.1.3"

/** Application HTML root element id */
def htmlRootId: String = "application"

/** Generated JS file with application code name (dev). */
def frontendImplFastJs: String = "frontend-impl-fast.js"
/** Generated JS file with application code name (prod). */
def frontendImplJs: String = "frontend-impl.js"
/** Generated JS file with dependencies code name (dev). */
def frontendDepsFastJs: String = "frontend-deps-fast.js"
/** Generated JS file with dependencies code name (prod). */
def frontendDepsJs: String = "frontend-deps.js"
/** Generated JS file with app launcher name (dev). */
def frontendInitJs: String = "frontend-init.js"

/** Udash DevGuide root URL. */
//TODO: add developer guide url
//def udashDevGuide: String = ""
}

sealed trait ProjectType

/** Project does not contain submodules, it's only frontend application and everything is compiled to JavaScript. */
case object FrontendOnlyProject extends ProjectType

/**
* Standard Udash project with three submodules:
*
* @param backend - module compiled to JVM name
* @param shared - module compiled to JS and JVM name
* @param frontend - module compiled to JS name
*/
case class StandardProject(backend: String, shared: String, frontend: String) extends ProjectType
Loading

0 comments on commit 0fbf121

Please sign in to comment.