diff --git a/packages/cli-repl/src/async-repl.ts b/packages/cli-repl/src/async-repl.ts index 175d9e86fb..2566a1bf20 100644 --- a/packages/cli-repl/src/async-repl.ts +++ b/packages/cli-repl/src/async-repl.ts @@ -49,7 +49,12 @@ function disableEvent(emitter: EventEmitter, event: string): RestoreEvents { }; } -// Start a REPLSever that supports asynchronous evaluation, rather than just +function getPrompt(repl: any): string { + // Use public getPrompt() API once available (Node.js 15+) + return repl.getPrompt?.() ?? repl._prompt; +} + +// Start a REPLServer that supports asynchronous evaluation, rather than just // synchronous, and integrates nicely with Ctrl+C handling in that respect. export function start(opts: AsyncREPLOptions): REPLServer { const repl = (opts.start ?? originalStart)(opts); @@ -64,6 +69,10 @@ export function start(opts: AsyncREPLOptions): REPLServer { let result; repl.emit(evalStart, { input } as EvalStartEvent); + // Use public getPrompt() API once available (Node.js 15+) + const origPrompt = getPrompt(repl); + repl.setPrompt(''); // Disable printing prompts while we're evaluating code. + try { let exitEventPending = false; const exitListener = () => { exitEventPending = true; }; @@ -116,6 +125,10 @@ export function start(opts: AsyncREPLOptions): REPLServer { (replSigint as any)?.restore?.(); (processSigint as any)?.restore?.(); + if (getPrompt(repl) === '') { + repl.setPrompt(origPrompt); + } + repl.removeListener('exit', exitListener); for (const listener of previousExitListeners) { repl.on('exit', listener); diff --git a/packages/cli-repl/src/mongosh-repl.spec.ts b/packages/cli-repl/src/mongosh-repl.spec.ts index 1d2a38a883..7b8852ff93 100644 --- a/packages/cli-repl/src/mongosh-repl.spec.ts +++ b/packages/cli-repl/src/mongosh-repl.spec.ts @@ -453,6 +453,35 @@ describe('MongoshNodeRepl', () => { expect(history).to.have.lengthOf(2); }); }); + + it('refreshes the prompt if a window resize occurs', async() => { + output = ''; + outputStream.emit('resize'); + await tick(); + expect(stripAnsi(output)).to.equal('> '); + }); + + it('does not refresh the prompt if a window resize occurs while evaluating', async() => { + let resolveInProgress; + mongoshRepl.runtimeState().repl.context.inProgress = + new Promise(resolve => { resolveInProgress = resolve; }); + input.write('inProgress\n'); + await tick(); + + output = ''; + outputStream.emit('resize'); + await tick(); + // The empty space is because the Node.js readline implementation still + // tries to make sure that something is printed when a resize happens. + // This is okay, though, because it also moves the cursor back to where + // it originally was. + expect(stripAnsi(output)).to.equal(' '); + + output = ''; + resolveInProgress(); + await tick(); + expect(stripAnsi(output)).to.equal('\n> '); + }); }); context('with fake TTY', () => {