@@ -50,6 +50,7 @@ import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
5050import { Terminal } from ' xterm'
5151import { FitAddon } from ' xterm-addon-fit'
5252import { WebLinksAddon } from ' xterm-addon-web-links'
53+ import { ZerolagInputAddon } from ' xterm-zerolag-input'
5354import ' xterm/css/xterm.css'
5455import { DocumentCopy , DocumentAdd , Select , Delete } from ' @element-plus/icons-vue'
5556import { ElMessage } from ' element-plus'
@@ -67,6 +68,7 @@ const terminalRef = ref(null)
6768
6869let term = null
6970let fitAddon = null
71+ let zerolag = null
7072let isComposing = false
7173let wheelHandler = null
7274let viewportWheelHandler = null
@@ -142,6 +144,11 @@ const initTerminal = () => {
142144 const webLinksAddon = new WebLinksAddon ()
143145 term .loadAddon (webLinksAddon)
144146
147+ zerolag = new ZerolagInputAddon ({
148+ prompt: { type: ' regex' , pattern: / [$#%❯>] \s * $ / , offset: 2 }
149+ })
150+ term .loadAddon (zerolag)
151+
145152 if (terminalRef .value ) {
146153 term .open (terminalRef .value )
147154 fitAddon .fit ()
@@ -161,7 +168,20 @@ const initTerminal = () => {
161168 // Terminal input handler
162169 term .onData ((data ) => {
163170 if (isComposing) return
164- emit (' data' , data)
171+
172+ if (data === ' \r ' ) {
173+ zerolag .clear ()
174+ emit (' data' , data)
175+ } else if (data === ' \x7f ' || data === ' \b ' ) {
176+ zerolag .removeChar ()
177+ emit (' data' , data)
178+ } else if (data .length === 1 && data .charCodeAt (0 ) >= 32 ) {
179+ zerolag .addChar (data)
180+ emit (' data' , data)
181+ } else {
182+ zerolag .clear ()
183+ emit (' data' , data)
184+ }
165185 })
166186
167187 term .onSelectionChange (() => {
@@ -198,6 +218,7 @@ const initTerminal = () => {
198218 if (event .code === ' Space' || event .key === ' ' ) {
199219 event .preventDefault ()
200220 if (props .isConnected ) {
221+ if (zerolag) zerolag .addChar (' ' )
201222 emit (' data' , ' ' )
202223 term .scrollToBottom ()
203224 }
@@ -212,6 +233,7 @@ const initTerminal = () => {
212233 event .preventDefault ()
213234 navigator .clipboard .readText ().then (text => {
214235 if (props .isConnected ) {
236+ if (zerolag && text) zerolag .appendText (text)
215237 emit (' data' , text)
216238 }
217239 }).catch (err => console .warn (' Paste failed:' , err))
@@ -228,6 +250,13 @@ const initTerminal = () => {
228250 }
229251 return true
230252 })
253+
254+ // Rerender after write parsed
255+ term .onWriteParsed (() => {
256+ if (zerolag && zerolag .hasPending ) {
257+ zerolag .rerender ()
258+ }
259+ })
231260 }
232261}
233262
@@ -330,6 +359,7 @@ const focus = () => {
330359}
331360
332361const clear = () => {
362+ if (zerolag) zerolag .clear ()
333363 if (term) term .clear ()
334364}
335365
0 commit comments