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.

The class core.sys.Execute provides more control over process execution. It has the following members:

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:

  1. If the program xdg-terminal-exec is installed, it is used. While xdg-terminal-exec is new, it represents a standardized way in which programs can ask to start a new instance of the user's preferred terminal emulator.
  2. 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 splitting STORM_TERM_COMMAND on spaces). For example, to launch xterm, one could set export STORM_TERM_COMMAND="xterm -e".
  3. Attempt to launch xterm using xterm -e followed by the command.
  4. 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).