SBT provide help for custom commands - command

How do you provide help for custom commands in sbt?
I want to display said help in case the args I have set are wrong (like putting a string in a number arg)
I also want to display the help if help <myCommand> is typed.
Any clues? The documentation doesn't say anything about it:
http://www.scala-sbt.org/0.12.4/docs/Extending/Commands.html
And google doesn't help either.
Thanks.

According to the documentation, help should work on Commands. But you need to define your Command correctly using one of the methods in Command.scala, e.g.
commands += Command.command("foo", "bar", "baz")(...)
then
> foo<TAB>
bar
> help foo
baz
For the benefit of anybody wanting to do the same for Task, here's an answer...
The help input task is what you want users to type, e.g.
> help compile
Compiles sources.
and to provide the documentation string, you provide it when you define the key to your Task. e.g.
val compile = TaskKey[CompileAnalysis]("compile", "Compiles sources.", APlusTask)
Later on you assign the key to the implementation of the Task, like so
compile <<= compileTask
or using the new macro based API (which I detest)
compile := { println("hello world") ; compile.value }
Lots of examples in
https://github.com/sbt/sbt/blob/1.0.x/main/src/main/scala/sbt/Keys.scala
https://github.com/sbt/sbt/blob/1.0.x/main/src/main/scala/sbt/Defaults.scala

Related

How to auto generate the with... type method in intellij

Is it possible to generate the with... type method with IntelliJ for Scala?
Example:
case class Person(name: String, age: Int)
I would like to find the tool to auto-generate the method of type:
def withName(name: String): Person = this.copy(name=name)
def withAge(age: Int): Person = this.copy(age=age)
is it possible?
Thank you.
There is no such thing out-of-the-box, but you can create a scala template of your own:
Select Settings/Preferences | Editor | Live Templates.
From options on the right, open the list of Scala templates.
Click + to add a new template.
You can see an example here
I you want to auto-generate these methods rather than writing them explicitly (even with an IntelliJ template), you can do that with an annotation macro that will run at compile-time.
In particular, you can check the scalameta project for informations about this. Note however that macros are an experimental feature that is likely to change in trivial ways when Scala 3 is released. In my opinion, you should think hard about whether writing withName(name) rather than copy(name=name) is worth the trouble of defining all these methods (whether its manually, through IntelliJ snippets, or using macros), and only go for macros if it will save you a lot of trouble down the line.

How does := function work in sbt?

I'm trying to understand in depth some concepts about sbt. At this time I'm trying to understand how the Settings Key Map works. I've seen this and now I want to understand how the settingAssignMacroImpl works, based on the signature of the := function.
I see that there's a macro but I don't quite understand how the macro expansion works there, so therefore I can't understand how the function assigns the value to the Map. I appreciate any light that you can shed on this.
EDIT: As noted by Sarvesh Kumar Singh, my question is about how the macro expands for updating the map, because i see something like this:
def settingMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(t: c.Expr[T]): c.Expr[Initialize[T]] =
Instance.contImpl[T, Id](c, InitializeInstance, InitializeConvert, MixedBuilder)(Left(t), Instance.idTransform[c.type])
But i can't quite understand the expansion process there.

How to force recompilation of classes that call macros?

I have some code that depends on a macro call. In my case the macro-code iterates over fields of a type T and returns their name recursively:
object Foo{
val bar:List[String] = MyMacroClass.fieldNames[Bar]
}
The Bar and MyMacro each are defined in separate independent sub-projects.
Now when I do changes to Bar, like adding or removing fields, the list will not reflect the changes if I don't manually clean and recompile.
Is there a way to tell sbt to recompile such cases?
ps. similar questions were asked here and here.
You can use dependsOn in MyMacro to force it to recompile each time Bar is changed. Something like lazy val MyMacroProject = project.dependsOn(BarProject).

Alternative to Scala REPL breakIf in 2.10

I was reading here about using the breakIf method in the REPL code for interactive debugging, but then I found this post saying that break and breakIf were removed from ILoop in Scala 2.10. Unfortunately, that post doesn't explain why the code was removed.
I'm assuming that these functions were removed because there's a better way of doing this. If that's the case, could someone please enlighten me?
Perhaps the idea is that you should just work with the ILoop directly? As far as I can tell, it shouldn't be much more complex than:
// insert the code below wherever you want a REPL
val repl = new ILoop
repl.settings = new Settings
repl.in = SimpleReader()
repl.createInterpreter()
// bind any local variables that you want to have access to
repl.intp.bind("i", "Int", i)
repl.intp.bind("e", "Exception", e)
// start the interpreter and then close it after you :quit
repl.loop()
repl.closeInterpreter()
Compared to the old breakIf API, this approach gets rid of an additional level of indirection for both the if condition (which was wrapped into a => Boolean) and the DebugParam/NamedParam (which were temporary wrappers used only to fill in the bind arguments).
This approach also allows you to specify your Settings as needed. For example, some REPL bugs can be worked around with -Yrepl-sync but break gave you no way of specifying that.

Where is subsetOf in scala collections?

I'm at a loss on this one...
Looking at a Set in Scala collections, I see that there is a method called subsetOf. But when I try to find where it is in the actual .scala source code (I've looked in Set.scala, GenSet.scala, SetLike.scala etc...) I can't find it!!!
Which trait actually defines that method? Or am I missing something?
If you click on function in scaladoc, you may see where is it defined:
The scala API specifies:
Definition Classes: GenSetLike
When you're looking at the API page, click the method entry to expand it. You'll see more information, including the "Definition Classes".
If you look at the source for GenSetLike.scala, you'll see it:
def subsetOf(that: GenSet[A]): Boolean = this forall that