nodejs下 electron 使用 Web Termination

想在工具里面执行 shell 进行部分命令行交互

基于 微软开源的 xterm.js 和 nodepty

https://github.com/microsoft/xterm.js 前端

https://github.com/microsoft/node-pty 后台

index.html 文件

<!doctype html>
<html>
  <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
  <body>
    <div ></div>
  </body>
  <script>
    window.require = window.parent.require;

    var global_xterm = undefined;
    var global_pty = undefined;
    function InitShellEnv(){
        // Initialize xterm.js and attach it to the DOM
        if (!global_xterm){
            var os = require('os');
            var process = require('process');
            var pty = require('node-pty');
            var Terminal = require('xterm').Terminal;
            var FitAddon = require('xterm-addon-fit').FitAddon

            const shell = process.env[os.platform() === 'win32' ? 'COMSPEC' : 'SHELL'];

            const ptyProcess = pty.spawn(shell, [], {
                name: 'xterm-color',
                cols: 80,
                rows: 34,
                cwd: process.cwd(),
                env: process.env
            });

            const xterm = new Terminal({
                cols: 80,
                rows: 34,
                cursorBlink: true,
            });
            xterm.open(document.getElementById('terminal'));
            global_xterm = xterm;
            global_pty = ptyProcess;

            const fitaddon = new FitAddon();
            xterm.loadAddon(fitaddon);
            fitaddon.fit()

            // Setup communication between xterm.js and node-pty
            xterm.onData(data => {
                ptyProcess.write(data)
                console.log("xterm=> "+ data);
            });
            ptyProcess.on('data', function (data) {
                xterm.write(data);
            });

            xterm.onLineFeed(() => {
                const buffer = xterm.buffer;
                const newLine = buffer.getLine(buffer.baseY + buffer.cursorY);
                if (newLine && !newLine.isWrapped) {
                    var inputdata = getLineData(buffer, buffer.baseY + buffer.cursorY - 1);
                    // parseCmd(inputdata);
                    console.log(inputdata);
                }else{
                }
            })

            const remote = require('electron').remote
            var apppath = remote.app.getAppPath();
            global_pty.write("cd " + apppath +"\n");
        }
    }

    function getLineData(buffer, lineIndex) {
        let line = buffer.getLine(lineIndex);
        if (!line) {
            return;
        }
        let lineData = line.translateToString(true);
        while (lineIndex > 0 && line.isWrapped) {
            line = buffer.getLine(--lineIndex);
            if (!line) {
                break;
            }
            lineData = line.translateToString(false) + lineData;
        }
        return lineData;
    }
    </script>
</html>

一定要注意 nodepty 和 electron 的版本要对应上 否则 会有各种各样奇奇怪怪的兼容问题 当初在这里纠结了将近3天 简直崩溃。

node-pty 有对应 nodejs 的版本 还有对应 electron 的版本,这两个版本是无法通用的. 一般下载的都是针对nodejs的版本,需要 electron-rebuild 重新生成 electron 版本的nodepty 但是生成过程极易遇到各种版本兼容问题

这里贴出我 package.json 文件, 这里标记了 electron node-pty 和 nodej 对应的版本。因为我这里还有其他的代码没有贴出来 可能有对于这个demo 来说冗余的库也在里面

{
    "name": "fileinfotool",
    "version": "0.1.0",
    "main": "main.js",
    "scripts": {
        "rebuild": "electron-rebuild -f -w node-pty"
    },
    "dependencies": {
        "electron": "^5.0.11",
        "iconv-lite": "^0.5.0",
        "node-pty": "^0.8.1",
        "xterm": "^4.1.0",
        "xterm-addon-fit": "^0.2.1",
        "image-size": "^0.7.4"
    },
    "devDependencies": {
        "electron-rebuild": "^1.8.6"
    }
}