Skip to content

Commit 58abb98

Browse files
Try xterm renderer addons for terminal (#436)
1 parent 00d78bd commit 58abb98

3 files changed

Lines changed: 64 additions & 1 deletion

File tree

bun.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
"@vercel/analytics": "^1.5.0",
9595
"@vercel/otel": "^2.1.2",
9696
"@vercel/speed-insights": "^1.2.0",
97+
"@xterm/addon-canvas": "^0.7.0",
98+
"@xterm/addon-fit": "^0.11.0",
99+
"@xterm/addon-webgl": "^0.19.0",
97100
"@xterm/xterm": "^6.0.0",
98101
"cheerio": "^1.0.0",
99102
"chrono-node": "^2.8.4",

src/features/dashboard/terminal/use-terminal-instance.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { CanvasAddon } from '@xterm/addon-canvas'
2+
import { FitAddon } from '@xterm/addon-fit'
3+
import { WebglAddon } from '@xterm/addon-webgl'
14
import '@xterm/xterm/css/xterm.css'
25
import { Terminal as XTerm } from '@xterm/xterm'
36
import { useCallback, useEffect, useRef } from 'react'
@@ -27,12 +30,14 @@ export function useTerminalInstance({
2730
onResize,
2831
}: UseTerminalInstanceOptions) {
2932
const xtermRef = useRef<XTerm | null>(null)
33+
const fitAddonRef = useRef<FitAddon | null>(null)
3034
const terminalContainerRef = useRef<HTMLDivElement | null>(null)
3135
const terminalTranscriptRef = useRef(INITIAL_TERMINAL_TEXT)
3236
const terminalSizeRef = useRef({ cols: DEFAULT_COLS, rows: DEFAULT_ROWS })
3337
const decoderRef = useRef(new TextDecoder())
3438

3539
const resizeTerminal = useCallback(() => {
40+
fitAddonRef.current?.fit()
3641
const nextSize = calculateTerminalSize(
3742
terminalContainerRef.current,
3843
xtermRef.current
@@ -99,26 +104,71 @@ export function useTerminalInstance({
99104
theme: TERMINAL_THEME,
100105
})
101106

107+
const fitAddon = new FitAddon()
108+
let rendererAddon: WebglAddon | CanvasAddon | undefined
109+
let contextLossSubscription: { dispose: () => void } | undefined
110+
102111
xtermRef.current = terminal
112+
fitAddonRef.current = fitAddon
113+
terminal.loadAddon(fitAddon)
103114
terminal.open(container)
104-
terminal.write(terminalTranscriptRef.current)
115+
116+
try {
117+
const webglAddon = new WebglAddon()
118+
const webglContextLossSubscription = webglAddon.onContextLoss(() => {
119+
webglContextLossSubscription.dispose()
120+
webglAddon.dispose()
121+
if (rendererAddon === webglAddon) {
122+
rendererAddon = undefined
123+
}
124+
if (contextLossSubscription === webglContextLossSubscription) {
125+
contextLossSubscription = undefined
126+
}
127+
})
128+
contextLossSubscription = webglContextLossSubscription
129+
rendererAddon = webglAddon
130+
terminal.loadAddon(webglAddon)
131+
} catch {
132+
contextLossSubscription?.dispose()
133+
contextLossSubscription = undefined
134+
rendererAddon?.dispose()
135+
try {
136+
rendererAddon = new CanvasAddon()
137+
terminal.loadAddon(rendererAddon)
138+
} catch {
139+
rendererAddon?.dispose()
140+
rendererAddon = undefined
141+
}
142+
}
143+
105144
const dataSubscription = terminal.onData(onInput)
145+
terminal.write(terminalTranscriptRef.current, () => {
146+
terminal.scrollToBottom()
147+
})
106148

107149
requestAnimationFrame(() => {
108150
resizeTerminal()
109151
terminal.focus()
152+
terminal.scrollToBottom()
110153
})
111154
const resizeTimer = window.setTimeout(() => {
112155
resizeTerminal()
156+
terminal.scrollToBottom()
113157
}, 100)
114158

115159
return () => {
116160
window.clearTimeout(resizeTimer)
117161
dataSubscription.dispose()
162+
contextLossSubscription?.dispose()
163+
rendererAddon?.dispose()
164+
fitAddon.dispose()
118165
terminal.dispose()
119166
if (xtermRef.current === terminal) {
120167
xtermRef.current = null
121168
}
169+
if (fitAddonRef.current === fitAddon) {
170+
fitAddonRef.current = null
171+
}
122172
}
123173
}, [onInput, resizeTerminal])
124174

0 commit comments

Comments
 (0)