终端接口和伪终端分别做什么?
结论
window.createTerminal 打开一个真实 shell,适合让用户继续输入命令。Pseudoterminal 是你自己实现的终端:你往界面写输出,用户按键通过回调给你,背后不一定有 shell。
展开
真实终端:
const terminal = vscode.window.createTerminal({ name: "构建", cwd: folder.uri });
terminal.show();
terminal.sendText("npm run build");
远程工作区里这样创建,shell 在远端。sendText 只是模拟输入,用户还能接着敲。进程生命周期由终端自己管。
伪终端适合进度型任务、解释型 REPL、把远端流包装成终端外观:
const pty: vscode.Pseudoterminal = {
onDidWrite: emitter.event,
open() {
emitter.fire("开始\r\n");
},
close() {
/* 停掉背后的任务 */
},
handleInput(data) {
/* 用户按键 */
}
};
vscode.window.createTerminal({ name: "任务", pty });
写入要用终端的换行 \r\n。关闭时停掉真实子进程,避免界面关了进程还在。
长时间输出要节流,不要每个字节都 fire 一次。颜色可以用终端转义序列,但别把未经过滤的控制序列从不可信程序直接透传给本地终端时不做限制。至少要知道这是在画用户界面。
需要和任务系统集成时,优先看任务提供器。终端是交互界面,任务多了问题面板、分组和默认测试命令的约定。
容易讲错的点
sendText不是等命令结束的 API。要知道结束,需要 shell 集成、退出码协议,或自己用伪终端包一层子进程。- 伪终端跑在扩展宿主里。
handleInput里同步做重活会卡住宿主。 - 不要用终端当日志系统。日志用输出通道,用户才能单独开关和搜。