From c321c433a10da0a9b6e0f6379ed44ab8567def7c Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Wed, 10 Oct 2018 09:30:09 +0200 Subject: Added mill-osgi module to documentation, contrib modules --- docs/pages/9 - Contrib Modules.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index f6c9cc7b..19817a4b 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -143,3 +143,24 @@ Quickstart: [40/40] project.publishM2Local Publishing to /tmp/m2repo ``` + +- [osgi](https://github.com/lefou/mill-osgi "GitHub-Project lefou/mill-osgi") + + Produce OSGi Bundles with mill. + + Quickstart: + ```scala + import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.2` + import de.tobiasroeser.mill.osgi._ + + object project extends ScalaModule with OsgiBundleModule { + + def bundleSymbolicName = "com.example.project" + + def osgiHeaders = T{ osgiHeaders().copy( + `Export-Package` = Seq("com.example.api"), + `Bundle-Activator` = Some("com.example.internal.Activator") + )} + + } + ``` -- cgit v1.2.3 From c10e342b904a9c120b323ab08709e97e7589cd57 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 21 Oct 2018 11:05:44 +0200 Subject: Fixed some markdown formatting --- docs/pages/9 - Contrib Modules.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index 19817a4b..f9270e38 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -109,58 +109,60 @@ Quickstart: ``` - [publishM2](https://github.com/lefou/mill-publishM2 "mill-publishM2") - + Mill plugin to publish artifacts into a local Maven repository. - + Quickstart: - + Just mix-in the `PublishM2Module` into your project. `PublishM2Module` already extends mill's built-in `PublishModule`. - + File: `build.sc` ```scala import mill._, scalalib._, publish._ - + import $ivy.`de.tototec::de.tobiasroeser.mill.publishM2:0.0.1` import de.tobiasroeser.mill.publishM2._ - + object project extends PublishModule with PublishM2Module { // ... } ``` - + Publishing to default local Maven repository - - ``` + + ```bash > mill project.publishM2Local [40/40] project.publishM2Local Publishing to /home/user/.m2/repository ``` - + Publishing to custom local Maven repository - ``` + + ```bash > mill project.publishM2Local /tmp/m2repo [40/40] project.publishM2Local Publishing to /tmp/m2repo ``` - [osgi](https://github.com/lefou/mill-osgi "GitHub-Project lefou/mill-osgi") - + Produce OSGi Bundles with mill. - + Quickstart: ```scala import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.2` import de.tobiasroeser.mill.osgi._ - + object project extends ScalaModule with OsgiBundleModule { - + def bundleSymbolicName = "com.example.project" - + def osgiHeaders = T{ osgiHeaders().copy( `Export-Package` = Seq("com.example.api"), `Bundle-Activator` = Some("com.example.internal.Activator") )} - + } ``` + -- cgit v1.2.3 From 2ccad83244b2630ba4183d926a91d8b3f92b9a31 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 21 Oct 2018 14:05:50 +0200 Subject: Re-organized thirdparty plugin section Each plugin is a level-3 section, that appears also in TOC. Plugins are in alphabetical order. --- docs/pages/9 - Contrib Modules.md | 168 +++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 77 deletions(-) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index f9270e38..aa7b21a7 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -82,87 +82,101 @@ Quickstart: The package name of the object. -### Other Mill Plugins +## Thirdparty Mill Plugins -- [ensime](https://github.com/yyadavalli/mill-ensime "mill-ensime") - - Create an [.ensime](http://ensime.github.io/ "ensime") file for your build. - - Quickstart: - ```scala - import $ivy.`fun.valycorp::mill-ensime:0.0.1` - ``` - ```sh - sh> mill fun.valycorp.mill.GenEnsime/ensimeConfig - ``` +### DGraph -- [dgraph](https://github.com/ajrnz/mill-dgraph "mill-dgraph") +Show transitive dependencies of your build in your browser. - Show transitive dependencies of your build in your browser. - - Quickstart: - ```scala - import $ivy.`com.github.ajrnz::mill-dgraph:0.2.0` - ``` - ```sh - sh> mill plugin.dgraph.browseDeps(proj)() - ``` +Project home: https://github.com/ajrnz/mill-dgraph -- [publishM2](https://github.com/lefou/mill-publishM2 "mill-publishM2") - - Mill plugin to publish artifacts into a local Maven repository. - - Quickstart: - - Just mix-in the `PublishM2Module` into your project. - `PublishM2Module` already extends mill's built-in `PublishModule`. - - File: `build.sc` - ```scala - import mill._, scalalib._, publish._ - - import $ivy.`de.tototec::de.tobiasroeser.mill.publishM2:0.0.1` - import de.tobiasroeser.mill.publishM2._ - - object project extends PublishModule with PublishM2Module { - // ... - } - ``` - - Publishing to default local Maven repository - - ```bash - > mill project.publishM2Local - [40/40] project.publishM2Local - Publishing to /home/user/.m2/repository - ``` - - Publishing to custom local Maven repository - - ```bash - > mill project.publishM2Local /tmp/m2repo - [40/40] project.publishM2Local - Publishing to /tmp/m2repo - ``` +#### Quickstart -- [osgi](https://github.com/lefou/mill-osgi "GitHub-Project lefou/mill-osgi") - - Produce OSGi Bundles with mill. - - Quickstart: - ```scala - import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.2` - import de.tobiasroeser.mill.osgi._ - - object project extends ScalaModule with OsgiBundleModule { - - def bundleSymbolicName = "com.example.project" - - def osgiHeaders = T{ osgiHeaders().copy( - `Export-Package` = Seq("com.example.api"), - `Bundle-Activator` = Some("com.example.internal.Activator") - )} +```scala +import $ivy.`com.github.ajrnz::mill-dgraph:0.2.0` +``` + +```sh +sh> mill plugin.dgraph.browseDeps(proj)() +``` + +### Ensime + +Create an [.ensime](http://ensime.github.io/ "ensime") file for your build. + +Project home: https://github.com/yyadavalli/mill-ensime - } - ``` +#### Quickstart + +```scala +import $ivy.`fun.valycorp::mill-ensime:0.0.1` +``` + +```sh +sh> mill fun.valycorp.mill.GenEnsime/ensimeConfig +``` + +### OSGi + +Produce OSGi Bundles with mill. + +Project home: https://github.com/lefou/mill-osgi + +#### Quickstart + +```scala +import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.2` +import de.tobiasroeser.mill.osgi._ + +object project extends ScalaModule with OsgiBundleModule { + + def bundleSymbolicName = "com.example.project" + + def osgiHeaders = T{ osgiHeaders().copy( + `Export-Package` = Seq("com.example.api"), + `Bundle-Activator` = Some("com.example.internal.Activator") + )} + +} +``` + + +### PublishM2 + +Mill plugin to publish artifacts into a local Maven repository. + +Project home: https://github.com/lefou/mill-publishM2 + +#### Quickstart + +Just mix-in the `PublishM2Module` into your project. +`PublishM2Module` already extends mill's built-in `PublishModule`. + +File: `build.sc` +```scala +import mill._, scalalib._, publish._ + +import $ivy.`de.tototec::de.tobiasroeser.mill.publishM2:0.0.1` +import de.tobiasroeser.mill.publishM2._ + +object project extends PublishModule with PublishM2Module { + // ... +} +``` + +Publishing to default local Maven repository + +```bash +> mill project.publishM2Local +[40/40] project.publishM2Local +Publishing to /home/user/.m2/repository +``` + +Publishing to custom local Maven repository + +```bash +> mill project.publishM2Local /tmp/m2repo +[40/40] project.publishM2Local +Publishing to /tmp/m2repo +``` -- cgit v1.2.3 From cb0eb362a12a09a4cc5455fe8513c15a79d8bdf6 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Fri, 26 Oct 2018 09:35:15 +0200 Subject: Fixed formatting of code block --- docs/pages/9 - Contrib Modules.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index aa7b21a7..13f7b655 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -58,27 +58,27 @@ This plugin generates a single object containing information from your build. To declare a module that uses BuildInfo you must extend the `mill.contrib.BuildInfo` trait when defining your module. Quickstart: - ```scala - object project extends BuildInfo { - val name = "poject-name" - def buildInfoMembers: T[Map[String, String]] = T { - Map( - "name" -> name), - "scalaVersion" -> scalaVersion() - ) - } +```scala +object project extends BuildInfo { + val name = "poject-name" + def buildInfoMembers: T[Map[String, String]] = T { + Map( + "name" -> name), + "scalaVersion" -> scalaVersion() + ) } - ``` +} +``` #### Configuration options -* `def buildInfoMembers: T[Map[String, String]]` +* `def buildInfoMembers: T[Map[String, String]]` The map containing all member names and values for the generated info object. -* `def buildInfoObjectName: String`, default: `BuildInfo` +* `def buildInfoObjectName: String`, default: `BuildInfo` The name of the object which contains all the members from `buildInfoMembers`. -* `def buildInfoPackageName: Option[String]`, default: `None` +* `def buildInfoPackageName: Option[String]`, default: `None` The package name of the object. -- cgit v1.2.3 From 6f3f9f67c24cbbd661090fe863d72b3dc499663e Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Fri, 26 Oct 2018 22:47:42 +0200 Subject: Fixed links in documentation --- docs/pages/7 - Extending Mill.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs/pages') diff --git a/docs/pages/7 - Extending Mill.md b/docs/pages/7 - Extending Mill.md index 2eb7c93b..2e59dfe3 100644 --- a/docs/pages/7 - Extending Mill.md +++ b/docs/pages/7 - Extending Mill.md @@ -176,7 +176,6 @@ def idea(ev: Evaluator) = T.command { ``` Many built-in tools are implemented as custom evaluator commands: -[all](intro.html#all), [inspect](intro.html#inspect), -[resolve](intro.html#resolve), [show](intro.html#show). If you want a way to run Mill -commands and programmatically manipulate the tasks and outputs, you do so with -your own evaluator command. +[all](http://www.lihaoyi.com/mill/#all), [inspect](http://www.lihaoyi.com/mill/#inspect), +[resolve](http://www.lihaoyi.com/mill/#resolve), [show](http://www.lihaoyi.com/mill/#show). +If you want a way to run Mill commands and programmatically manipulate the tasks and outputs, you do so with your own evaluator command. -- cgit v1.2.3 From 05dcd53c07bbdc7afcf7fc2901f2758edf4efe17 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Sun, 28 Oct 2018 17:37:03 +0100 Subject: Added docs for TestNG support and sorted contrib modules --- docs/pages/9 - Contrib Modules.md | 67 ++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 25 deletions(-) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index 13f7b655..9b44082d 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -1,5 +1,36 @@ ## Contrib Modules +### BuildInfo + +Generate scala code from your buildfile. +This plugin generates a single object containing information from your build. + +To declare a module that uses BuildInfo you must extend the `mill.contrib.BuildInfo` trait when defining your module. + +Quickstart: +```scala +object project extends BuildInfo { + val name = "poject-name" + def buildInfoMembers: T[Map[String, String]] = T { + Map( + "name" -> name), + "scalaVersion" -> scalaVersion() + ) + } +} +``` + +#### Configuration options + +* `def buildInfoMembers: T[Map[String, String]]` + The map containing all member names and values for the generated info object. + +* `def buildInfoObjectName: String`, default: `BuildInfo` + The name of the object which contains all the members from `buildInfoMembers`. + +* `def buildInfoPackageName: Option[String]`, default: `None` + The package name of the object. + ### ScalaPB This module allows [ScalaPB](https://scalapb.github.io) to be used in Mill builds. ScalaPB is a [Protocol Buffers](https://developers.google.com/protocol-buffers/) compiler plugin that generates Scala case classes, encoders and decoders for protobuf messages. @@ -50,42 +81,29 @@ object example extends ScalaPBModule { } ``` -### BuildInfo +### TestNG -Generate scala code from your buildfile. -This plugin generates a single object containing information from your build. - -To declare a module that uses BuildInfo you must extend the `mill.contrib.BuildInfo` trait when defining your module. +Provides support for [TestNG](https://testng.org/doc/index.html). + +To use TestNG as test framework, you need to add it to the `TestModule.testFrameworks` property. -Quickstart: ```scala -object project extends BuildInfo { - val name = "poject-name" - def buildInfoMembers: T[Map[String, String]] = T { - Map( - "name" -> name), - "scalaVersion" -> scalaVersion() - ) +object project extends ScalaModule { + object test extends Tests{ + def testFrameworks = Seq("mill.testng.TestNGFramework") } } ``` - -#### Configuration options -* `def buildInfoMembers: T[Map[String, String]]` - The map containing all member names and values for the generated info object. +### Twirl -* `def buildInfoObjectName: String`, default: `BuildInfo` - The name of the object which contains all the members from `buildInfoMembers`. - -* `def buildInfoPackageName: Option[String]`, default: `None` - The package name of the object. +(todo) ## Thirdparty Mill Plugins ### DGraph - + Show transitive dependencies of your build in your browser. Project home: https://github.com/ajrnz/mill-dgraph @@ -105,7 +123,7 @@ sh> mill plugin.dgraph.browseDeps(proj)() Create an [.ensime](http://ensime.github.io/ "ensime") file for your build. Project home: https://github.com/yyadavalli/mill-ensime - + #### Quickstart ```scala @@ -179,4 +197,3 @@ Publishing to custom local Maven repository [40/40] project.publishM2Local Publishing to /tmp/m2repo ``` - -- cgit v1.2.3 From c854d55b8cfb0481a76ee6886cb31275fe8d5ffe Mon Sep 17 00:00:00 2001 From: Iurii Malchenko Date: Sun, 28 Oct 2018 18:51:28 +0200 Subject: adding TwirlModule docs --- docs/pages/9 - Contrib Modules.md | 150 +++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) (limited to 'docs/pages') diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index 9b44082d..4ddf097a 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -97,7 +97,155 @@ object project extends ScalaModule { ### Twirl -(todo) +Twirl templates support. + +To declare a module that needs to compile twirl templates you must extend the `mill.twirllib.TwirlModule` trait when defining your module. +Also note that twirl templates get compiled into scala code, so you also need to extend `ScalaModule`. + +```scala +import $ivy.`com.lihaoyi::mill-contrib-twirllib:0.3.2`, mill.twirllib._ +object app extends ScalaModule with TwirlModule { + +} +``` + +#### Configuration options + +* ` def twirlVersion: T[String]` (mandatory) - the version of the twirl compiler to use, like "1.3.15" + +#### Details + +The following filesystem layout is expected: + +```text +build.sc +app/ + views/ + view1.scala.html + view2.scala.html +``` + +`TwirlModule` adds the `compileTwirl` task to the module: +``` +mill app.compileTwirl +``` + +(it will be automatically run whenever you compile your module) + +This task will compile `*.scala.html` templates (and others, like `*.scala.txt`) into the `out/app/compileTwirl/dest` +directory. This directory must be added to the generated sources of the module to be compiled and made accessible from the rest of the code: +```scala +object app extends ScalaModule with TwirlModule { + def twirlVersion = "1.3.15" + def generatedSources = T{ Seq(compileTwirl().classes) } +} +``` + +#### Caveats + +There is a couple of caveats, to be aware of, as of now (in `v0.3.2`). + +##### Packages +First, if you structure your twirl templates into packages, like this: +```text +build.sc +app/ + src/hello/ + Main.scala + views/ + hello/ + another/ + view1.scala.html + view2.scala.html +``` + +the generated sources in the `out` directory will look like this: +```text +build.sc +out/app/compileTwirl/dest/ + hello/ + another/ + html/ + view1.template.scala + view2.template.scala +``` + +Looking at the `mill show app.compileTwirl` in this setup shows this: +``` +{ + ... + "classes": "ref: ... : .../out/app/compileTwirl/dest/html" +} +``` + +Basically it means that currently `TwirlModule` expects all templates to be html and with no packages. +So adding this directly to the generated sources will not exactly work as expected (as there might not even be a `out/app/compileTwirl/dest/html` directory +at all, unless you have templates in the default package). + +The workaround is simple, though: +```scala +object app extends ScalaModule with TwirlModule { + def twirlVersion = "1.3.15" + override def generatedSources = T{ + val classes = compileTwirl().classes + Seq(classes.copy(path = classes.path / up)) // we just move one dir up + } +} +``` + +This should cover the problem with templates under packages, and also should make other-than-html +templates available as well. + +##### Default imports + +Another problem is with some default imports that the twirl sbt plugin assumes, but it seems not to work with `TwirlModule`. + +If you reference `Html` in your templates, like + +```scala +// wrapper.scala.html +@(content: Html) +
+ @content +
+``` + +the template will not compile. You'll need to add this import: +``` +@import play.twirl.api._ +``` + +in the template that uses twirl classes. + +Another one is `@defining`, which might be used like this: +``` +@defining({ + val calculatedClass = { + // do some calculations here + } + calculatedClass +}) { calculatedClass => +
stuff 1
+
stuff 2
+} +``` + +You'll need this import: +```scala +@import play.twirl.api.TwirlFeatureImports._ +``` + +At some point `TwirlModule` might get support for the additional "default" imports, which will make this much easier, +but right now it is unimplemented + +```scala + // REMIND currently it's not possible to override these default settings + private def twirlAdditionalImports: Seq[String] = Nil +``` + +#### Example +There's an [example project](https://github.com/lihaoyi/cask/tree/master/example/twirl) + ## Thirdparty Mill Plugins -- cgit v1.2.3 From 099fdb8defb7d2c8316da94d749c0c23088e0dc9 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Tue, 30 Oct 2018 08:33:14 +0100 Subject: Added a section about debug logging to documentation --- docs/pages/4 - Tasks.md | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs/pages') diff --git a/docs/pages/4 - Tasks.md b/docs/pages/4 - Tasks.md index 6c7737e0..e8a1c94c 100644 --- a/docs/pages/4 - Tasks.md +++ b/docs/pages/4 - Tasks.md @@ -199,6 +199,9 @@ task are streamed to standard out/error as you would expect, but each task's specific output is also streamed to a log file on disk, e.g. `out/run/log` or `out/classFiles/log` for you to inspect later. +Messages logged with `log.debug` appear by default only in the log files. +You can use the `--debug` option when running mill to show them on the console too. + ### mill.util.Ctx.Env - `T.ctx().env` -- cgit v1.2.3 From 7b4ced648ecd9b79b3a16d67552f0bb69f4dd543 Mon Sep 17 00:00:00 2001 From: David Gregory Date: Wed, 31 Oct 2018 20:44:53 +0000 Subject: Add tut contrib module (#464) * Add tut contrib module * Add TutModule tests and documentation * Use Path instead of PathRef for tut target directory * Use the correct scala version in TutModule * Ensure resolving tut doesn't bring in extra scala-library jars * Ensure MILL_VERSION system property is set in tut tests * Fork to run tut to fix classpath problems, add test with library usage * Follow convention w.r.t. publishVersion in testArgs * Add Scaladoc to TutModule * Don't supply a default version of Tut * Update docs to account for mandatory tutVersion setting * Inline tutArgs, otherwise Tut does not recompile when sources change --- build.sc | 6 +- contrib/tut/src/mill/contrib/tut/TutModule.scala | 132 +++++++++++++++++++++ .../tut/test/src/mill/contrib/tut/TutTests.scala | 124 +++++++++++++++++++ .../test/tut-with-libraries/TutWithLibraries.md | 10 ++ contrib/tut/test/tut/TutExample.md | 3 + docs/pages/9 - Contrib Modules.md | 56 +++++++++ main/core/src/mill/util/JsonFormatters.scala | 7 ++ 7 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 contrib/tut/src/mill/contrib/tut/TutModule.scala create mode 100644 contrib/tut/test/src/mill/contrib/tut/TutTests.scala create mode 100644 contrib/tut/test/tut-with-libraries/TutWithLibraries.md create mode 100644 contrib/tut/test/tut/TutExample.md (limited to 'docs/pages') diff --git a/build.sc b/build.sc index aa1cf428..878f5613 100755 --- a/build.sc +++ b/build.sc @@ -250,6 +250,10 @@ object contrib extends MillModule { } } + object tut extends MillModule { + def moduleDeps = Seq(scalalib) + def testArgs = Seq("-DMILL_VERSION=" + build.publishVersion()._2) + } } @@ -362,7 +366,7 @@ def launcherScript(shellJvmArgs: Seq[String], } object dev extends MillModule{ - def moduleDeps = Seq(scalalib, scalajslib, scalanativelib, contrib.scalapblib) + def moduleDeps = Seq(scalalib, scalajslib, scalanativelib, contrib.scalapblib, contrib.tut) def forkArgs = ( diff --git a/contrib/tut/src/mill/contrib/tut/TutModule.scala b/contrib/tut/src/mill/contrib/tut/TutModule.scala new file mode 100644 index 00000000..f051a465 --- /dev/null +++ b/contrib/tut/src/mill/contrib/tut/TutModule.scala @@ -0,0 +1,132 @@ +package mill +package contrib.tut + +import ammonite.ops._ +import coursier.MavenRepository +import mill.scalalib._ +import scala.util.matching.Regex + +/** + * Tut is a documentation tool which compiles and evaluates Scala code in documentation files and provides various options for configuring how the results will be displayed in the compiled documentation. + * + * Extending this trait declares a Scala module which compiles markdown, HTML and `.txt` files in the `tut` folder of the module with Tut. + * + * By default the resulting documents are simply placed in the Mill build output folder but they can be placed elsewhere by overriding the [[mill.contrib.tut.TutModule#tutTargetDirectory]] task. + * + * For example: + * + * {{{ + * // build.sc + * import mill._, scalalib._, contrib.tut.__ + * + * object example extends TutModule { + * def scalaVersion = "2.12.6" + * def tutVersion = "0.6.7" + * } + * }}} + * + * This defines a project with the following layout: + * + * {{{ + * build.sc + * example/ + * src/ + * tut/ + * resources/ + * }}} + * + * In order to compile documentation we can execute the `tut` task in the module: + * + * {{{ + * sh> mill example.tut + * }}} + */ +trait TutModule extends ScalaModule { + /** + * This task determines where documentation files must be placed in order to be compiled with Tut. By default this is the `tut` folder at the root of the module. + */ + def tutSourceDirectory = T.sources { millSourcePath / 'tut } + + /** + * A task which determines where the compiled documentation files will be placed. By default this is simply the Mill build's output folder for this task, + * but this can be reconfigured so that documentation goes to the root of the module (e.g. `millSourcePath`) or to a dedicated folder (e.g. `millSourcePath / 'docs`) + */ + def tutTargetDirectory: T[Path] = T { T.ctx().dest } + + /** + * A task which determines what classpath is used when compiling documentation. By default this is configured to use the same inputs as the [[mill.contrib.tut.TutModule#runClasspath]], + * except for using [[mill.contrib.tut.TutModule#tutIvyDeps]] rather than the module's [[mill.contrib.tut.TutModule#runIvyDeps]]. + */ + def tutClasspath: T[Agg[PathRef]] = T { + // Same as runClasspath but with tut added to ivyDeps from the start + // This prevents duplicate, differently versioned copies of scala-library ending up on the classpath which can happen when resolving separately + transitiveLocalClasspath() ++ + resources() ++ + localClasspath() ++ + unmanagedClasspath() ++ + tutIvyDeps() + } + + /** + * A task which determines the scalac plugins which will be used when compiling code examples with Tut. The default is to use the [[mill.contrib.tut.TutModule#scalacPluginIvyDeps]] for the module. + */ + def tutScalacPluginIvyDeps: T[Agg[Dep]] = scalacPluginIvyDeps() + + /** + * A [[scala.util.matching.Regex]] task which will be used to determine which files should be compiled with tut. The default pattern is as follows: `.*\.(md|markdown|txt|htm|html)`. + */ + def tutNameFilter: T[Regex] = T { """.*\.(md|markdown|txt|htm|html)""".r } + + /** + * The scalac options which will be used when compiling code examples with Tut. The default is to use the [[mill.contrib.tut.TutModule#scalacOptions]] for the module, + * but filtering out options which are problematic in the REPL, e.g. `-Xfatal-warnings`, `-Ywarn-unused-imports`. + */ + def tutScalacOptions: T[Seq[String]] = + scalacOptions().filterNot(Set( + "-Ywarn-unused:imports", + "-Ywarn-unused-import", + "-Ywarn-dead-code", + "-Xfatal-warnings" + )) + + /** + * The version of Tut to use. + */ + def tutVersion: T[String] + + /** + * A task which determines how to fetch the Tut jar file and all of the dependencies required to compile documentation for the module and returns the resulting files. + */ + def tutIvyDeps: T[Agg[PathRef]] = T { + Lib.resolveDependencies( + repositories :+ MavenRepository(s"https://dl.bintray.com/tpolecat/maven"), + Lib.depToDependency(_, scalaVersion()), + compileIvyDeps() ++ transitiveIvyDeps() ++ Seq( + ivy"org.tpolecat::tut-core:${tutVersion()}" + ) + ) + } + + /** + * A task which performs the dependency resolution for the scalac plugins to be used with Tut. + */ + def tutPluginJars: T[Agg[PathRef]] = resolveDeps(tutScalacPluginIvyDeps)() + + /** + * Run Tut using the configuration specified in this module. The working directory used is the [[mill.contrib.tut.TutModule#millSourcePath]]. + */ + def tut: T[CommandResult] = T { + val in = tutSourceDirectory().head.path.toIO.getAbsolutePath + val out = tutTargetDirectory().toIO.getAbsolutePath + val re = tutNameFilter() + val opts = tutScalacOptions() + val pOpts = tutPluginJars().map(pathRef => "-Xplugin:" + pathRef.path.toIO.getAbsolutePath) + val tutArgs = List(in, out, re.pattern.toString) ++ opts ++ pOpts + %%( + 'java, + "-cp", tutClasspath().map(_.path.toIO.getAbsolutePath).mkString(java.io.File.pathSeparator), + "tut.TutMain", + tutArgs + )(wd = millSourcePath) + } +} diff --git a/contrib/tut/test/src/mill/contrib/tut/TutTests.scala b/contrib/tut/test/src/mill/contrib/tut/TutTests.scala new file mode 100644 index 00000000..fd369eed --- /dev/null +++ b/contrib/tut/test/src/mill/contrib/tut/TutTests.scala @@ -0,0 +1,124 @@ +package mill.contrib +package tut + +import ammonite.ops._ +import mill._ +import mill.eval.Result._ +import mill.scalalib._ +import mill.util.{TestEvaluator, TestUtil} +import utest._ +import utest.framework.TestPath + +object TutTests extends TestSuite { + + trait TutTestModule extends TestUtil.BaseModule with TutModule { + def millSourcePath = TestUtil.getSrcPathBase() / millOuterCtx.enclosing.split('.') + def scalaVersion = "2.12.4" + def tutVersion = "0.6.7" + } + + object TutTest extends TutTestModule + + object TutCustomTest extends TutTestModule { + def tutTargetDirectory = millSourcePath + } + + object TutLibrariesTest extends TutTestModule { + def ivyDeps = Agg(ivy"org.typelevel::cats-core:1.4.0") + def tutSourceDirectory = T.sources { resourcePathWithLibraries } + def scalacPluginIvyDeps = Agg(ivy"org.spire-math::kind-projector:0.9.8") + } + + val resourcePath = pwd / 'contrib / 'tut / 'test / 'tut + val resourcePathWithLibraries = pwd / 'contrib / 'tut / 'test / "tut-with-libraries" + + def workspaceTest[T](m: TestUtil.BaseModule, resourcePath: Path = resourcePath) + (t: TestEvaluator => T) + (implicit tp: TestPath): T = { + val eval = new TestEvaluator(m) + rm(m.millSourcePath) + rm(eval.outPath) + mkdir(m.millSourcePath) + cp(resourcePath, m.millSourcePath / 'tut) + t(eval) + } + + def tests: Tests = Tests { + 'tut - { + 'createOutputFile - workspaceTest(TutTest) { eval => + val expectedPath = + eval.outPath / 'tutTargetDirectory / 'dest / "TutExample.md" + + val expected = + """ + |```scala + |scala> 1 + 1 + |res0: Int = 2 + |``` + | + """.trim.stripMargin + + val Right((result, evalCount)) = eval.apply(TutTest.tut) + + assert( + exists(expectedPath) && + read! expectedPath == expected + ) + } + + 'supportCustomSettings - workspaceTest(TutCustomTest) { eval => + val defaultPath = + eval.outPath / 'tutTargetDirectory / 'dest / "TutExample.md" + val expectedPath = + TutCustomTest.millSourcePath / "TutExample.md" + + val expected = + """ + |```scala + |scala> 1 + 1 + |res0: Int = 2 + |``` + | + """.trim.stripMargin + + val Right((result, evalCount)) = eval.apply(TutCustomTest.tut) + + assert( + !exists(defaultPath) && + exists(expectedPath) && + read! expectedPath == expected + ) + } + + 'supportUsingLibraries - workspaceTest(TutLibrariesTest, resourcePath = resourcePathWithLibraries) { eval => + val expectedPath = + eval.outPath / 'tutTargetDirectory / 'dest / "TutWithLibraries.md" + + val expected = + """ + |```scala + |import cats._ + |import cats.arrow.FunctionK + |import cats.implicits._ + |``` + | + |```scala + |scala> List(1, 2, 3).combineAll + |res0: Int = 6 + | + |scala> λ[FunctionK[List, Option]](_.headOption)(List(1, 2 ,3)) + |res1: Option[Int] = Some(1) + |``` + | + """.trim.stripMargin + + val Right(_) = eval.apply(TutLibrariesTest.tut) + + assert( + exists(expectedPath) && + read! expectedPath == expected + ) + } + } + } +} diff --git a/contrib/tut/test/tut-with-libraries/TutWithLibraries.md b/contrib/tut/test/tut-with-libraries/TutWithLibraries.md new file mode 100644 index 00000000..7df1e703 --- /dev/null +++ b/contrib/tut/test/tut-with-libraries/TutWithLibraries.md @@ -0,0 +1,10 @@ +```tut:silent +import cats._ +import cats.arrow.FunctionK +import cats.implicits._ +``` + +```tut +List(1, 2, 3).combineAll +λ[FunctionK[List, Option]](_.headOption)(List(1, 2 ,3)) +``` diff --git a/contrib/tut/test/tut/TutExample.md b/contrib/tut/test/tut/TutExample.md new file mode 100644 index 00000000..c149fbc6 --- /dev/null +++ b/contrib/tut/test/tut/TutExample.md @@ -0,0 +1,3 @@ +```tut +1 + 1 +``` diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index 4ddf097a..cd02f2c2 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -95,6 +95,62 @@ object project extends ScalaModule { } ``` +### Tut + +This module allows [Tut](https://tpolecat.github.io/tut) to be used in Mill builds. Tut is a documentation tool which compiles and evaluates Scala code in documentation files and provides various options for configuring how the results will be displayed in the compiled documentation. + +To declare a module that uses Tut you can extend the `mill.contrib.tut.TutModule` trait when defining your module. + +This creates a Scala module which compiles markdown, HTML and `.txt` files in the `tut` folder of the module with Tut. + +By default the resulting documents are simply placed in the Mill build output folder but they can be placed elsewhere by overriding the `tutTargetDirectory` task. + +```scala +// build.sc +import mill._, scalalib._, contrib.tut.__ + +object example extends TutModule { + def scalaVersion = "2.12.6" + def tutVersion = "0.6.7" +} +``` + +This defines a project with the following layout: + +``` +build.sc +example/ + src/ + tut/ + resources/ +``` + +In order to compile documentation we can execute the `tut` task in the module: + +``` +sh> mill example.tut +``` + +#### Configuration options + +* tutSourceDirectory - This task determines where documentation files must be placed in order to be compiled with Tut. By default this is the `tut` folder at the root of the module. + +* tutTargetDirectory - A task which determines where the compiled documentation files will be placed. By default this is simply the Mill build's output folder for the `tutTargetDirectory` task but this can be reconfigured so that documentation goes to the root of the module (e.g. `millSourcePath`) or to a dedicated folder (e.g. `millSourcePath / 'docs`) + +* tutClasspath - A task which determines what classpath is used when compiling documentation. By default this is configured to use the same inputs as the `runClasspath`, except for using `tutIvyDeps` rather than the module's `ivyDeps`. + +* tutScalacPluginIvyDeps - A task which determines the scalac plugins which will be used when compiling code examples with Tut. The default is to use the `scalacPluginIvyDeps` for the module. + +* tutNameFilter - A `scala.util.matching.Regex` task which will be used to determine which files should be compiled with tut. The default pattern is as follows: `.*\.(md|markdown|txt|htm|html)`. + +* tutScalacOptions - The scalac options which will be used when compiling code examples with Tut. The default is to use the `scalacOptions` for the module but filtering out options which are problematic in the REPL, e.g. `-Xfatal-warnings`, `-Ywarn-unused-imports`. + +* tutVersion - The version of Tut to use. + +* tutIvyDeps - A task which determines how to fetch the Tut jar file and all of the dependencies required to compile documentation for the module and returns the resulting files. + +* tutPluginJars - A task which performs the dependency resolution for the scalac plugins to be used with Tut. + ### Twirl Twirl templates support. diff --git a/main/core/src/mill/util/JsonFormatters.scala b/main/core/src/mill/util/JsonFormatters.scala index f92941f7..2728d94d 100644 --- a/main/core/src/mill/util/JsonFormatters.scala +++ b/main/core/src/mill/util/JsonFormatters.scala @@ -3,6 +3,7 @@ package mill.util import ammonite.ops.{Bytes, Path} import upickle.Js import upickle.default.{ReadWriter => RW} +import scala.util.matching.Regex object JsonFormatters extends JsonFormatters trait JsonFormatters { implicit val pathReadWrite: RW[ammonite.ops.Path] = upickle.default.readwriter[String] @@ -11,6 +12,12 @@ trait JsonFormatters { Path(_) ) + implicit val regexReadWrite: RW[Regex] = upickle.default.readwriter[String] + .bimap[Regex]( + _.pattern.toString, + _.r + ) + implicit val bytesReadWrite: RW[Bytes] = upickle.default.readwriter[String] .bimap( o => javax.xml.bind.DatatypeConverter.printBase64Binary(o.array), -- cgit v1.2.3