*decided to start a bounty & edited out information not needed
I would like to run a script inside the SBT console that would run an SBT command at the end. How can this be done
I wrote a script that allows me to execute shell commands. Typing in sbt
then path/to/my-script start
gives me this error: /bin/sh: start command not found
But path/to/my-script sbt start
works fine
Reason why sbt plugins (such as these) or a custom task won't work in this case:
quick edit
*I would prefer to execute start
from a script instead of using custom task/command to run my script
I'll explain step by step what I'd like to do (what I'm doing may sound silly to you but please read my response to Etan):
Type sbt in my console which will invoke the SBT console
Instead of typing start
, I'd like to run a script which will perform something else that doesn't directly have anything to do with the project and then invoke start
for me when it's done.
Being not too familiar with scripting, script can invoke #!/bin/sh
commands, so I guess what I'm trying to do is invoke a #!/bin/sh/<*this-sbt-console*>
command if that's possible
Even a workaround like if I can get the script to just print start
on the terminal and invoke the enter/return
key after it's done, would suffice
other info:
sbt shell has a command prompt (with tab completion and history!). To compile again, press up arrow and then enter. To run your program, type run . To leave sbt shell, type exit or use Ctrl+D (Unix) or Ctrl+Z (Windows).
In order to be able to execute a script and, after that script completes, proceed to execute another sbt command, one approach is to implement a custom sbt command which does the following:
This is demonstrated in this Build.scala
file:
import sbt._
import Keys._
// imports standard command parsing functionality
import complete.DefaultParsers._
object CommandExample extends Build {
// Declare a project, adding new commands.
lazy override val projects = Seq(root)
lazy val root = Project("root", file(".")) settings(
commands ++= Seq(start, customStart)
)
// A fake "start" command.
def start = Command.command("start") { state =>
println("Fake start command executed.")
state
}
// A command that executes an external command before executing the "start" command.
// The name of the external command is the first parameter.
// Any additional parameters are passed along to the external command.
def customStart = Command.args("customStart", "<name>") { (state, args) =>
if (args.length > 0) {
val externalCommand = args.mkString(" ")
println(s"Executing '$externalCommand'")
externalCommand !
}
"start" :: state
}
}
This is a sample execution:
$ sbt
[info] Loading project definition from /home/fernando/work/github/fernandoacorreia/so24565469/project
[info] Set current project to hello (in build file:/home/fernando/work/github/fernandoacorreia/so24565469/)
> customStart ls -la
Executing 'ls -la'
total 40
drwxr-xr-x 6 fernando fernando 4096 Jul 8 10:52 .
drwxr-xr-x 27 fernando fernando 4096 Jul 8 08:51 ..
-rw-r--r-- 1 fernando fernando 95 Jul 8 10:47 build.sbt
drwxr-xr-x 8 fernando fernando 4096 Jul 8 08:58 .git
-rw-r--r-- 1 fernando fernando 203 Jul 8 09:04 .gitignore
-rw-r--r-- 1 fernando fernando 1082 Jul 8 08:51 LICENSE
drwxr-xr-x 3 fernando fernando 4096 Jul 8 10:51 project
-rw-r--r-- 1 fernando fernando 111 Jul 8 08:51 README.md
drwxr-xr-x 3 fernando fernando 4096 Jul 8 08:57 src
drwxr-xr-x 2 fernando fernando 4096 Jul 8 10:52 target
Fake start command executed.
>
The external command passed as a parameter to customStart
may be any executable command, e.g. a binary file or a shell script.
To learn more about creating commands, refer to the Commands documentation page.
To learn more about executing external processes, refer to the External Processes documentation page.
The complete example is available for download at this GitHub repository.
Since sbt executes the script (as a child process), that script can't execute commands on the original (parent) sbt process.
It would be possible to capture the script's output, either to stdout
or to a file, and have the sbt command execute an arbitrary command generated by the script, but that's somewhat convoluted.
Another approach would be to invert the order of execution. Instead of having sbt
execut the script, the script would be executed first, directly from the shell, and the script would execute the sbt command.
For instance, this script:
#!/bin/bash
echo "Running custom script"
# Insert commands here
sbt start
Produces this output:
$ ./script
Running custom script
[info] Loading project definition from /home/fernando/work/github/fernandoacorreia/so24565469/project
[info] Set current project to hello (in build file:/home/fernando/work/github/fernandoacorreia/so24565469/)
Fake start command executed.
As you say "Is there a way to just tell a script to write something onto the terminal and press return/enter?"
yes - the slightly hacky but highly effective solution is a little program called expect.
http://www.thegeekstuff.com/2010/10/expect-examples/
http://www.admin-magazine.com/Articles/Automating-with-Expect-Scripts
It will let you do anything you can do from the keyboard, but automatically. It's like a macro playback engine for the UNIX command prompt.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With