What
This is a blog post about sbt plugin to query search.maven.org
tl;dr
Why
Most development tasks can be done without leaving your favorite editor/ide nor console. Writing Scala code is no different: sbt gives you a lot of power to run code and tests, to package and publish application.
There is one small thing though, forcing you to leave that environment and go to a browser - to find the exact name of dependency for your project. Unless you have super memo powers you will probably have to check the group id for akka, or latest version for any other package that you would like to include in your project.
To make it even simpler, I created sbt-search-maven-plugin. Just type searchMaven something
and everything is clear. This prints the same results as search.maven.org
without leaving sbt.
Plugin development
In order to make this happen I had to get some knowledge on how to write a sbt plugin. There are three great sources you can check:
These are all great, but I wanted to create plugin that gets some user input from sbt shell, which is not covered in these references.
Input plugin
Plugin code is similar as in above examples, but main “entry” point for your code is different, as we need InputKey. There are some important places to look at:
build.sbt
The most important part for developing a plugin is
sbtPlugin := true
The whole build.sbt for this plugin.
extends AutoPlugin
The entry point for your code should be placed in an object that extends sbt.AutoPlugin
. This in turn should have another object defined: autoImport
with definition of task.
object autoImport {
lazy val searchMaven = InputKey[Unit]("searchMaven", "Search maven")
}
Input key makes it possible to get input provided by user from sbt shell. To write some implementation we need one more thing:
override lazy val projectSettings = Seq(
searchMaven := search(complete.DefaultParsers.spaceDelimited("<arg>").parsed, streams.value.log)
)
search
from snippet above is a regular Scala function in which we can finally implement our new feature.
sbt.Keys._
contain a lot of useful things that we can use in our code, like scalaVersion
defined in one’s project or streams.value.log
, which we use in our plugin to print results to user.
The whole file can be found here
Additional sbt settings
There are two things that should be mentioned here.
To make your plugin be enabled by default you should add such override:
override def trigger = allRequirements
requires
(it’s empty by default)
This plugin doesn’t interact with code in project - it just searches for artifacts - so we don’t want our code to be run multiple times when it’s executed inside multimodule project. To avoid this, the additional setting has to be specified:
aggregate in searchMaven := false
for testing
If you use version without SNAPSHOT
suffix and you don’t want to get warnings about deprecation during packaging your plugin, just add isSnapshot := true
to your build.sbt
.
Testing sbt plugin
unit tests
Nothing fancy here, just simple unit test for code that’s not related to sbt.
scripted
Scripted is the default mechanism for testing sbt plugins by writing scripts for sbt. Search maven is not building anything,
so we can just prepare basic script to check whether searchMaven
command is available and executable with a success.
A special directory structure has to be used. Tests are placed in sbt-test
in src
. Under that directory another two directories have to be created for test group and test itself. The full path looks like this:
<projectHome>/src/sbt-test/<testGroup>/<testName>
In such a path test should be described as:
plugins.sbt
inside of the project dir that adds plugin to the test projecttest
file that contains script (test scenario)build.sbt
file that describes the test build and an assertions for test. Assertions are written in form of the sbt tasks.
Compare the usage-help-test
Make it available for everyone
The best description can be found here. The screenshots are a bit outdated, but most of the content is still valid.
build.sbt can stay simple.
Contribution
You can pick a feature from the future work section in readme, implement issue with feature proposal (if any) or fix some bugs. Pull requests are very welcome!
Summary
This blog describes how to write a simple sbt plugin, test it and publish it.