Startup script for scala REPL - scala

What is the name of startup script for the scala REPL. For example something along the lines of the following:
~/.scalarc

You could try something like:
$ alias scala='scala -i ~/.scalarc '
Note the trailing spaceā€”if you omit it your alias will disregard parameters.
Further use of 'scala' (once the alias is defined) will work as expected for REPL. If you use the alias for launching compiled programs, '~/.scalarc' will simply be ignored.
edit: It seems using '-i' in this way causes a significant slowdown.
The following, though somewhat convoluted (warning: bashism ahead), works faster:
$ scala -i <( cat ~/.scalarc foo.scala)
This concatenates your code (e.g. 'foo.scala') with '.scalarc' and evaluates everything on startup, leaving you at the REPL.
I don't think it's a satisfactory solution, but worth mentioning.

Related

why scala puts the version on stderr instead

I have to do this:
scala -version 2>&1 | sed 's/.*version \([0-9]*\.[0-9]*\).*/\1/'
Instead of this:
scala -version | sed 's/.*version \([0-9]*\.[0-9]*\).*/\1/'
so I am wondering why does scala -version (sometimes maybe ...) put its result on stderr?
Actually, in Unix stderr is not used for errors only.
It's more like stdin and stdout are using for the default piping streams (cmd1 | cmd2 | cmd3) and sdterr is everything that the command creators thought that should not go into this default pipeline, and instead should be shown to the user who build it. It includes errors, but sometimes also information about progress, configuration, diagnostics, etc.
Let's see some example of that:
echo "2 + 2 * 2" | scala | grep "res"
This would treat scala as something that takes source as input and prints the results of evaluation on output. But it still prints some stuff on stderr, and when you run it you'll see
Type in expressions for evaluation. Or try :help.
Jul 08, 2022 9:32:44 AM org.jline.utils.Log logr
WARNING: Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
scala> val res0: Int = 6
On a first glance it is redundant but when you look closely it tells some interesting things like WARNING: Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information) which is nice to see as you are debugging your script, and not go into the stream where you are only expecting to see the results of the execution.
What would happen if you added -version after scala?
> echo "2 + 2 * 2" | scala -version | grep "res"
Scala code runner version 2.13.8 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.
Script still runs - it's shell so you can glue a lot of things together whether it makes sense or not, so it's expected. But this script doesn't do anything reasonable - there is no code processing output from scala -version and if version landed on stdin you'd see empty result, not knowing what happened. But since it landed on stderr you see what happened, and can fix the script.
And if you actually wanted to process scala -version output, it's just one 2>&1 away as you noticed.
There are also other things to consider like mentioned in comments: consistency with what java -version does, no promise to print such information to stdin. Also, it might have been made this way to be internally consistent: scala might use stdin for code input and stdout for code execution exclusively, and anything else is wired to some global logger printing on stderr. Finally, while there are some conventions what should and should not go into stderr, none of that is set in stone, so you should not come with predefined expectations. Authors will do what they find the most pragmatic.

Autoconf : How to get program output in a string and check if another string is present in that

I am developing a Qt application in Python. It uses a resource file, which needs to be compiled. I am using autotools to manage compilation and installation of my projects.
Now, in order for the resource file to be usable by the application, it needs to be compiled with a certain version of the compilation program (pyrcc). I can get the version by putting the output of pyrcc -version in a variable in configure.ac. But then, I don't know how to check whether the string pyrcc5 is present in the output. If it is not present, I want to tell the user that his PyRCC programm has the wrong version, and abort configure.
Additionally, I would like to avoid the need of an extra variable for the program output, but instead do it like this (Pseudo code):
if "pyrcc5" not in output of "pyrcc -version":
say "pyrcc has wrong version"
exit 1
How can I do this ?
When writing a configure.ac for Autoconf, always remember that you are basically writing a shell script. Autoconf provides a host of macros that afford you a lot of leverage, but you can usually at least get an idea about basic "How can I do X in Autoconf?" questions by asking instead "How would I do X in a portable shell script?"
In particular, for ...
I would like to avoid the need of an extra variable for the program
output, but instead do it like this (Pseudo code):
if "pyrcc5" not in output of "pyrcc -version":
say "pyrcc has wrong version"
exit 1
... the usual tool for a portable shell script to use for such a task is grep, and, happily, the easiest way to apply it to the task does not require an intermediate variable. For example, this implements exactly your pseudocode (without emitting any extraneous messaging to the console):
if ! pyrcc -version | grep pyrcc5 >/dev/null 2>/dev/null; then
echo "pyrcc has wrong version"
exit 1
fi
That pipes the output of pyrcc -version into grep, and relies on the fact that grep exits with a success status if and only if it finds any matches.
You could, in fact, put exactly that in your configure.ac, but it would be more idiomatic to
Use the usual Autoconf mechanisms to locate pyrcc and grep, and to use the versions discovered that way;
Use the Autoconf AS_IF macro to write the if construct, instead of writing it literally;
Use standard Autoconf mechanisms for emitting a "checking..." message and reporting on its result; and
Use the standard Autoconf mechanism for outputting a failure message and terminating.
Of course, all of that makes the above considerably more complex, but also more flexible and portable. It might look like this:
AC_ARG_VAR([PYRCC], [The name or full path of pyrcc. Version 5 is required.])
# ...
AC_PROG_GREP
AC_CHECK_PROGS([PYRCC], [pyrcc5 pyrcc], [])
AS_IF([test "x${PYRCC}" = x],
[AC_MSG_ERROR([Required program pyrcc was not found])])
# ...
AC_MSG_CHECKING([whether ${PYRCC} has an appropriate version])
AS_IF([! pyrcc -version | grep pyrcc5 >/dev/null 2>/dev/null], [
AC_MSG_RESULT([no])
AC_MSG_ERROR([pyrcc version 5 is required, but ${PYRCC} is a different version])
], [
AC_MSG_RESULT([yes])
])
In addition to portability and conventional Autoconf progress messaging, that also gets the builder a way to specify a particular pyrcc executable to configure (by setting variable PYRCC in its environment), documents that in configure's help text, and exports PYRCC as a make variable.
Oh, and I snuck in a check for pyrcc under the name pyrcc5, too, though I don't know whether that's useful in practice.
The final result no longer looks much like the shell script fragment I offered first, I grant. But again, the pure shell script fragment could be used as is, and also, the fully Autoconfiscated version is derived directly from the pure script.

cvs annotate and standard error redirection

First, some background. I'm trying to use cvs annotate within a Perl script invoked from a ksh command line to find out who's using bad hex constants in their source code and dole out justice appropriately. I'd like to use stdout for this program strictly for my own structured output, so I can pipe it to a file or to other programs. But, every call to cvs annotate results in a diagnostic message being printed to the console. It takes the form of:
Annotations for <filename>
***********
It's mucking up my stdout! I played around with annotate on the command line, and I figured that these diagnostic messages were coming from stderr, because running this command directly in ksh:
cvs annotate <filename> 1>yay.txt 2>boo.txt
correctly puts the desired annotated output into yay.txt and the diagnostics into boo.txt. However, things get weirder when I try to run this from within a perl script using backticks.
$muhstring = `cvs annotate $filename 2>boo.txt`;
The desired annotated output does appear in $muhstring, but the diagnostics still get printed to the command line, and boo.txt is created as an empty file. There's an admittedly old post on perlmonks.org that says this syntax should work as written. So, what's the deal? Is this a CVS quirk, have I misread the post, or have things changed since 1999? Or is it something else?
Edit: So, it is not, in fact, mucking up stdout. I tried this in ksh:
perl findbadhexowners.pl badhex.txt > out.txt
and the diagnostic messages still printed to the console, but out.txt only contains the annotations. This is fine for my purposes, and I can continue with other code.
That said, it seems like Perl and cvs specifically are interacting a little strangely, especially considering that redirection in ksh works fine and redirection in Perl for other commands like cd works fine - for example, in Perl
`cd nonexistentDir 1>stdout.txt 2>stderr.txt`;
gives the expected output in both stdout.txt and stderr.txt. It's only using cvs annotate from within Perl that produces this problem.

In IPython every shell command is run by prefixing it with "!" but few commands run without that, What is the reason behind it?

In case of "ls" command it runs with and without the prefix "!". In case of "cat fileName" it's the same, but when you consider "wc -l fileName" it works only with "!" prefix.
When you combine cat and wc command "cat fileName | wc -l" executed successfully without "!" prefix.
I don't understand the logic behind this prefix "!" in ipython.
Thank you in advance
(I am new to python programming, if it sounds silly question please forgive me.)
IPython tries to make interactive programming as comfortable as possible. Some shell builtins like ls, cd or cat are basic commands to navigate in unix shells. IPython, as a "Python Shell" provides the same functionally for convenience. Along with features like colored output, etc.
The !command is for executing arbitrary shell code and is much more powerful. It can be used to run any command you can type in a normal shell and can also catch its output.
Compare ls with !ls. The former will print the content in your current directory with nice coloring. The latter will print the same list, but just plain text.
But note that you can do really cool things with !command:
files = !ls
for f in files:
print("I like this file:", f)
Which reads the output of ls into a python array files which you can use in your code just like any other array.
To sum up: if you just want to navigate, you usually use the standard commands, if available. If you need to capture the output or run programs you have to use the !command syntax.

"scala" command terminates batch scripts

during my work here I collided with a somewhat peculiar problem. It's possible that there is a highly simple explanation for this behaviour, but to me it just doesn't make much sense.
Here's the situation:
I wrote a batch file "test.bat" that, right now, looks like this:
echo 1
scala myProgram
echo 2
When I open the command prompt in the according directory and run test.bat, it starts by echoing 1, then runs myProgram (which also has certain outputs that appear in the console, so the scala program myProgram works properly) - and then stops. 2 does not appear in the console and the console waits for me to input another command.
Why this behaviour? Is is a malfunction of the console? Or of the scala command? Or not a malfunction at all and it is actually meant to behave that way?
What I was actually trying to do is redirecting the output of "scala myProgram" to a file (which works well) and rename this file after the scala program has terminated, so my batch file originally looked somewhat like this:
scala myProgram > log.txt 2>&1
ren "log.txt" "log2.txt"
And I was confused about the fact that "log2.txt" was never created.
Your answers are greatly appreciated, thank you.
Adding -nc to scala command worked for me:
$ scala -nc /tmp/2.scala
Hello world
So I guess, the issue has something to do with the compilation daemon
-nc no compilation daemon: do not use the fsc offline compiler
Could you try that?