Strange issue with SBT, println, and scala console application - scala

When I run my scala code (I'm using SBT), the prompt is displayed after I enter some text as shown here:
C:\... > sbt run
[info] Loading project definition [...]
[info] Set current project to [...]
Running com[...]
test
>>
exit
>> >> >> >> >> >> [success] Total time[...]
It seems like it's stacking up the print() statements and only displaying them when it runs a different command.
If I use println() it works as it should (except that I don't want a newline)
The code:
...
def main(args:Array[String]) {
var endSession:Boolean = false
var cmd = ""
def acceptInput:Any = {
print(">> ")
cmd = Console.readLine
if (cmd != "exit") {
if (cmd != "") runCommand(cmd)
acceptInput
}
}
acceptInput
}
...
What's going on here?

Output from print (and println) can be buffered. Scala sends output through java.io.PrintStream, which suggests that it will only auto-flush on newline, and then only if you ask. It might be OS dependent, though, since my print appears immediately.
If you add Console.out.flush after each print, you'll empty out the buffer to the screen (on any OS).

Related

Scala / Special character handling / How to turn m�dchen to mädchen?

I've got a Scala Akka App where I execute python scripts inside Futures with ProcessBuilder.
Unfortunately are special character not displayed correct, so do I get instead of mädchen-> m�dchen
(äöü -> �)
If I execute the python script via command line do I get the right output of "mädchen", so I assume it has nothing to do with the python script instead somehow related to my Scala input read.
Python Spider:
print("mädchen")
Scala:
val proc = Process("scrapy runspider spider.py")
var output : String = ""
val exitValue = proc ! ProcessLogger (
(out) => if( out.trim.length > 0 )
output += out.trim,
(err) =>
System.err.printf("e:%s\n",err)
)
println(exitValue) // 0 -> succ.
println(output) // m�dchen -> should be mädchen
I already tried many thinks and also read that Strings are by default UTF-8 so I am not sure why I get those question marks.
Also did I tried with no success:
var byteBuffer : ByteBuffer = StandardCharsets.UTF_8.encode(output.toString())
val str = new String(output.toString().getBytes(), "UTF-8")
Update:
It seems to be a windows related issue, following instruction will solve this problem: Using UTF-8 Encoding (CHCP 65001) in Command Prompt / Windows Powershell (Windows 10)

Debugging SCollection contents when running tests

Is there any way to view the contents of an SCollection when running a unit test (PipelineSpec)?
When running something in production on many machines there would be no way to see the entire collection in one machine, but I wonder is there a way to view the contents of an SCollection (for example when running a unit test in debug mode in intellij).
If you want to print debug statements to the console then you can use the debug method which is part of SCollections. A sample code shown below
val stdOutMock = new MockedPrintStream
Console.withOut(stdOutMock) {
runWithContext { sc =>
val r = sc.parallelize(1 to 3).debug(prefix = "===")
r should containInAnyOrder(Seq(1, 2, 3))
}
}
stdOutMock.message.filterNot(_ == "\n") should contain theSameElementsAs
Seq("===1", "===2", "===3")

Shell like application using sbt console

I would like to deploy some scala code, to be used very similar to sbt console
(command line interface, history, etc)
and would like to
customize it
and made it simple to deploy.
Can sbt console be used with these changes:
Removed startup info messages
Removed scala welcome message
Customized command prompt instead of "scala>" to be "myApp>"
No access to local nor global ivy/maven repositories (all jars
available, including sbt jars and dependencies)
Anybody passed this path ?
I have tried
Using sbt to build command line application
but with no much progress so far
(I guessed it was intented to very similar situation)
Are there ready made plugin available ?
Any other tool related or unrelated to sbt ?
Thank you
Actully, no need for sbt. To have it tweaked, scala code should be changed.
For the sbt "Customized command prompt" part, you have a good example with "sbt: Customize the Shell prompt in sbt" from Patrick Bailey (patmandenver).
create the ~/.sbt/0.13/global.sbt file:
vi ~/.sbt/0.13/global.sbt
And place the following in it.
shellPrompt := { state =>
def textColor(color: Int) = { s"\033[38;5;${color}m" }
def backgroundColor(color:Int) = { s"\033[48;5;${color}m" }
def reset = { s"\033[0m" }
def formatText(str: String)(txtColor: Int, backColor: Int) = {
s"${textColor(txtColor)}${backgroundColor(backColor)}${str}${reset}"
}
val red = 1
val green = 2
val yellow = 11
val white = 15
val black = 16
val orange = 166
formatText(s"[${name.value}]")(white, orange) +
"\n " +
formatText("\u276f")(green, black) +
formatText("\u276f")(yellow, black) +
formatText("\u276f ")(red, black)
}
Run reload in sbt and….
That can be amended/enhanced/completed to add other information you would need in your case.

Launch specific external process in Scala

I've been struggling to launch a specific external process in Scala. It works for most programs, but when I try
Array("gnome-terminal", "--working-directory",
"/mydir", "-x", "bash", "-c", "tmux attach")
it fails. I tried the same using Python's subprocess.Popen and it worked perfectly. Any suggestion?
My code is:
object Test {
def main(args: Array[String]):Unit = {
val source = Source.fromFile("file.txt")
val lines = source.getLines
lines.toList.map(raw => {
val programAndOptions = raw.split('$')
// here I get the Array mentioned above
Process(programAndOptions) run
})
source.close
}
}
Update
My file.txt is something like this:
evince$/path/to/my/pdf
evince$/path/to/other/pdf
nautilus$/path/to/my/working/directory
gnome-terminal$--working-directory$/mydir$-x$bash$-c$tmux attach
Update2
I ran the same code again to test and try some other things and it worked 'as is'.
'Run' is non blocking so it execute the program and continue with the code, which is this case is source.close and exit. Exiting the jvm probably kill the app.
Try using the '!' function instead of 'run' or do something like:
val p = Process(programAndOptions) run
p.exitValue

What do files deleted by groovy leave behind in Windows 7?

I have a groovy script that saves multiple files from a remote directory to my temp directory and parses them into xml. It has an interesting bug. Each time it runs, it can't find one file in my temp directory. The next time it runs, it finds that file, but can't find a new file. If I have 20 files, it won't find all 20 files until the 20th run. The temp directory is cleared after each run. I'm wondering if there are other artifacts the program is leaving behind?
If I clean the project after 16 runs, it still finds the first 16 files. So it seems it's not an artifact in eclipse.
This is running in Eclipse 3, Java 1.5, Windows 7, Groovy 1.0.
remoteftpFile.findAll {
println "in find"
ftp.getReply();
it.isFile()
}.each {
println "in each"
ftp.getReply();
println it
ftp.getReply();
def tempDestination=PropertiesUtil.getTempDir()
def procDestination=PropertiesUtil.getProcessedDir()
def tempFile = new File(tempDestination+ it.name )
def procFile = new File(procDestination+ it.name )
//set it to delete
ftp.getReply();
println "got tempfile"
def localftpFile = ftp.SaveToDisk(it,tempFile) //Save each file to disk
//************** Handles decryption via gpgexe
println "Decrypting file";
println localftpFile.toString();
def localftpFileStr=localftpFile.toString();
def processedftpFileStr=procFile.toString();
def gpgstring=PropertiesUtil.getGpgString();
def decryptedOutputName = localftpFileStr.substring(0, (localftpFileStr.length()-4));
def decryptedProcOutputName= processedftpFileStr.substring(0, (processedftpFileStr.length()-4));
def decryptedOutputXMLName = decryptedOutputName.substring(0, (decryptedOutputName.length()-4))+".xml";
def decryptedProcOutputXMLName = decryptedProcOutputName.substring(0, (decryptedProcOutputName.length()-4))+".xml";
println decryptedOutputName;
def xmlfile = new File(decryptedOutputName)
def cdmpXmlFile = new File(decryptedOutputXMLName)
def procCdmpXmlFile = decryptedProcOutputXMLName
println gpgstring + " --output ${decryptedOutputName} --decrypt ${localftpFile} "
(new ExternalExecute()).run(gpgstring +" --output ${decryptedOutputName} --decrypt ${localftpFile} ");
Thread.sleep(1000);
//************* Now Parse CSV file(s) into xml using stack overflow solution
println "parsing file"
def reader = new FileReader(xmlfile)
def writer = new FileWriter(cdmpXmlFile)
def csvdata = []
xmlfile.eachLine { line ->
if (line){
csvdata << line.split(',')
}
}
def headers = csvdata[0]
def dataRows = csvdata[1..-1]
def xml = new groovy.xml.MarkupBuilder(writer)
// write 'root' element
xml.root {
dataRows.eachWithIndex { dataRow, index ->
// write 'entry' element with 'id' attribute
entry(id:index+1) {
headers.eachWithIndex { heading, i ->
// write each heading with associated content
"${heading}"(dataRow[i])
}
}
}
}
println "Performing XSL Translation on ${cdmpXmlFile}"
def cdmpXML = new XMLTransformer(xmlTranslate).run(cdmpXmlFile) //Run it on each of the xml files and set the output
new File("C:\\temp\\temp.xml").write(cdmpXML)
new File(procCdmpXmlFile).write(cdmpXML)
println "Done Performing XSL Translation"
println "Uploading Data to CDMP"
def cdmpUp = new UpdateCDMP(updateDB)
cdmpUp.run(cdmpXML)
println "Finished Upload and Import"
//do clean-up backing it up AND removing the files
println "Finished"
println "Closing Buffers"
reader.close();
writer.close();
println "Deleting Local Files"
new File(decryptedOutputName).deleteOnExit();
new File(localftpFile).deleteOnExit();
xmlfile.deleteOnExit();
cdmpXmlFile.deleteOnExit();
println "Deleting " + cdmpXmlFile.getName()
new File("C:\\temp\\temp.xml").deleteOnExit();
}
ftp.close()
}
This is because you are using deleteOnExit, which is not guaranteed to delete a file. It only deletes if:
the files are closed correctly,
the JVM exits correctly (with no exceptions), and
a System.exit() was called with 0 argument (or the VM terminated naturally).
It's especially problematic on Windows OSes. I can't point to a specific Stack Overflow question about this, but most questions involving deleteOnExit discuss this issue.
If you actually want to delete a file, then you should always use aFile.delete() directly. There is really no good reason to delay the deletion until later in your example.