System Interfaces
The core.sys package contains interfaces for interacting with the operating system.
At this time, these interfaces are focused on launching other processes.
Starting Processes
The following free functions are provided to ask the operating system to open files (and web
addresses through core.io.Urls), as well as starting arbitrary programs.
-
void open(core.io.Url file)Open an
Urlusing the default program that is associated with the file in the operating system. Throws aSystemErroron failure. -
void execute(core.io.Url program, core.Array<core.Str> args)Execute the program
programwith the parameters inargs. Ifprogramis a relative url that consists of a single part, then the function searches for the program in thePATHenvironment variable.Equivalent to
Execute(program, params).detach().
The class core.sys.Execute provides more control over process execution. It has the
following members:
-
core.sys.Execute workingDirectory(core.Maybe<core.io.Url> dir)Set the working directory.
-
core.sys.Execute newTerminal()Start the program in a new terminal window (implies a new process group).
- On Windows: this is only done if the started program is a console application.
-
On Linux: this always launches a new terminal using
xdg-terminal-execif available.
-
core.sys.Execute newGroup()Start the program in a new process group. Mostly relevant for terminal-based applications.
-
void detach()Execute the program and detach it from the current process (i.e., we will not wait for it, nor interact with stdin/stdout).
Note that the members that set properties return the object itself. This is to make it possible to chain such calls into a single line. For example, to start a program in a new terminal window, one can write:
Execute("emacs", ["~/.emacs"]).newTerminal().detach();
This design also allows extending the capabilities of the core.sys.Execute interface in
the future without creating many combinations of the execute overload.
Notes for Windows
On Windows, the open function calls the Win32 function ShellExecute, which takes file
associations into account. This makes the open function roughly equivalent to typing the URL in
the "Run" dialog.
The functionality provided by Execute is based around the Win32 function CreateProcess. While it
is straight-forward to map most of the functionality to CreateProcess, there is one notable
exception: namely that Windows treats all command-line arguments as a single string that is passed
to the program. It is then up to each individual program to split the string into individual
arguments. Storm constructs a string of the quoted arguments for you, using a format that
corresponds to what the C runtime library understands. This should cover most use-cases. However, a
notable exception from this convention is cmd.exe.
Notes for Linux
The open function is implemented by calling the xdg-open program on Linux. This makes Storm
respect the file associations that are set up by the desktop environment. However, xdg-open is not
always installed, and it is not always possible to detect errors from xdg-open as it sometimes
forks off the new process, and sometimes simply execs into it. Storm does its best to account for
this and interprets the exit codes from xdg-open, but since it does not always terminate quickly
Storm has to wait for a while before it is able to determine whether xdg-open succeeded or not.
The functionality provided by Execute generally maps well to exec and fork on Linux. One
difficulty is that there is no well-established way to determine which terminal emulator to launch
for terminal applications. The implementation currently has the following approach:
-
If the program
xdg-terminal-execis installed, it is used. Whilexdg-terminal-execis new, it represents a standardized way in which programs can ask to start a new instance of the user's preferred terminal emulator. -
Inspect the environment variable
STORM_TERM_COMMAND. If it is set, Storm will append the program to start to the end of the command and execute it (after splittingSTORM_TERM_COMMANDon spaces). For example, to launchxterm, one could setexport STORM_TERM_COMMAND="xterm -e". -
Attempt to launch
xtermusingxterm -efollowed by the command. - If everything else fails, throw an error.
Finally, it is worth noting that old versions of xdg-terminal-exec did not support any command
line arguments. Since Storm uses xdg-terminal-exec -- <command> to avoid problems with commands
that start with dashes, old versions of xdg-terminal-exec will launch a terminal that just
complains that it is unable to launch the command --. To solve this problem, you need a newer
version of xdg-terminal-exec (it is not possible to detect the old version programmatically as it
does not accept any command line parameters such as --version).
