SBT Command that Calls Another Command and an InputTask - scala

I am writing an SBT Command that is supposed to call another command (eclipse from the Eclipse SBT Plugin) and another InputTask.
How can one achieve this?

Assuming that you want to create a "release" command and it needs to call another task named "pack", you can add the following code to build.sbt:
commands += Command.command("release")((state:State) => {
Project.evaluateTask(pack, state)
println("release called")
state
})
Updated:
In addition, if you have to create the "release" command and it requires calling another command named "init_compile", then the following sample code can be used:
commands += Command.command("init_compile")((state:State) => {
println("init_compile called.")
state
})
commands += Command.command("release")((state:State) => {
val newState = Command.process("init_compile",state)
println("release called.")
newState
})

Related

How to call an InputKey from within a Task in an SBT Plugin

I am trying to make a task execute several inputKey.
myTask := Def.taskDyn {
val outputOfMyInputKey = myInputKey.[WHAT SHOULD I DO HERE].value
Def.task {
// do something with outputOfMyInputKey
}
}
Anybody knows how to call inputKey with default parameters ?
I tried parsed , evaluated, value, inputTaskValue but none of them works.
Thanks.
Take a look at this section of the sbt docs: Get a Task from an InputTask. You can use .toTask to provide input for your input task:
myInputKey.toTask("").value
Notice that if you provide a non-empty input, it should start with a space:
myInputKey.toTask(" arg1 arg2").value

How do I get args passed to this scala object?

I'm trying to figure out how to pass args to this scala object:
I have this class written in this sbt project path: allaboutscala/src/main/scala/gzip_practice/gzipwriter
package gzip_practice
import java.io._
import java.util.zip._
/** Gzcat
*/
object gzcat extends App {
private val buf = new Array[Byte](1024)
try {
for (path <- args) {
try {
var in = new GZIPInputStream(new FileInputStream(path))
var n = in.read(buf)
while (n >= 0) {
System.out.write(buf, 0, n)
n = in.read(buf)
}
}
catch {
case _:FileNotFoundException =>
System.err.printf("File Not Found: %s", path)
case _:SecurityException =>
System.err.printf("Permission Denied: %s", path)
}
}
}
finally {
System.out.flush
}
}
This is an sbt project called allaboutscala. I am trying to run it with:
scala src/main/scala/gzip_practice/gzipwriter.scala "hi" but the command just hangs and I don't know why.
How am I supposed to run this object constructor with args?
You can use the scala command as a script runner.
Normally, it will wrap your "script" code in a main method.
But if you have an object with a main method, like your App, it will use that for the entry point.
However, it doesn't like package statements in the script.
If you comment out your package statement, you can compile and run with:
scala -nc somefile.scala myarg.gz
-nc means "no compile daemon"; otherwise, it will start a second process to compile scripts, so that subsequent compiles go faster; but it is a brittle workflow and I don't recommend it.
I confirmed that your code works.
Usually, folks use sbt or an IDE to compile and package in a jar to run with scala myapp.jar.
An object is a static instance of a class. You could construct it using:
object gzcat(args: String*) extends App {
...
}
args is bound as a val within the object gzcat.
Are you trying to run it with repl? I would suggest running it with sbt, then you can run sbt projects from project root directory with command line parameter as follows:
sbt "run file1.txt file2.txt"
The quotes are required. If you leave sbt shell open, then it running it will be much faster. Open shell in project root with
sbt
In the sbt shell:
run file1.txt file2.txt
Within the sbt shell, no quotes.

How to invoke a Eclipse Clean-Up Profile programmatically?

Is there a way to invoke a specific Clean-Up profile (Source->Clean Up) programmatically?
I would like to invoke it on an iterable of ICompilationUnits.
I looked at the declarations in org.eclise.jdt.ui.
The relevant command ID is org.eclipse.jdt.ui.edit.text.java.clean.up and the implementation is org.eclipse.jdt.internal.ui.actions.AllCleanUpsAction. Unfortunately it is an internal action and the command does not support any parameters.
I can see three possible approaches:
create an AllCleanUpsAction and invoke ...run(new StructuredSelection(<compilation units>[])). Problem: the action is internal so you might want to create a fragment to access it...
open the package navigator view. Select the proper files corresponding to the compilation units. Execute the command ID via IHandlerService.executeCommand("org.eclipse.jdt.ui.edit.text.java.clean.up"). Problem: the package navigator is changed... and you might not have all compilation units in visible in the navigator.
set the current selection in your view to new StructuredSelection(<compilation units>[]). Then execute the command as above. Problem: I'm not sure the command is properly enabled..
You can use RefactoringExecutionStarter.startCleanupRefactoring which takes an array of ICompilationUnits to perform the clean up on as one of its parameters. This method also allows you to specify the ICleanUps that you want to perform and allows you to skip showing the clean up wizard if you want.
Here's an example which removes unnecessary parentheses:
ICleanUp[] cleanUps = new ICleanUp[]{new ExpressionsCleanUp(){
#Override
protected boolean isEnabled(String key){
switch(key){
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES:
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_NEVER:
return true;
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_ALWAYS:
return false;
default:
return super.isEnabled(key);
}
}
}};
ICompilationUnit[] icus = new ICompilationUnit[]{icu};
Shell shell = HandlerUtil.getActiveEditor(event).getSite().getShell();
try {
RefactoringExecutionStarter.startCleanupRefactoring(
icus, cleanUps, false, shell, false, ActionMessages.CleanUpAction_actionName);
} catch (InvocationTargetException e) {
throw new AssertionError(e);
}

SBT how to run InputTask

I am creating some custom tasks in my SBT project and need to call other tasks for that.
How can i call inputTasks from inside my tasks and support them some input?
Since you can factor your own tasks around this I'm assuming you're trying to use the run task. It took a bit of digging, but I've finally made it work; in a nutshell, this is what you do (assuming your task is named deployTask, tweak to match your needs):
deployTask <<= ( fullClasspath in Compile, runner ) map { ( classpath, runner ) =>
val logger = ConsoleLogger() // Not sure this is optimal
Run.executeTrapExit( {
Run.run( "com.sample.MainClass",
classpath map { _.data },
Seq( "option1", "option2", "..." ), // <-- Options go here
logger )( runner )
}, logger )
}
This doesn't invoke the InputTask directly (I haven't found a way to do that yet), but it at least lets you run arbitrary Java code.

Handling program args with Groovy Eclipse plugin v2

I am wondering how to handle program arguments when you are running Groovy within Eclipse. It isn't as straight forward as it is from the command line and I am having trouble figure it out. Im using Eclipse 3.5. My run configuration has these arguments all on one line:
--classpath "${workspace_loc:/GroovyProject};${workspace_loc:/GroovyProject}"
--main groovy.ui.GroovyMain "C:\Temp\Workspace\GroovyProject\GroovyTest.groovy "
argtest1
argtest2
argtest3
The script I am using to try to make this work looks like this:
// GroovyTest.groovy
class GroovyTest {
static main(args) {
println "hello, world"
for (arg in this.args ) {
println "Argument:" + arg;
}
}
}
The error I get is:
hello, world
Caught: groovy.lang.MissingPropertyException: No such property: args
for class: GroovyTest at GroovyTest.main(GroovyTest.groovy:5)
You have az unnecessary this in the for (arg in this.args) line.
this.args means that you have an instance of the GroovyTest object and you refer to its args field. In this case args is a method parameter so you have to refer to it simply as args.