How to get .bashrc / .profile variables in Scala - scala

I am unable to get access to the environmental variables in either ~/.bashrc or ~/.profile from Scala. How do I access the environmental variables from a Scala Process? Also I am unable to update the paths like this:
Process("myProgram", None, "PATH"-> ".:/path/to/myProgram").!!
However this works:
Process("/path/to/myProgram",None).!!
Works fine. However, when myProgram depends on some environmental variables being set this doesnt work anymore.
How do I change the PATH variable from a Scala program?
And even better, how can I get Scala to access the environmental variables from .bashrc or .profile. Currently none of those are available.
Thanks for your time and help

How do I access the environmental variables from a Scala Process?
The util.Properties object offers 3 different methods for inspecting the environmental variables that the Scala process/program has inherited. Here's an example:
util.Properties.envOrNone("LC_COLLATE")
//res0: Option[String] = Some(POSIX)
How do I change the PATH variable from a Scala program?
A running process is not allowed to alter its own environment, but it can launch a new process with a modified environment. There are a couple different ways to go about this.
One is to launch the shell of your choice and use shell syntax to make the modifications before invoking the target command.
import sys.process._
Seq("sh", "-c", "PATH=$PATH:$HOME/Progs myProg").!!
// a single arg:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Or you can supply the environment mods as an argument to one of the many overloaded Process.apply() methods.
import scala.sys.process._
Process("./myProg"
,new java.io.File("/full/path/to")
,"PATH"->s"${Properties.envOrElse("PATH",".")}:/full/path/to"
).!!
...can I get Scala to access the environmental variables from .bashrc or .profile?
If your Scala program is launched from a shell with the proper environment then every process launched from your program should inherit the same. If, for whatever reason, your program has not inherited a fully equipped environment then the easiest thing to do is to launch a fully equipped shell to launch the target command.
import scala.sys.process._
Seq("sh", "-c" , ". $HOME/.bashrc && myProg").!!

Related

How to get & set environment variables in Scala?

I want to set Scala variable to environmental variables and get the variable in shell scripting.
Setting environment variables
The companion object of scala.sys.process.Process has several apply factory methods that allow you to specify various parameters, such as
the arguments passed to the executable
current working directory of the started process
extra environment variables
For example:
import scala.sys.process.Process
import java.io.File
Process(
List("bash", "-c", """echo "pwd=$(pwd) FOOBAR=${FOOBAR}";"""),
Some(new java.io.File("..")),
"FOOBAR" -> "42"
).!!
will start bash in the parent directory of your current working directory, with an additional environment variable FOOBAR set to "42".
Getting environment variables
Works in exactly the same way as for Java, with System.getenv.
For example, if you start scala/scala3 from your terminal with
BARFOO="someValue" scala3
and then in the Scala-REPL run
System.getenv("BARFOO")
then it will return
"someValue"

fish shell functions not accessing user paths

I've recently started using fish, and I needed to use a jar file for google's bundletool.
As such, I needed to set up an alias/function for bundletool, and I chose a function since it seems more "fishy".
My function is simple:
function bundletool
java -jar bundletool-all-1.12.1.jar $argv
end
The bundletool jar itself lives at ~/.local/bin, which is on my fish user path:
lase#laser-razer /m/c/U/matth [1]> echo $fish_user_paths
/home/lase/.local/bin /usr/local/go/bin /home/lase/.nvm /home/lase/.cargo/bin /home/lase/.cargo
In a regular shell, I can execute java -jar bundletool-all-1.12.1.jar, and the command runs as expected. However, in the function, fish doesn't seem to know about my fish_user_paths, and reports it cannot find the jar file.
To remedy this, I had to update my function to specify the full path:
function bundletool
java -jar ~/.local/bin/bundletool-all-1.12.1.jar $argv
end
This works, but I feel like I'm doing something incorrectly. Should I be setting up my paths or functions in a different fashion?
Your function will run in the ordinary environment.
It will run with the current $PATH [0] and, more importantly to you, the current working directory.
What happens is this:
java -jar bundletool-all-1.12.1.jar
Will tell java to run the jar found at bundletool-all-1.12.1.jar.
Notably, fish just hands java the string "bundletool-all-1.12.1.jar", and java will then not look at $PATH. It does not care about $PATH. It simply looks at "bundletool-all-1.12.1.jar", and tries to open a file by that name.
And it will find that file, if it is in the current directory.
And that's the reason this worked for you when you executed it interactively - because you happened to be in that directory
And then you tried it with the function, but you tried it from a different directory, and so it didn't work.
This works, but I feel like I'm doing something incorrectly. Should I be setting up my paths or functions in a different fashion?
No, giving the full path to the file instead of relying on the working directory is the right thing to do.
[0]: $fish_user_paths is just a variable you set, that fish will then take care to add to $PATH. $PATH is the actual variable that fish and other tools (including any command fish starts, if it wants to) will use to find commands.

In powershell, how can I define all env vars for the next command similar to python's Popen abilities?

In powershell, how can I...
explicitly define all the env vars for the next command?
I don't want any system env vars if possible,
After this command runs I dont want anything we have done to affect further processes in the shell.
As an example, in python we have the equivalent ability in Popen to pass a dictionary of the full environment to the subprocess, and I'm hoping there might be something similar in Powershell.
I think this link explains what you need: Windows user environment variable vs. system environment variable
[Environment]::GetEnvironmentVariable("TEMP", "Machine")

Is there a configuration file for Scala REPL / SBT Console?

I've been trying to find some sort of a dotfile to put Scala REPL settings and custom function in.
In particular I'm interested in passing it flags like -Dscala.color (enables syntax highlighting), as well as overriding settings like result string truncation:
scala> :power
scala> vals.isettings.maxPrintString = 10000
It would be nice to have these settings apply to both the simple Scala REPL sessions as well as sbt console sessions.
Does such a central configuration place exist for Scala?
Maybe you can use a modernized Scala REPL:
https://lihaoyi.github.io/Ammonite/
Poor man's solution: Set yourself an alias
alias myScala='scala -Dscala.repl.axPrintString = 10000'
As mentioned here ~/.sbt/0.13/global.sbt is the global configuration file for sbt. You can change your global settings here, this probably not going to effect REPL but should do work with SBT Console
You mainly asked about property settings, this goes a little beyond that to consider loading a definitions file as well—and isn't much help for Windows—but I thought I'd share in case it's useful:
I've resorted to using a wrapper script saved as ~/bin/scala, to set config properties and load some utility functions:
#!/bin/sh
# The scala REPL doesn't have any config file, so this wrapper serves to set
# some property values and load an init file of utilities when run without
# arguments to enter REPL mode.
#
# If there are arguments, just assume we're running a .scala file in script
# mode, a class or jar, etc., and execute normally.
SCALA=${SCALA:-/usr/local/bin/scala}
if [ "$#" -eq 0 ] && [ -r ~/.config/scala/replinit.scala ]; then
exec "$SCALA" -i ~/.config/scala/replinit.scala -Dscala.color
else
exec "$SCALA" "$#"
fi
If you sometimes use Ammonite REPL, as another answer suggests, the utility definitions can be shared by loading them from ~/.ammonite/predef.scala:
try load.exec(ammonite.ops.home/".config"/'scala/"replinit.scala")
catch { case _: Exception => println("=== replrc not loaded! ===") }
I'm not sure about a way to load the init file for sbt console automatically, though—Seth Tisue's comment about the initialize setting is helpful for properties, but using a :load command in a value for initialCommands in console doesn't appear to work.

Cannot get system variables in scala

I am trying to print the a system variable in windows in scala. This is the code that I have written. I am getting null.
println(System.getenv("HOME"))
How do I get and print system variables in scala?
The reason you are getting null is that the variable isn't set in the context of the process. If it's set in the shell, it still might not be exported. Try
$ export HOME='....'
and then start your Scala program from the same shell session.