How to get & set environment variables in Scala? - 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"

Related

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")

How to get .bashrc / .profile variables in 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").!!

Accessing environment variables using $ in Scala process

I'm trying to use a command that uses environment variables, and following is working fine( this is not the actual command I'm going to use).
Seq("echo "+System.getenv("JAVA_HOME"))!
but is there way to use the following kind of syntax ? In the case if we load the command from .sh file ?
Seq("echo ${JAVA_HOME}")!
You can use scala process with bash -c to get environment variables:
import scala.sys.process._
val value = Seq("bash", "-c", "echo $JAVA_HOME").lines.head

Eval in fish shell function working strange

I tried to make wrapper to docker's command to change docker machine context. Here's the command and output:
docker-machine env dev
set -x DOCKER_TLS_VERIFY "1";
set -x DOCKER_HOST "tcp://192.168.99.101:2376";
set -x DOCKER_CERT_PATH "/Users/sandric/.docker/machine/machines/dev";
set -x DOCKER_MACHINE_NAME "dev";
# Run this command to configure your shell:
# eval (docker-machine env dev)
Code for function, I placed in .config/fish/config.fish:
function cdm
eval (docker-machine env $argv)
end
So, when trying to run cdm in new session, function evaluated, but context didn't change. If however, I'd run:
eval (docker-machine env default)
from command prompt, and tried to run cdm with different arguments - all works fine. So I suspect that it has smth to do with existing of environment variables this command trying to set from fish function.. I even tried then to experiment and change that function to alias (which is also alias to fish functions as I get) command with constant instead of parameter:
alias cdm "eval (docker-machine env dev)"
And it worked the same - it didn't changed environment variables if I ran this alias first on newly opened session, but if I run eval code from command prompt - after that alias working as expected.
So, whats its all about, anyone have any ideas?
It looks like that Docker's output does not specify an explicit scope, so when you run it inside your function and those variables have not been defined elsewhere, they will end up in the function's scope.
However, if you run the same code from the command prompt, you will end up with variables defined in the global scope, which are then updated by the set in the function.
See the documentation for set:
The scoping rules when creating or updating a variable are:
If a variable is explicitly set to either universal, global or local,
that setting will be honored. If a variable of the same name exists in
a different scope, that variable will not be changed.
If a variable is not explicitly set to be either universal, global or
local, but has been previously defined, the previous variable scope is
used.
If a variable is not explicitly set to be either universal, global or
local and has never before been defined, the variable will be local to
the currently executing function. Note that this is different from
using the -l or --local flag. If one of those flags is used, the
variable will be local to the most inner currently executing block,
while without these the variable will be local to the function. If no
function is executing, the variable will be global.
To fix this problem, try defining your cdm function with --no-scope-shadowing (although this seems to work, I'm not sure that it should).

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.