From c23209b0784b47c24268b1182ff8a6a735f9d5f5 Mon Sep 17 00:00:00 2001 From: Marcin Kostrzewa Date: Thu, 13 Jun 2019 11:49:04 +0200 Subject: [PATCH] Add preliminary package structure and API (#3) --- build.sbt | 21 +++- pkg/src/main/resources/Main.luna | 2 + pkg/src/main/scala/org/enso/pkg/Config.scala | 28 +++++ pkg/src/main/scala/org/enso/pkg/Main.scala | 15 +++ pkg/src/main/scala/org/enso/pkg/Package.scala | 116 ++++++++++++++++++ 5 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 pkg/src/main/resources/Main.luna create mode 100644 pkg/src/main/scala/org/enso/pkg/Config.scala create mode 100644 pkg/src/main/scala/org/enso/pkg/Main.scala create mode 100644 pkg/src/main/scala/org/enso/pkg/Package.scala diff --git a/build.sbt b/build.sbt index 3d8960ac06..7efd96f417 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,8 @@ scalaVersion := "2.12.8" lazy val Benchmark = config("bench") extend Test lazy val bench = taskKey[Unit]("Run Benchmarks") -lazy val enso = (project in file(".")).aggregate(syntax) +lazy val enso = (project in file(".")) + .aggregate(syntax, pkg) lazy val syntax = (project in file("syntax")) .configs(Benchmark) @@ -18,20 +19,28 @@ lazy val syntax = (project in file("syntax")) publishArtifact := false, libraryDependencies ++= Seq( "com.storm-enroute" %% "scalameter" % "0.17" % "bench", - // "org.typelevel" %% "cats-core" % "1.6.0", - // "org.scalatest" %% "scalatest" % "3.0.5" % Test, - // "com.lihaoyi" %% "pprint" % "0.5.3" + "org.typelevel" %% "cats-core" % "1.6.0", + "org.scalatest" %% "scalatest" % "3.0.5" % Test, + "com.lihaoyi" %% "pprint" % "0.5.3" ), resolvers ++= Seq( "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", - "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases" + "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases" ), testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), parallelExecution in Benchmark := false, logBuffered := false ) .settings(SbtJFlexPlugin.jflexSettings) - .settings(mainClass in (Compile,run) := Some("org.enso.syntax.Main")) + .settings(mainClass in (Compile, run) := Some("org.enso.syntax.Main")) .settings(bench := { (test in Benchmark).value }) + +lazy val pkg = (project in file("pkg")) + .settings( + mainClass in (Compile, run) := Some("org.enso.pkg.Main"), + libraryDependencies ++= Seq("circe-core", "circe-generic", "circe-yaml") + .map("io.circe" %% _ % "0.10.0"), + libraryDependencies += "commons-io" % "commons-io" % "2.6" + ) diff --git a/pkg/src/main/resources/Main.luna b/pkg/src/main/resources/Main.luna new file mode 100644 index 0000000000..7ac771dfdb --- /dev/null +++ b/pkg/src/main/resources/Main.luna @@ -0,0 +1,2 @@ +def Main: + None \ No newline at end of file diff --git a/pkg/src/main/scala/org/enso/pkg/Config.scala b/pkg/src/main/scala/org/enso/pkg/Config.scala new file mode 100644 index 0000000000..f1ca856e9b --- /dev/null +++ b/pkg/src/main/scala/org/enso/pkg/Config.scala @@ -0,0 +1,28 @@ +package org.enso.pkg + +import java.io.File +import java.io.PrintWriter + +import io.circe.yaml +import io.circe.generic.auto._ +import io.circe.syntax._ +import io.circe.yaml.syntax._ + +import scala.io.Source +import scala.util.Try + +case class Config( + author: String, + maintainer: String, + name: String, + version: String, + license: String) { + def toYaml: String = this.asJson.asYaml.spaces4 +} + +object Config { + def fromYaml(yamlString: String): Option[Config] = { + yaml.parser.parse(yamlString).flatMap(_.as[Config]).toOption + } + +} diff --git a/pkg/src/main/scala/org/enso/pkg/Main.scala b/pkg/src/main/scala/org/enso/pkg/Main.scala new file mode 100644 index 0000000000..4d0a4854c2 --- /dev/null +++ b/pkg/src/main/scala/org/enso/pkg/Main.scala @@ -0,0 +1,15 @@ +package org.enso.pkg + +import java.io.File + +object Main extends App { + override def main(args: Array[String]): Unit = { + Package.getOrCreate( + new File("/Users/marcinkostrzewa/765Luna__$%%$#Project") + ) + Package.getOrCreate( + new File("/Users/marcinkostrzewa/proper_%%$##%#project") + ) + Package.getOrCreate(new File("/Users/marcinkostrzewa/Properproject")) + } +} diff --git a/pkg/src/main/scala/org/enso/pkg/Package.scala b/pkg/src/main/scala/org/enso/pkg/Package.scala new file mode 100644 index 0000000000..2a5b1779a5 --- /dev/null +++ b/pkg/src/main/scala/org/enso/pkg/Package.scala @@ -0,0 +1,116 @@ +package org.enso.pkg + +import java.io.File +import java.io.PrintWriter + +import org.apache.commons.io.FileUtils + +import scala.io.Source +import scala.util.Try + +object CouldNotCreateDirectory extends Exception + +case class Package(root: File, config: Config) { + + val sourceDir = new File(root, Package.sourceDirName) + val configFile = new File(root, Package.configFileName) + val thumbFile = new File(root, Package.thumbFileName) + + def save(): Unit = { + if (!root.exists) createDirectories() + if (!sourceDir.exists) createSourceDir() + saveConfig() + } + + def createDirectories() { + val created = Try(root.mkdirs).getOrElse(false) + if (!created) throw CouldNotCreateDirectory + createSourceDir() + } + + def rename(newName: String): Package = { + val newPkg = copy(config = config.copy(name = newName)) + newPkg.save() + newPkg + } + + def remove(): Unit = { + FileUtils.deleteDirectory(root) + } + + def move(newRoot: File): Package = { + val newPkg = copyPackage(newRoot) + remove() + newPkg + } + + def copyPackage(newRoot: File): Package = { + FileUtils.copyDirectory(root, newRoot) + copy(root = newRoot) + } + + def createSourceDir(): Unit = { + if (!Try(sourceDir.mkdir).getOrElse(false)) throw CouldNotCreateDirectory + val lunaCodeSrc = Source.fromResource(Package.mainFileName) + val writer = new PrintWriter(new File(sourceDir, Package.mainFileName)) + writer.write(lunaCodeSrc.mkString) + writer.close() + lunaCodeSrc.close() + } + + def saveConfig(): Unit = { + val writer = new PrintWriter(configFile) + Try(writer.write(config.toYaml)) + writer.close() + } + + def hasThumb: Boolean = thumbFile.exists + def name: String = config.name +} + +object Package { + val configFileName = "package.yaml" + val sourceDirName = "src" + val mainFileName = "Main.luna" + val thumbFileName = "thumb.png" + + def create(root: File, config: Config): Package = { + val pkg = Package(root, config) + pkg.save() + pkg + } + + def create(root: File, name: String): Package = { + val config = Config( + author = "", + maintainer = "", + name = name, + version = "", + license = "" + ) + create(root, config) + } + + def fromDirectory(root: File): Option[Package] = { + if (!root.exists()) return None + val configFile = new File(root, configFileName) + val source = Try(Source.fromFile(configFile)) + val result = source.map(_.mkString).toOption.flatMap(Config.fromYaml) + source.foreach(_.close()) + result.map(Package(root, _)) + } + + def getOrCreate(root: File): Package = { + val existing = fromDirectory(root) + existing.getOrElse(create(root, generateName(root))) + } + + def generateName(file: File): String = { + val dirname = file.getName + val startingWithLetter = + if (!dirname(0).isLetter) "Project" ++ dirname else dirname + val startingWithUppercase = startingWithLetter.capitalize + val onlyAlphanumeric = startingWithUppercase.filter(_.isLetterOrDigit) + onlyAlphanumeric + } +}