diff --git a/.gitignore b/.gitignore index f117627..eb85297 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -.* project/project project/target target +.idea +.bsp \ No newline at end of file diff --git a/.sbtopts b/.sbtopts new file mode 100644 index 0000000..3cc545d --- /dev/null +++ b/.sbtopts @@ -0,0 +1,2 @@ +-Dfile.encoding=UTF-8 +-J-Xmx2g diff --git a/CHANGELOG b/CHANGELOG index 37e043e..e121cf4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,12 @@ +1.12.4: https://github.com/xitrum-framework/scaposer/pull/26 + +* Support Scala 3, scala.js and scala-native +* Remove support for Scala 2.11 +* Update scala-parser-combinators to 2.3.0 + 1.11.1: https://github.com/xitrum-framework/scaposer/pull/22 -* Support Scala 12.3 +* Support Scala 2.13 * Update scala-parser-combinators from 1.1.1 to 1.1.2 1.11.0: diff --git a/README.rst b/README.rst index 78193ba..e0750dd 100644 --- a/README.rst +++ b/README.rst @@ -112,12 +112,12 @@ i18n2 will overwrite those in i18n1. Use with SBT ------------ -Supported Scala versions: 2.11-2.13 +Supported Scala versions: 2.13-3 build.sbt example: :: - libraryDependencies += "tv.cntt" %% "scaposer" % "1.11.1" + libraryDependencies += "tv.cntt" %% "scaposer" % "1.12.4" Scaposer is used in `Xitrum web framework `_. diff --git a/build.sbt b/build.sbt index bfba97e..6cf945a 100644 --- a/build.sbt +++ b/build.sbt @@ -1,17 +1,69 @@ -organization := "tv.cntt" -name := "scaposer" -version := "1.11.1-SNAPSHOT" +lazy val `scaposer` = crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Pure) + .settings( + name := "scaposer", -scalaVersion := "2.13.0" -crossScalaVersions := Seq("2.13.0", "2.12.8", "2.11.12") + scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked"), + javacOptions ++= Seq("-source", "1.8", "-target", "1.8"), -scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked") -javacOptions ++= Seq("-source", "1.8", "-target", "1.8") + libraryDependencies += "org.scala-lang.modules" %%% "scala-parser-combinators" % "2.3.0", -// Scala 2.11+ core does not include scala.util.parsing.combinator -libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" + libraryDependencies += "org.specs2" %%% "specs2-core" % "4.20.3" % Test, + ) -libraryDependencies += "org.specs2" %% "specs2-core" % "4.6.0" % "test" +ThisBuild / scalaVersion := "2.13.12" +ThisBuild / crossScalaVersions := Seq(scalaVersion.value, "2.12.18", "3.3.1") -//https://github.com/scala/scala-parser-combinators/issues/197 -fork in Test := true \ No newline at end of file +ThisBuild / organization := "io.github.olegych" +ThisBuild / organizationName := "OlegYch" +ThisBuild / organizationHomepage := Some(url("https://github.com/OlegYch")) + +ThisBuild / scmInfo := Some( + ScmInfo( + url("https://github.com/OlegYch/scaposer"), + "scm:git@github.com:OlegYch/scaposer.git" + ) +) +ThisBuild / developers := List( + Developer( + id = "ngocdaothanh", + name = "Ngoc Dao", + email = "ngocdaothanh@gmail.com", + url = url("https://github.com/ngocdaothanh") + ), + Developer( + id = "OlegYch", + name = "Aleh Aleshka", + email = "oleglbch@gmail.com", + url = url("https://github.com/OlegYch") + ), +) + +ThisBuild / description := "GNU Gettext .po file loader for Scala" +ThisBuild / licenses := Seq("MIT" -> url("https://opensource.org/license/mit/")) +ThisBuild / homepage := Some(url("https://github.com/OlegYch/scaposer")) + +// Remove all additional repository other than Maven Central from POM +ThisBuild / pomIncludeRepository := { _ => false } +ThisBuild / publishMavenStyle := true +ThisBuild / publishTo := sonatypePublishToBundle.value +ThisBuild / sonatypeCredentialHost := "s01.oss.sonatype.org" +ThisBuild / sonatypeProfileName := "OlegYch" +ThisBuild / releaseCrossBuild := true + +import ReleaseTransformations._ +ThisBuild / versionScheme := Some("early-semver") +releaseProcess := Seq[ReleaseStep]( + checkSnapshotDependencies, + inquireVersions, + runClean, + runTest, + setReleaseVersion, + commitReleaseVersion, + tagRelease, + releaseStepCommandAndRemaining("+publishSigned"), + releaseStepCommand("sonatypeBundleRelease"), + setNextVersion, + commitNextVersion, + pushChanges +) diff --git a/project/build.properties b/project/build.properties index 8e682c5..e8a1e24 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.18 +sbt.version=1.9.7 diff --git a/project/plugins.sbt b/project/plugins.sbt index b599e4d..91286ba 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,8 @@ -// Run sbt eclipse to create Eclipse project file -addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.14.0") +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.16") + +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10") +addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0") \ No newline at end of file diff --git a/src/main/scala/scaposer/I18n.scala b/scaposer/src/main/scala/scaposer/I18n.scala similarity index 99% rename from src/main/scala/scaposer/I18n.scala rename to scaposer/src/main/scala/scaposer/I18n.scala index edbb441..627f061 100644 --- a/src/main/scala/scaposer/I18n.scala +++ b/scaposer/src/main/scala/scaposer/I18n.scala @@ -168,7 +168,7 @@ case class I18n(ctxSingularToStrs: Map[(String, String), Seq[String]]) { } else { pluralFormso.map { expr => PluralIndexExpressionParser(expr) match { - case PluralIndexExpressionParser.Success(result, _) => x: Long => result(x).toInt + case PluralIndexExpressionParser.Success(result, _) => (x: Long) => result(x).toInt case failure: PluralIndexExpressionParser.NoSuccess => fallbackPluralFormEvaluator _ } }.getOrElse(fallbackPluralFormEvaluator _) diff --git a/src/main/scala/scaposer/ParseFailure.scala b/scaposer/src/main/scala/scaposer/ParseFailure.scala similarity index 100% rename from src/main/scala/scaposer/ParseFailure.scala rename to scaposer/src/main/scala/scaposer/ParseFailure.scala diff --git a/src/main/scala/scaposer/Parser.scala b/scaposer/src/main/scala/scaposer/Parser.scala similarity index 98% rename from src/main/scala/scaposer/Parser.scala rename to scaposer/src/main/scala/scaposer/Parser.scala index da303e5..59a99d1 100644 --- a/src/main/scala/scaposer/Parser.scala +++ b/scaposer/src/main/scala/scaposer/Parser.scala @@ -42,7 +42,7 @@ private class Parser extends JavaTokenParsers { * `b`, `f`, `n`, `r` or `t`. * - `\` followed by `u` followed by four hexadecimal digits */ - private val reStringLiteral: Parser[String] = + private val reStringLiteral: this.Parser[String] = ("\""+"""((\\\")|\p{Space}|\\u[a-fA-F0-9]{4}|[^"\p{Cntrl}\\]|\\[\\/bfnrt])*"""+"\"").r // Scala regex is single line by default diff --git a/src/main/scala/scaposer/PluralIndexExpressionParser.scala b/scaposer/src/main/scala/scaposer/PluralIndexExpressionParser.scala similarity index 65% rename from src/main/scala/scaposer/PluralIndexExpressionParser.scala rename to scaposer/src/main/scala/scaposer/PluralIndexExpressionParser.scala index cdebf1f..65e8f41 100644 --- a/src/main/scala/scaposer/PluralIndexExpressionParser.scala +++ b/scaposer/src/main/scala/scaposer/PluralIndexExpressionParser.scala @@ -4,13 +4,13 @@ import scala.util.parsing.combinator.RegexParsers object PluralIndexExpressionParser extends RegexParsers { private def wholeExpr = nplurals ~ assign ~ integerConst ~ endExpr ~ plural ~ assign ~ subexpr ~ endExpr ^^ { - case _ ~ _ ~ maxIndex ~ _ ~ _ ~ _ ~ f ~ _ => x: Long => Math.min(f(Math.max(x, 0L)), maxIndex) + case _ ~ _ ~ maxIndex ~ _ ~ _ ~ _ ~ f ~ _ => (x: Long) => Math.min(f(Math.max(x, 0L)), maxIndex) } def apply(input: String): ParseResult[Long => Long] = parseAll(wholeExpr, input) final private val assign = "=" - final private val equals = "==" + final private val equals_ = "==" final private val notEquals = "!=" final private val greater = ">" final private val less = "<" @@ -36,13 +36,13 @@ object PluralIndexExpressionParser extends RegexParsers { final private val endExpr = ";" private def number = """\d+""".r ^^ { str => - x: Long => str.toLong + (x: Long) => str.toLong } private def integerConst = """\d+""".r ^^ (_.toInt) private def n = "n" ^^ { _ => - x: Long => x.toLong + (x: Long) => x.toLong } private def subexpr = ternary | logicToNumber | expr @@ -51,44 +51,44 @@ object PluralIndexExpressionParser extends RegexParsers { private def term: Parser[Long => Long] = value ~ rep(multuply ~ value | divide ~ value | mod ~ value) ^^ { case number ~ list => list.foldLeft(number) { - case (x, `multuply` ~ y) => t: Long => x(t) * y(t) - case (x, `divide` ~ y) => t: Long => x(t) / y(t) - case (x, `mod` ~ y) => t: Long => x(t) % y(t) + case (x, `multuply` ~ y) => (t: Long) => x(t) * y(t) + case (x, `divide` ~ y) => (t: Long) => x(t) / y(t) + case (x, `mod` ~ y) => (t: Long) => x(t) % y(t) } } private def expr: Parser[Long => Long] = term ~ rep(plus ~ term | minus ~ term) ^^ { case number ~ list => list.foldLeft(number) { - case (x, `plus` ~ y) => t: Long => x(t) + y(t) - case (x, `minus` ~ y) => t: Long => x(t) - y(t) + case (x, `plus` ~ y) => (t: Long) => x(t) + y(t) + case (x, `minus` ~ y) => (t: Long) => x(t) - y(t) } } - private def compare = expr ~ (greaterOrEquals| lessOrEquals | notEquals | equals | greater | less) ~ expr ^^ { - case a ~ `greaterOrEquals` ~ b => x: Long => a(x) >= b(x) - case a ~ `lessOrEquals` ~ b => x: Long => a(x) <= b(x) - case a ~ `notEquals` ~ b => x: Long => a(x) != b(x) - case a ~ `equals` ~ b => x: Long => a(x) == b(x) - case a ~ `greater` ~ b => x: Long => a(x) > b(x) - case a ~ `less` ~ b => x: Long => a(x) < b(x) + private def compare = expr ~ (greaterOrEquals| lessOrEquals | notEquals | equals_ | greater | less) ~ expr ^^ { + case a ~ `greaterOrEquals` ~ b => (x: Long) => a(x) >= b(x) + case a ~ `lessOrEquals` ~ b => (x: Long) => a(x) <= b(x) + case a ~ `notEquals` ~ b => (x: Long) => a(x) != b(x) + case a ~ `equals_` ~ b => (x: Long) => a(x) == b(x) + case a ~ `greater` ~ b => (x: Long) => a(x) > b(x) + case a ~ `less` ~ b => (x: Long) => a(x) < b(x) } private def logic: Parser[Long => Boolean] = (openBrace ~> (logic) <~ closeBrace) | (compare ~ rep(logicalAnd ~ logic | logicalOr ~ logic) ^^ { case compare ~ list => list.foldLeft(compare) { - case (x, `logicalAnd` ~ y) => t: Long => x(t) && y(t) - case (x, `logicalOr` ~ y) => t: Long => x(t) || y(t) + case (x, `logicalAnd` ~ y) => (t: Long) => x(t) && y(t) + case (x, `logicalOr` ~ y) => (t: Long) => x(t) || y(t) } }) private def logicToNumber: Parser[Long => Long] = logic ^^ { x => - t: Long => if (x(t)) 1 else 0 + (t: Long) => if (x(t)) 1 else 0 } private def negLogic = negation ~ openBrace ~ logic ~ closeBrace ^^ { - case _ ~ _ ~ x ~ _ => t: Long => !x(t) + case _ ~ _ ~ x ~ _ => (t: Long) => !x(t) } private def ternary: Parser[Long => Long] = (logic | negLogic) ~ "?" ~ subexpr ~ ":" ~ subexpr ^^ { - case logic ~ _ ~ yes ~ _ ~ no => x: Long => if (logic(x)) yes(x) else no(x) + case logic ~ _ ~ yes ~ _ ~ no => (x: Long) => if (logic(x)) yes(x) else no(x) } } diff --git a/src/main/scala/scaposer/Translation.scala b/scaposer/src/main/scala/scaposer/Translation.scala similarity index 100% rename from src/main/scala/scaposer/Translation.scala rename to scaposer/src/main/scala/scaposer/Translation.scala diff --git a/src/test/scala/scaposer/I18nSpec.scala b/scaposer/src/test/scala/scaposer/I18nSpec.scala similarity index 100% rename from src/test/scala/scaposer/I18nSpec.scala rename to scaposer/src/test/scala/scaposer/I18nSpec.scala diff --git a/src/test/scala/scaposer/ParserSpec.scala b/scaposer/src/test/scala/scaposer/ParserSpec.scala similarity index 99% rename from src/test/scala/scaposer/ParserSpec.scala rename to scaposer/src/test/scala/scaposer/ParserSpec.scala index cbcd151..2d49395 100644 --- a/src/test/scala/scaposer/ParserSpec.scala +++ b/scaposer/src/test/scala/scaposer/ParserSpec.scala @@ -121,7 +121,7 @@ class ParserSpec extends Specification { private def getPluralIndexEvaluator(expr: String) = { PluralIndexExpressionParser(expr.replace(" ", "")).map { f => - n: Long => f(n).toInt + (n: Long) => f(n).toInt }.get } } diff --git a/version.sbt b/version.sbt new file mode 100644 index 0000000..0260af5 --- /dev/null +++ b/version.sbt @@ -0,0 +1 @@ +ThisBuild / version := "1.12.5-SNAPSHOT"