入職的新公司所在的事業部專一於K12的編程教育。公司項目裏有使用xterm.js這個庫, 並基於master分支作出了必定的修改。爲了儘快的熟悉業務以及公司的代碼, 因此這裏打算學習xterm.js的文檔(粗略的翻譯, 方便本身查閱, 凡是保留原文的地方, 是我目前尚未明白具體使用場景和用法的地方)javascript
最近比較忙啊, 尚未過試用期也不敢太早回家。因此只有這個週六更新了 😢css
xterm是一個使用TypeScript編寫的前端終端組件。並在Vscode等熱門項目中獲得了應用前端
npm install xterm
複製代碼
// 初始化終端 import { Terminal } from 'xterm' import 'xterm/dist/xterm.css' let term = new Terminal() // 將term掛砸到dom節點上 term.open(document.getElementById('app')) term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ') 複製代碼
插件爲javascript的模塊能夠擴展Terminal的原型java
import { Terminal } from 'xterm'; import * as fit from 'xterm/lib/addons/fit/fit' // 擴展Terminal Terminal.applyAddon(fit) let term = new Terminal() term.open(document.getElementById('#terminal')) // 使用fit方法 term.fit() 複製代碼
這裏包含了xterm.js的類型聲明文件d.tsios
終端的字體粗細git
終端的渲染方式, dom渲染或者是canvas渲染github
建立一個新的Terminal對象web
// 參數類型, 須要ITerminalOptions接口的定義 // 返回Terminal類型 new Terminal(options?: ITerminalOptions): Terminal 複製代碼
終端窗口的列數, 能夠在建立Terminal指定colsdocker
// 終端中每一行最多一列 let term = new Terminal({ cols: 1 }) 複製代碼
// 終端掛載的Dom元素 term.element 複製代碼
終端的全部標記shell
終端窗口的行數, 能夠在建立Terminal指定rows
let term = new Terminal({ rows: 30 }) 複製代碼
返回, 接受終端輸入的textarea的dom節點
Natural language strings that can be localized.
Adds a handler for CSI escape sequences.
向終端添加事件監聽器, 並返回可用於刪除事件監聽器的對象, 對象中dispose屬性的方法能夠取消監聽。支持的事件參考off方法的內容。
// 終端添加focus事件的監聽, dispose函數能夠取消監聽 const { dispose } = term.addDisposableListener('focus', function () { console.log('focus') dispose() }) 複製代碼
添加標記, addMarker接受一個數字做爲參數, 數字表示當前光標到標記y的偏移量,並返回標記。
let buffer = term.addMarker(cursorYOffset: number): IMarker let term = new Terminal() term.open(document.getElementById('app')) term.write('Hello from \x1B[1;3;31mxterm.js\x1B') term.addMarker(0) term.addMarker(1) // 返回兩個標記 console.log(term.markers) 複製代碼
Adds a handler for OSC escape sequences.
Attaches a custom key event handler which is run before keys are processed, giving consumers of xterm.js ultimate control as to what keys should be processed by the terminal and what keys should not.
Deregisters the character joiner if one was registered. NOTE: character joiners are only used by the canvas renderer.
Deregisters a link matcher if it has been registered.
使終端失焦
清除整個終端, 只保留當前行
選擇終端內的全部文本
選中指定的兩個指定行之間的終端文本
term.write('Hello from \x1B[1;3;31mxterm.js\x1B') term.selectLines(0, 0) 複製代碼
清除當前選擇的終端(只是清除選擇的內容, 而非清除終端)
銷燬終端, 不推薦使用。推薦使用dispose()
銷燬終端
終端得到焦點
獲取的終端的配置選項, 須要指定配置的key
let term = new Terminal({ fontWeight: '800', fontSize: 20 }) term.open(document.getElementById('app')) term.write('Hello from \x1B[1;3;31mxterm.js\x1B') // '800' console.log(term.getOption('fontWeight')) // 20 console.log(term.getOption('fontSize')) 複製代碼
詳細的類型推導請參考下圖
獲取當前終端選擇的內容。(鼠標光標選中的內容)
判斷當前終端是否有選中的內容。(鼠標光標選中的內容)
刪除事件監聽, 支持的方法見上圖
添加事件監聽, 支持註冊的事件如上圖
打開終端。(xterm必須掛載dom完成)
刷新指定兩行之間的內容
Registers a character joiner, allowing custom sequences of characters to be rendered as a single unit. This is useful in particular for rendering ligatures and graphemes, among other things.
Each registered character joiner is called with a string of text representing a portion of a line in the terminal that can be rendered as a single unit. The joiner must return a sorted array, where each entry is itself an array of length two, containing the start (inclusive) and end (exclusive) index of a substring of the input that should be rendered as a single unit. When multiple joiners are provided, the results of each are collected. If there are any overlapping substrings between them, they are combined into one larger unit that is drawn together.
All character joiners that are registered get called every time a line is rendered in the terminal, so it is essential for the handler function to run as quickly as possible to avoid slowdowns when rendering. Similarly, joiners should strive to return the smallest possible substrings to render together, since they aren’t drawn as optimally as individual characters.
NOTE: character joiners are only used by the canvas renderer.
Registers a link matcher, allowing custom link patterns to be matched and handled.
重置整個終端
調整終端的大小, 參數爲指定的col, row
控制終端滾動條的滾動的行數(正數向下滾動, 負數向上滾動)
滾動的頁面樹(正數向下滾動, 負數向上滾動)
滾動到底部
滾動到具體的行
滾動到頂部
設置終端的配置, 具體的配置請參考下圖
向終端寫入文本並換行
向終端寫入文本
添加插件到終端的原型上
這裏沒有什麼好翻譯的了, Xterm.js是由TypeScript編寫。這裏定義Xterm內部以及外部參數和返回值的iterface
attach能夠將終端附加到websocket流中。Terminal實例會捕獲全部鍵盤和鼠標事件並經過socket發送給後端
import * as Terminal from 'xterm'; import * as attach from 'xterm/lib/addons/attach/attach'; // 添加attach插件 Terminal.applyAddon(attach); var term = new Terminal(); var socket = new WebSocket('wss://docker.example.com/containers/mycontainerid/attach/ws'); term.attach(socket) 複製代碼
// socket socoket實例 // bidirectional 終端是否向套接字發送數據 // bufferred 終端是否緩衝輸出得到更好的性能 attach(socket: WebSocket, bidirectional: Boolean, bufferred: Boolean) 複製代碼
// 分離當前終端和scoket detach(socket) 複製代碼
調整終端的大小以及行和列適配父級元素
fullscreen插件提供了設置全屏終端的toggleFullScreen方法, toggleFullScreen接受Boolean類型的值, 設置是否全屏展現終端
// 前端代碼 import { Terminal } from 'xterm' import 'xterm/dist/xterm.css' import io from 'socket.io-client'; const socket = io('http://localhost:3000'); let term = new Terminal({ fontSize: 30 }) term.open(document.getElementById('app')) socket.on('concat', function (data) { socket.emit('run', { xml: ` #include <iostream> using namespace std; int main() { cout << "Nice to meet you."; return 0; } `}) socket.on('writeIn', function (xml) { term.writeln(xml) }) }) 複製代碼
// 後端代碼 const Koa = require('koa') const Router = require('koa-router') const app = new Koa() const router = new Router() const server = require('http').createServer(app.callback()) const io = require('socket.io')(server) const json = require('koa-json') const onerror = require('koa-onerror') const bodyparser = require('koa-bodyparser') const logger = require('koa-logger') const config = require('./config') const routes = require('./routes') onerror(app) app.use(bodyparser()) .use(json()) .use(logger()) .use(router.routes()) .use(router.allowedMethods()) routes(router) io.on('connection', function (socket) { socket.emit('concat'); socket.on('run', function () { socket.emit('writeIn', '編譯成功') socket.emit('writeIn', '代碼運行結束') }) }) app.on('error', function(err, ctx) { logger.error('server error', err, ctx) }) module.exports = server.listen(config.port, () => { console.log(`Listening on http://localhost:${config.port}`) }) s 複製代碼
到這裏咱們大概對Xterm.js這個庫有了一個初步的認知, 不至於在接下來的工做中無從下手了