xterm遇到的问题及解决方案
/r插入终端导致的之后插入的数据覆盖了改行头部的数据
问题说明
如图所示,当在一行输入的候,输入的l插入到了改行的头部。
查看ws返回数据
可见ws返回的信息存在\r
字符,在xterm.js中\r
是回车字符的意思,但是\r
并不会让xterm.js中的光标到下一行,而是让光标到当前行的起始位置
,所以就会导致当前行的头部数据被覆盖。
问题分析
在xterm.js的issus中找到一个相似的问题,Xterm overwrites comands on same line if its longer #1359。
分析结果为,当前端xterm.js渲染的终端列数大于后端终端的列数就会出现这样的问题。
假设xterm.js渲染的终端列数和后端的终端列数一致,当输入到这一行的最后一个列数后再输入就会返回\r
,但是如果列数相同,xterm.js会自动换行显示,会新起一行,这时候再插入\r
会将光标移动到新起一行的开头插入数据,则不会有影响。
假设xterm.js渲染的终端列数和后端的终端列数不一致,当前端输入还没有自动换行,还没有新起一行则接收到了\r
,所以光标移动到开头插入则会覆盖头部的数据。
解决方案
一般这种情况是前端使用了xterm-addon-fit
插件来将整个终端盛满父容器,但是盛满后没有将终端的row
和col
返回给后端设置终端大小导致的。
解决方法分为两种:
1、在xterm.js初始化时和在窗口大小改变时将row和col返回给后端进行设置。
2、取消使用xterm-addon-fit
插件初始化设置终端大小和后端一致。
xterm主屏幕缓冲区和备用屏幕缓冲区切换
问题说明
需求是通过xterm.js实现一个终端,上方存在下拉框可以切换容器,但是切换的时候不清空上次终端操作的内容。
其实在切换终端的时候我们什么都不做处理就可以实现保留上次终端的内容。
但是会有一个问题,就是如果通过vim命令进入编辑状态,这时候切换终端,新的终端返回的内容会在vim编辑状态的最上面显示。
如图所示,新进入的终端的内容没有插入到了vim编辑状态的上面。
问题分析
因为终端分为主屏幕缓冲区和备用屏幕缓冲区,当切换终端的时候没有退出上一次终端的备用屏幕缓冲区,导致新进入的终端内容插入到了备用屏幕缓冲区。
解决方案
通过ws接收信息,如果内容存在\u001b[?1049h
则为进入备用屏幕缓冲区,如果内容存在\u001b[?1049l
则为进入主屏幕缓冲区。
可以创建一个变量来判断当前是否处于备用屏幕缓冲区,如果处于备用屏幕缓冲区切换终端是先退出备用屏幕缓冲区再创建ws进入终端。
spare = false
handleSocketMessage(data) {
// 进入备用屏幕缓冲区if (content.includes('\u001b[?1049h')) {this.spare = true;}// 退出备用屏幕缓冲区if (content.includes('\u001b[?1049l')) {this.spare = false;}
}
// 进入终端
intoTerminal() {// 是否处于备用屏幕缓冲区if (this.term?.element && this.spare) {// 退出备用屏幕缓冲区this.term.write('\u001b[?1049l');// 设置备用屏缓冲区状态this.spare = false;}
}
通过write插入内容,后插入的内容太多会导致之前插入的数据丢失
问题说明
通过write插入内容,后插入的内容太多会导致之前插入的数据丢失。
问题分析
缓冲区大小限制太小。
解决方案
初始化终端的时候配置缓冲区大小。
let term = new Terminal({scrollback: 100000, // 终端缓冲区大小
});