<commit_before>
package play.console

import jline._
import java.io._
import scalax.file._
import giter8.Giter8

/**
 * provides the console infrastructure for all play apps
 */
object Console {

  val consoleReader = new jline.ConsoleReader

  val logo = Colors.yellow(
    """|       _            _
           | _ __ | | __ _ _  _| |
           || '_ \| |/ _' | || |_|
           ||  __/|_|\____|\__ (_)
           ||_|            |__/
           |
           |""".stripMargin) + ("play! " + play.core.PlayVersion.current + " (using Java " + System.getProperty("java.version") + " and Scala " + play.core.PlayVersion.scalaVersion + "), http://www.playframework.org")

  // -- Commands

  def replace(file: File, tokens: (String, String)*) {
    if (file.exists) {
      Path(file).write(tokens.foldLeft(Path(file).slurpString) { (state, token) =>
        state.replace("%" + token._1 + "%", token._2)
      })
    }
  }

  private def interact(params: Map[String, String]): Map[String, String] = {
    params.map { e =>
      consoleReader.printString(e._1 + "[" + e._2 + "]:".stripMargin)
      consoleReader.putString("")
      e._1 -> Option(consoleReader.readLine()).map(_.trim).filter(_.size > 0).getOrElse(e._2)
    }
  }

  private def generateLocalTemplate(template: String, name: String, path: File): Unit = {
    val random = new java.security.SecureRandom
    val newSecret = (1 to 64).map { _ =>
      (random.nextInt(74) + 48).toChar
    }.mkString.replaceAll("\\\\+", "/")

    def copyRecursively(from: Path, target: Path) {
      import scala.util.control.Exception._
      from.copyTo(target)
      from.children().foreach { child =>
        catching(classOf[java.io.IOException]) opt copyRecursively(child, target / child.name)
      }
    }

    copyRecursively(
      from = Path(new File(System.getProperty("play.home") + "/skeletons/" + template)),
      target = Path(path))

    replace(new File(path, "project/Build.scala"),
      "APPLICATION_NAME" -> name)
    replace(new File(path, "project/plugins.sbt"),
      "PLAY_VERSION" -> play.core.PlayVersion.current)
    replace(new File(path, "conf/application.conf"),
      "APPLICATION_SECRET" -> newSecret)
  }

  private def haveFun(name: String) =
    """|OK, application %s is created.
                  |
                  |Have fun!
                  |""".stripMargin.format(name).trim

  /**
   * Creates a new play app skeleton either based on local templates on g8 templates fetched from github
   * Also, one can create a g8 template directly like this: play new app_name --g8 githubuser/repo.g8
   * @param args first parameter is the application name
   */
  def newCommand(args: Array[String]): (String, Int) = {

    val path = args.headOption.map(new File(_)).getOrElse(new File(".")).getCanonicalFile

    val defaultName = path.getName

    println()
    println(Colors.green("The new application will be created in %s".format(path.getAbsolutePath)))
    println()

    if (path.exists) {
      (Colors.red("The directory already exists, cannot create a new application here."), -1)
    } else {
      val template: (String, String) = if (args.length == 3 && args(1) == "--g8") (args.last, defaultName)
      else {
        consoleReader.printString("What is the application name? ")
        consoleReader.printNewline
        consoleReader.printString(Colors.cyan("> "))
        consoleReader.putString(defaultName)
        consoleReader.flushConsole()
        val name = Option(consoleReader.readLine()).map(_.trim).filter(_.size > 0).getOrElse(defaultName)
        consoleReader.printNewline

        consoleReader.printString("Which template do you want to use for this new application? ")
        consoleReader.printNewline
        consoleReader.printString(
          """|
               |  1             - Create a simple Scala application
               |  2             - Create a simple Java application
               |""".stripMargin)

        consoleReader.printNewline
        consoleReader.printString(Colors.cyan("> "))
        consoleReader.flushConsole()
        consoleReader.putString("")

        val templateNotFound = new RuntimeException("play.home system property is not set, so can not find template")
        val fs = java.io.File.separator
        val templateToUse = Option(consoleReader.readLine()).map(_.trim).getOrElse("") match {
          case "1" => "scala-skel"
          case "2" => "java-skel"
          case g8 @ _ => g8
        }
        (templateToUse, name)
      }<commit_msg>[#877] Added app id validation to match SBT 0.12<commit_after>
package play.console

import jline._
import java.io._
import scalax.file._
import giter8.Giter8

/**
 * provides the console infrastructure for all play apps
 */
object Console {

  val consoleReader = new jline.ConsoleReader

  val logo = Colors.yellow(
    """|       _            _
           | _ __ | | __ _ _  _| |
           || '_ \| |/ _' | || |_|
           ||  __/|_|\____|\__ (_)
           ||_|            |__/
           |
           |""".stripMargin) + ("play! " + play.core.PlayVersion.current + " (using Java " + System.getProperty("java.version") + " and Scala " + play.core.PlayVersion.scalaVersion + "), http://www.playframework.org")

  // -- Commands

  def replace(file: File, tokens: (String, String)*) {
    if (file.exists) {
      Path(file).write(tokens.foldLeft(Path(file).slurpString) { (state, token) =>
        state.replace("%" + token._1 + "%", token._2)
      })
    }
  }

  private def interact(params: Map[String, String]): Map[String, String] = {
    params.map { e =>
      consoleReader.printString(e._1 + "[" + e._2 + "]:".stripMargin)
      consoleReader.putString("")
      e._1 -> Option(consoleReader.readLine()).map(_.trim).filter(_.size > 0).getOrElse(e._2)
    }
  }

  private def generateLocalTemplate(template: String, name: String, path: File): Unit = {
    val random = new java.security.SecureRandom
    val newSecret = (1 to 64).map { _ =>
      (random.nextInt(74) + 48).toChar
    }.mkString.replaceAll("\\\\+", "/")

    def copyRecursively(from: Path, target: Path) {
      import scala.util.control.Exception._
      from.copyTo(target)
      from.children().foreach { child =>
        catching(classOf[java.io.IOException]) opt copyRecursively(child, target / child.name)
      }
    }

    copyRecursively(
      from = Path(new File(System.getProperty("play.home") + "/skeletons/" + template)),
      target = Path(path))

    replace(new File(path, "project/Build.scala"),
      "APPLICATION_NAME" -> name)
    replace(new File(path, "project/plugins.sbt"),
      "PLAY_VERSION" -> play.core.PlayVersion.current)
    replace(new File(path, "conf/application.conf"),
      "APPLICATION_SECRET" -> newSecret)
  }

  private def haveFun(name: String) =
    """|OK, application %s is created.
                  |
                  |Have fun!
                  |""".stripMargin.format(name).trim

  /**
   * Could use the SBT ID parser, except that means going direct into SBT code, which is supposed to be separated
   * and bridged by the xsbti API.  This is semantically equivalent.
   */
  private val IdParser = """(\p{L}[\p{L}\p{LD}_-]*)""".r

  /**
   * Creates a new play app skeleton either based on local templates on g8 templates fetched from github
   * Also, one can create a g8 template directly like this: play new app_name --g8 githubuser/repo.g8
   * @param args first parameter is the application name
   */
  def newCommand(args: Array[String]): (String, Int) = {

    val path = args.headOption.map(new File(_)).getOrElse(new File(".")).getCanonicalFile

    val defaultName = path.getName

    println()
    println(Colors.green("The new application will be created in %s".format(path.getAbsolutePath)))
    println()

    if (path.exists) {
      (Colors.red("The directory already exists, cannot create a new application here."), -1)
    } else {
      val template: (String, String) = if (args.length == 3 && args(1) == "--g8") (args.last, defaultName)
      else {
        var nameInput: Either[String, String] = Right("")
        do {
          consoleReader.printString("What is the application name? [%s]".format(defaultName))
          consoleReader.printNewline()
          nameInput = Option(consoleReader.readLine(Colors.cyan("> "))).map(_.trim).filter(_.size > 0).getOrElse(defaultName) match {
            case IdParser(name) => Right(name)
            case _ => Left("Application name may only contain letters, digits, '_' and '-', and it must start with a letter.")
          }

          nameInput.left.foreach { msg =>
            consoleReader.printString(Colors.red("Error: ") + msg)
            consoleReader.printNewline()
            consoleReader.printNewline()
          }
        } while (nameInput.isLeft)

        val name = nameInput.right.get

        consoleReader.printNewline()
        consoleReader.printString("Which template do you want to use for this new application? ")
        consoleReader.printNewline()
        consoleReader.printString(
          """|
               |  1             - Create a simple Scala application
               |  2             - Create a simple Java application
               |""".stripMargin)

        consoleReader.printNewline()
        consoleReader.putString("")

        val templateToUse = Option(consoleReader.readLine(Colors.cyan("> "))).map(_.trim).getOrElse("") match {
          case "1" => "scala-skel"
          case "2" => "java-skel"
          case g8 @ _ => g8
        }
        (templateToUse, name)
      }
{'fraction_non_alphanumeric': 0.13842931937172775, 'fraction_numerical': 0.0071204188481675396, 'mean_word_length': 2.4806851311953353, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3308127', 'n_tokens_mistral': 2903, 'n_tokens_neox': 2805, 'n_words': 671}