I've been working a side project recently, when ever I have time, to make a small script that determines what Command Line Interface to load using node.js
and its built-in child_process
module.
The goal of the script is to determine the OS environment, determine that environments default shell, and use that shell to execute a command via node. The point is to make sure that it is cross-platform compatible.
I don't have much experience with JavaScript and can't help feeling there might be a better way to do it. Any feedback is appreciated.
terminal.js
// "linux": ["gnome-terminal", "konsole", "xfce4-terminal", "terminator", "xterm", "uxterm"],
// "win32": ["cmd","powershell","bash"],
// "darwin": ["bash"],
class Terminal {
constructor() {
this.get_linux_terminal = function () {
switch (process.env.GDMSESSION) {
// if session is using gtk
case 'ubuntu':
case 'ubuntu-2d':
case 'gnome':
case 'gnome-shell':
case 'gnome-classic':
case 'gnome-fallback':
case 'cinnamon':
return "gnome-terminal";
// xfce session has its own terminal, xfce is gtk compatible
case 'xfce':
return "xfce4-terminal";
// if session is using qt, kde and lxde are qt compatible
case 'kde-plasma':
return "konsole";
case 'Lubuntu':
return "lxterminal";
// if unknown session, default to xterm
default:
// attempt to determine desktop session
switch (process.env.XDG_CURRENT_DESKTOP) {
case 'Unity':
case 'GNOME':
case 'X-Cinnamon':
return "gnome-terminal";
case 'XFCE':
return "xfce4-terminal";
case 'KDE':
return "konsole";
case 'LXDE':
return "lxterminal";
default:
return "xterm";
}
return ""; // redundant LBYL response
}
};
this.set_linux_terminal = function (shell) {
// creates an object containing the environments
// default shell and execute option
switch (shell) {
case 'gnome-terminal':
case 'xfce4-terminal':
return {
'shell': shell,
'option': '-x'
};
case 'konsole':
case 'lxterminal':
case 'xterm':
return {
'shell': shell,
'option': '-e'
};
default:
return {
'shell': "xterm",
'option': '-e'
};
return ""; // redundant LBYL response
}
};
this.get_tty = function () {
if ("linux" == process.platform) {
// linux has a mass variety of environments and a variety of ways
// for determining those environments. best to go for the base
// environments by depending on the most common builtin shells instead.
// https://askubuntu.com/questions/72549/how-to-determine-which-window-manager-is-running
return this.set_linux_terminal(
this.get_linux_terminal()
);
}
if ("darwin" == process.platform){
// even though mac os x supports other shells, i assume that they
// support the command option as $SHELL -c "command string".
// some users report that $SHELL fails and that osascript works.
// https://ss64.com/osx/osascript.html
// return {
// 'shell': process.env.SHELL,
// 'option': '-c'
// };
return {
'shell': 'osascript',
'option': '-e',
'command': 'tell app "Terminal" to do script',
};
}
if ("win32" == process.platform) {
// windows xp and up can be gaurenteed to have the cmd.exe shell.
// %comspec% should default to %windir%\system32\cmd.exe unless
// otherwise modified by the end user.
// https://en.wikipedia.org/wiki/Environment_variable#Windows
return {
'shell': process.env.COMSPEC,
'option': '/c',
'command': 'start',
};
}
return {}; // redundant LBYL response
};
}
}
exports.cli = cli = new Terminal()
exports.has_a_tty = cli.get_tty()
cprocess.js
const terminal = require('./terminal');
const spawn = require('child_process').spawn;
switch (process.platform) {
case 'linux':
var echo = spawn(
terminal.has_a_tty.shell,
[
terminal.has_a_tty.option,
"python",
"-c",
"print('Hello, World');input('...enter to continue...')",
]
);
break;
case 'win32':
case 'darwin':
var echo = spawn(
terminal.has_a_tty.shell,
[
terminal.has_a_tty.option,
terminal.has_a_tty.command,
"python",
"-c",
"print('Hello, World');input('...enter to continue...')",
]
);
break;
default:
console.error(
new Error("Error: Could not determine the OS platform type.")
);
break;
}
echo.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
echo.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
echo.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});