diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index 032bae40..58dc51ae 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -141,6 +141,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit private toolbarRevealTimeout = new ResettableTimeout(() => { this.revealToolbar = false }, 1000) + private frontendWriteLock = Promise.resolve() get input$ (): Observable { if (!this.frontend) { @@ -373,14 +374,14 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit }) } - protected onFrontendReady (): void { + protected async onFrontendReady (): Promise { this.frontendIsReady = true if (this.savedState) { this.frontend!.restoreState(this.savedState) if (!this.savedStateIsLive) { - this.frontend!.write('\r\n\r\n') - this.frontend!.write(colors.bgWhite.black(' * ') + colors.bgBlackBright.white(' History restored ')) - this.frontend!.write('\r\n\r\n') + await this.frontend!.write('\r\n\r\n') + await this.frontend!.write(colors.bgWhite.black(' * ') + colors.bgBlackBright.white(' History restored ')) + await this.frontend!.write('\r\n\r\n') } } } @@ -411,13 +412,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit /** * Feeds input into the terminal frontend */ - write (data: string): void { - this.withSpinnerPaused(() => { - this.writeRaw(data) - }) + async write (data: string): Promise { + this.frontendWriteLock = this.frontendWriteLock.then(() => + this.withSpinnerPaused(() => this.writeRaw(data))) + await this.frontendWriteLock } - protected writeRaw (data: string): void { + protected async writeRaw (data: string): Promise { if (!this.frontend) { throw new Error('Frontend not ready') } @@ -434,7 +435,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit } } - this.frontend.write(data) + await this.frontend.write(data) } async paste (): Promise { @@ -780,10 +781,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.spinnerActive = false } - protected withSpinnerPaused (work: () => void): void { + protected async withSpinnerPaused (work: () => any): Promise { const wasActive = this.spinnerActive this.stopSpinner() - work() + await work() if (wasActive) { this.startSpinner() } diff --git a/tabby-terminal/src/features/debug.ts b/tabby-terminal/src/features/debug.ts index 3364f7c0..807a7316 100644 --- a/tabby-terminal/src/features/debug.ts +++ b/tabby-terminal/src/features/debug.ts @@ -121,7 +121,7 @@ export class DebugDecorator extends TerminalDecorator { private async doLoadOutput (terminal: BaseTerminalTabComponent) { const data = await this.loadFile() if (data) { - terminal.frontend?.write(data) + await terminal.frontend?.write(data) } } @@ -131,7 +131,7 @@ export class DebugDecorator extends TerminalDecorator { if (data.startsWith('`')) { data = data.substring(3, data.length - 3) } - terminal.frontend?.write(JSON.parse(data)) + await terminal.frontend?.write(JSON.parse(data)) } } } diff --git a/tabby-terminal/src/frontends/frontend.ts b/tabby-terminal/src/frontends/frontend.ts index d1362993..54056b72 100644 --- a/tabby-terminal/src/frontends/frontend.ts +++ b/tabby-terminal/src/frontends/frontend.ts @@ -72,7 +72,7 @@ export abstract class Frontend { abstract selectAll (): void abstract clearSelection (): void abstract focus (): void - abstract write (data: string): void + abstract write (data: string): Promise abstract clear (): void abstract visualBell (): void abstract scrollToBottom (): void diff --git a/tabby-terminal/src/frontends/xtermFrontend.ts b/tabby-terminal/src/frontends/xtermFrontend.ts index 9e0eb833..6217da9d 100644 --- a/tabby-terminal/src/frontends/xtermFrontend.ts +++ b/tabby-terminal/src/frontends/xtermFrontend.ts @@ -247,8 +247,8 @@ export class XTermFrontend extends Frontend { setTimeout(() => this.xterm.focus()) } - write (data: string): void { - this.xterm.write(data) + async write (data: string): Promise { + await new Promise(r => this.xterm.write(data, r)) } clear (): void {