How do I connect xterm.js(in electron) to a real working command prompt?

Viewed 2596

I've dug myself into a deep rabbit hole trying to find out what the title says. If you're confused about what this question is, I'll give a more detailed explanation: Have you ever seen the VSCode Terminal? or Terminus? Well I want to do what those applications do. I have an electron app, and for the users convenience I want to include a command prompt of some sorts into it. I've looked in to xterm.js, but I can only find examples of things like SSH, not a direct link to a console hosted on the system. What I'm asking is how do I connect xterm.js(in electron) to a real working command prompt? I've seen programs able to interact with cmd.exe such as Windows Terminal. I'll use it as an example.

Image taken from process hacker

In the attached photo you can see three processes. WindowsTerminal.exe, OpenConsole.exe, and cmd.exe. After digging around in the source code of Windows Terminal, I can see the OpenConsole.exe gets started with every instance of a cmd that you make. So I assume that is the program that's interacting with cmd.exe. Now I know that Windows Terminal is made using UWP but you can see similar things happening with VSCode(I opened a bunch of terminals to demonstrate)

here is another post with a similar question, but with no answers. I hope this one gains some traction.

So if you can answer, thanks. If you got sidetracked a bit, remember my question: How do I connect xterm.js(in electron) to a real working command prompt?

Sorry if you couldn't understand my wording, im not very good at this :P

2 Answers

The following video was helpful for me. Shortly, you need to :

  1. install node-pty and electron-rebuild packages (additional to the xterm)
  2. Place the following codes to appropriate process files

In the main process (main.js):

const os = require('os');
const pty = require('node-pty');

var shell = os.platform() === "win32" ? "powershell.exe" : "bash";
var ptyProcess = pty.spawn(shell, [], {
        name: 'xterm-color',
        cols: 80,
        rows: 24,
        cwd: process.env.HOME,
        env: process.env
    });
    
    ptyProcess.on("data", (data) => {
      mainWindow.webContents.send("terminal-incData", data);
    });

    ipcMain.on("terminal-into", (event, data)=> {
      ptyProcess.write(data);
    })

In the renderer process:

const Terminal  =  require('xterm').Terminal;
const FitAddon = require('xterm-addon-fit').FitAddon;

const term = new Terminal();
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);

// Open the terminal in #terminal-container
term.open(document.getElementById('terminal-container'));
term.onData(e => {
    ipcRenderer.send("terminal-into", e);
} );
ipcRenderer.on('terminal-incData', (event, data) => {
    term.write(data);
})

// Make the terminal's size and geometry fit the size of #terminal-container
fitAddon.fit();
  1. run electron-rebuild command if you get an error.

You might get the following errors when you try to install electron-rebuild package:

  • Solution for MAC: error: no template named 'remove_cv_t'.
  • Solution for Windows: gyp ERR! find Python
Related