• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2var childProcess = require("child_process");
3var os = require("os");
4
5module.exports = function opener(args, options, callback) {
6    var platform = process.platform;
7
8    // Attempt to detect Windows Subystem for Linux (WSL). WSL  itself as Linux (which works in most cases), but in
9    // this specific case we need to treat it as actually being Windows. The "Windows-way" of opening things through
10    // cmd.exe works just fine here, whereas using xdg-open does not, since there is no X Windows in WSL.
11    if (platform === "linux" && os.release().indexOf("Microsoft") !== -1) {
12        platform = "win32";
13    }
14
15    // http://stackoverflow.com/q/1480971/3191, but see below for Windows.
16    var command;
17    switch (platform) {
18        case "win32": {
19            command = "cmd.exe";
20            break;
21        }
22        case "darwin": {
23            command = "open";
24            break;
25        }
26        default: {
27            command = "xdg-open";
28            break;
29        }
30    }
31
32    if (typeof args === "string") {
33        args = [args];
34    }
35
36    if (typeof options === "function") {
37        callback = options;
38        options = {};
39    }
40
41    if (options && typeof options === "object" && options.command) {
42        if (platform === "win32") {
43            // *always* use cmd on windows
44            args = [options.command].concat(args);
45        } else {
46            command = options.command;
47        }
48    }
49
50    if (platform === "win32") {
51        // On Windows, we really want to use the "start" command. But, the rules regarding arguments with spaces, and
52        // escaping them with quotes, can get really arcane. So the easiest way to deal with this is to pass off the
53        // responsibility to "cmd /c", which has that logic built in.
54        //
55        // Furthermore, if "cmd /c" double-quoted the first parameter, then "start" will interpret it as a window title,
56        // so we need to add a dummy empty-string window title: http://stackoverflow.com/a/154090/3191
57        //
58        // Additionally, on Windows ampersand and caret need to be escaped when passed to "start"
59        args = args.map(function (value) {
60            return value.replace(/[&^]/g, "^$&");
61        });
62        args = ["/c", "start", "\"\""].concat(args);
63    }
64
65    return childProcess.execFile(command, args, options, callback);
66};
67