Start external console application from Scala in interactive mode - scala

I am using scala.sys.process to start an external console application from within my Scala code. However, I hit a road block when the console app requires the user input.
Basically, when I start the console app with
Seq("powershell" , "myConsoleApp.exe").run
myConsoleApp.exe will not be started in its own "window". I can see the console app is running when I check the Task Manager. Without an actual window, I can't really key in anything.
I know Scala can return the program output to a String or a Stream[String] - I guess Scala will probably be able pipe input to the external process also.
But I really don't want to re-write such logic in Scala when all of them are already available in the external program.
I am wondering if there is a way to start an external console program in its own window? Or is this a shortcoming with scala.sys.process.
Thanks,

Adapted from this Java answer Show the CMD window with Java
import scala.sys.process._
Seq("cmd", "/c", "start", "PowerShell.exe", "myConsoleApp.exe") run

After some more googling, I found that my problem is more in the way I call powershell.
Here is a solution that works for me:
Seq("powershell", "Start-Process", "myConsoleApp.exe")

This will run interactively from Scala console, copy and :paste
val con = System.console
new java.lang.Thread() {
val in = new java.lang.Thread() {
override def run() {
while (true) {
Thread.sleep(1)
if (con.reader.ready)
con.reader.read()
}
}
}
override def run() {
in.start()
while (true) {
Thread.sleep(1000)
con.printf("\nHai")
}
}
}.start()

Related

Store execution plan of Spark´s dataframe

I am currently trying to store the execution plan of a Spark´s dataframe into HDFS (through dataframe.explain(true) command)
The issue I am finding is that when I am using the explain(true) command, I am able to see the output by the command line and by the logs, however if I create a file (let´s say a .txt) with the content of the dataframe´s explain the file will appear empty.
I believe the issue relates to the configuration of Spark, but I am unable to
find any information about this in internet
(for those who want to see more about the plan execution of the dataframes using the explain function please refer to https://jaceklaskowski.gitbooks.io/mastering-apache-spark/spark-sql-dataset-operators.html#explain)
if I create a file (let´s say a .txt) with the content of the dataframe´s explain
How exactly did you try to achieve this?
explain writes its result to console, using println, and returns Unit, as can be seen in Dataset.scala:
def explain(extended: Boolean): Unit = {
val explain = ExplainCommand(queryExecution.logical, extended = extended)
sparkSession.sessionState.executePlan(explain).executedPlan.executeCollect().foreach {
// scalastyle:off println
r => println(r.getString(0))
// scalastyle:on println
}
}
So, unless you redirect the console output to write to your file (along with anything else printed to the console...), you won't be able to write explain's output to file.
The best way I have found is to redirect the output to a file when you run the job. I have used the following command :
spark-shell --master yarn -i test.scala > getlogs.log
my scala file has the following simple commands :
val df = sqlContext.sql("SELECT COUNT(*) FROM testtable")
df.explain(true)
exit()

SBT & Scala AudioSystem

I have a strange problem that I've been trying to figure out for a while now.
I have an application that I am building with Scala & Spray and which uses the AudioSystem API.
I build and test the application using SBT.
I have a boot.scala which extends "App".
If I place the following code in boot.scala and run it through Eclipse(without sbt) (Run As... Scala App) it runs fine...
val stream:AudioInputStream = AudioSystem.getAudioInputStream(new File("test.wav"))
val audioFormat:AudioFormat = stream.getFormat();
val samplingRate = audioFormat.getSampleRate()
println("Sampling Rate: "+samplingRate)
The sampling rate of the file is output as expected.
I have the same code in a Specs2 Route test similar to...
"API" should {
"Respond to POST requests" in {
val stream:AudioInputStream = AudioSystem.getAudioInputStream(new File("test.wav"))
val audioFormat:AudioFormat = stream.getFormat();
val samplingRate = audioFormat.getSampleRate()
println("Sampling Rate: "+samplingRate)
...
However when I execute this from a terminal using "sbt test" I get the following error...
UnsupportedAudioFileException: : could not get audio input stream from input file
I know the file (test.wav) is ok as I can play it and executing the code through Eclipse works fine. The terminal (and its encodings) seem ok too as I put together a test file which just runs the same few lines of code and ran it from a terminal successfully.
The problem seems to only occur with SBT!
Anyone got any ideas?
Thanks
Finally found the answer after literally days of searching...
Why does AudioSystem.getMixerInfo() return different results under sbt vs Scala?
"This is a classloader issue. javax.sound does NOT like having the context classloader be anything other than the system classloader." and the fix for me was...
val cl = classOf[javax.sound.sampled.AudioSystem].getClassLoader
val old = Thread.currentThread.getContextClassLoader
var audioFormat:AudioFormat = null
try {
Thread.currentThread.setContextClassLoader(cl)
val stream:AudioInputStream =
AudioSystem.getAudioInputStream(new ByteArrayInputStream(data))
audioFormat = stream.getFormat()
} finally Thread.currentThread.setContextClassLoader(old)
Thanks

Getting STDIN in eclipse?

I need to write a code for competition using STDIN and STDOUT, how can I set up eclipse to take input from STDIN??
When I was just using editor and command line I was running:
java Hatch < hatch_input
Now I need the equivalent to work directly from eclipse. It would be perfect if I could use it directly from file, but it would to suffice to just be able to paste the actual input somewhere, as long as I can write code that takes STDIN directly in eclipse by clicking RUN.
class Main{
public static void main (String[] args) throws java.lang.Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
}
}
Above code is what I am trying to achieve.
When you run your program you can setup a run configuration. Just click on on the arrow next to the play button and choose "Run configurations..."
In the new run configuration dialog you create a new Java application run configuration. In the tab "Arguments" you can enter the arguments you want the program to receive.
Suggestion: In the last tab, "common", choose to save it as a shared file, this will create a *.launch file that you can use to quickly run the program. You can also create different launch files for different inputs.
You can also just type in the input data or copy paste in the console window of the eclipse. for Sdtin when the program hits that point focus shifts to console and waits for the response.
There is following code,which i tried. this code is working fine if you run program in command prompt, but in eclipse not working because there console are no longer waiting for user input and give the java.lang.NullPointerException.
if you are read data by user input you can use System.in.read(). and this is also working in eclipse console.
In this code you can get Data from user but this data is not args which we throw at run time...
public class CONSOLE
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Console c = System.console();
System.out.println("Enter Username : \t");
String u = c.readLine();
System.out.println("Enter Password : \t");
char[] p = c.readPassword();
System.out.println("USERNAME : "+u);
System.out.println("PASSWORD : "+String.valueOf(p));
}
}
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();

playframework 2 module and logs to output

I'v followed this tutorial
to make Scala Plaframework application work with depending module that has 'println' message in it.
So,
myApp depends on myModule, in myMyModule' controller I have:
object MyLogger {
def log(message: String) {
Console.println("something" + message)
}
}
In myApp I have:
object Application extends Controller {
def index = Action {
MyLogger.log("Here's my log message");
Ok(views.html.index("Your new application is ready."))
}
}
I go to localhost:9000, and I'm expecting 'Here's my log message' to be in my output, but there is no any, except:
[info] play - Listening for HTTP on port 9000...
(Server started, use Ctrl+D to stop and go back to the console...)
I' have checked:
cd myApp;
play dependencies (myApp it really depends on myModule, so it should work)
--
After some investigation I found that until I delete dependency to myDev, this message 'this is an info' in MyApp index controller was not showed as well. And then, when I delete that dependency, the application stars reacting to my changes again:
def index = Action {
play.api.Logger.info("this is an info")
Ok(views.html.index("Your new application is ready!"))
}
So, maybe I defined my module using wrong way. Should I change the structure of the myModule? or it is possible to leave it like a default project structure? I will check it later. I guess the reason is with 'routes' file wich I leave in my MyModule.
Why won't you use play.api.Logger ?
It allows you to log to the different levels - depending on your application.conf and app mode settings:
def index = Action {
play.api.Logger.info("this is an info")
play.api.Logger.debug("and debug is also possible")
play.api.Logger.error("...and error")
play.api.Logger.warn("or even warn")
Ok(views.html.index("Your new application is ready."))
}
dev mode displays all levels by default and life will avoid displaying the debug
The reason why I had this problem, is because myModule was an application, but not a module. I had to:
delete 'routes' file
clean up 'application.conf' file
delete 'views' folder
Then I can call this a module, but not application.
I guess it woud be better If play has something like this: play newModule. Maybe it has?
(So, I just missed this part about 'routes', that actually was described in the tutorial above. Too lazy to read.. :(. Play framework 1.x works similar to that, regarding the modules. )

How to detect key presses on console?

I'm writing a roguelike in Scala. I need to be able to see when the user presses an arrow key for example. All of the solutions I have found require the player to press enter.
Is there any way to detect keypresses in a console app in a similar manner to getch() in C?
The problem with Enter is that terminal buffers input, so you need to turn it to raw mode. Note that it is a platform-specific issue, so it is not very portable.
Look at answers to this question: How to read a single char from the console in Java (as the user types it)?
Short answer for UNIX systems:
import sys.process._
(Seq("sh", "-c", "stty -icanon min 1 < /dev/tty") !)
(Seq("sh", "-c", "stty -echo < /dev/tty") !)
(1 to 20).foreach { _ =>
val c = Console.in.read
println("Got " + c)
}
Scala includes jline in its distribution (with slightly modified packaging), since it uses it in the REPL. It's not normally loaded, but if you know where your Scala lib directory is, you can add it to the classpath. If you add it to the classpath, then this will work:
object Key extends App {
val con = new tools.jline.console.ConsoleReader()
println( con.readVirtualKey() )
}
(note that this method will give ^P ^N ^B ^F for up, down, left, and right, respectively, matching the standard control keys). But this will also override the standard behavior of System.in.read(), so you can pass it arrays of length 1 to get the next waiting byte (and test for waiting bytes with System.in.available, which should be more than 1 for arrow keys).
I must be missing something:
System.in.read
Works for me.
Scala sits on top of the JVM, so the answer for Scala is exactly the same as the answer for Java.
Unfortunately, I don't think you're going to like it - see this other answer for details.
I used the version 3 of jline. It doesn't work inside the IntelliJ IDE, but perfectly in SBT in the terminal of my Macbook.
build.sbt
libraryDependencies += "org.jline" % "jline" % "3.1.3"
This is an example app, which will stop on pressing the key 'enter'.
Main.scala
import org.jline.terminal.TerminalBuilder
object Main extends App {
val terminal = TerminalBuilder.builder().jna(true).system(true).build()
terminal.enterRawMode()
val reader = terminal.reader()
var input = -1
while (input != 13) {
input = reader.read
input match {
case 'a' =>
println("you pressed 'a'")
case unknown =>
println(s"you pressed a unknown key $unknown")
}
}
}
terminal.close()
reader.close()
That should work.