From 96a490060785f0fe9ee981f856b60e545a6c440c Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 27 Apr 2021 12:44:43 +0200 Subject: [PATCH 1/3] fix(cli-repl): do not print prompt while evaluating MONGOSH-700 --- packages/cli-repl/src/mongosh-repl.spec.ts | 29 ++++++++++++++++++++++ packages/cli-repl/src/mongosh-repl.ts | 5 ++-- 2 files changed, 32 insertions(+), 2 deletions(-) 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', () => { diff --git a/packages/cli-repl/src/mongosh-repl.ts b/packages/cli-repl/src/mongosh-repl.ts index 7bd0eee73e..e0ad8ded1c 100644 --- a/packages/cli-repl/src/mongosh-repl.ts +++ b/packages/cli-repl/src/mongosh-repl.ts @@ -308,12 +308,13 @@ class MongoshNodeRepl implements EvaluationListener { } async eval(originalEval: asyncRepl.OriginalEvalFunction, input: string, context: any, filename: string): Promise { + const { internalState, repl, shellEvaluator } = this.runtimeState(); + if (!this.insideAutoComplete) { + repl.setPrompt(''); // Disable printing prompts while we're evaluating code. this.lineByLineInput.enableBlockOnNewLine(); } - const { internalState, repl, shellEvaluator } = this.runtimeState(); - try { const shellResult = await shellEvaluator.customEval(originalEval, input, context, filename); if (!this.insideAutoComplete) { From 4d4fdaa374325bbef2b0d3e8de477364fb8c64fd Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 27 Apr 2021 15:02:40 +0200 Subject: [PATCH 2/3] fixup! fix(cli-repl): do not print prompt while evaluating MONGOSH-700 --- packages/cli-repl/src/async-repl.ts | 6 ++++++ packages/cli-repl/src/mongosh-repl.ts | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/cli-repl/src/async-repl.ts b/packages/cli-repl/src/async-repl.ts index 175d9e86fb..d44846810d 100644 --- a/packages/cli-repl/src/async-repl.ts +++ b/packages/cli-repl/src/async-repl.ts @@ -64,6 +64,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 = (repl as any).getPrompt?.() ?? (repl as any)._prompt; + repl.setPrompt(''); // Disable printing prompts while we're evaluating code. + try { let exitEventPending = false; const exitListener = () => { exitEventPending = true; }; @@ -116,6 +120,8 @@ export function start(opts: AsyncREPLOptions): REPLServer { (replSigint as any)?.restore?.(); (processSigint as any)?.restore?.(); + 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.ts b/packages/cli-repl/src/mongosh-repl.ts index e0ad8ded1c..7bd0eee73e 100644 --- a/packages/cli-repl/src/mongosh-repl.ts +++ b/packages/cli-repl/src/mongosh-repl.ts @@ -308,13 +308,12 @@ class MongoshNodeRepl implements EvaluationListener { } async eval(originalEval: asyncRepl.OriginalEvalFunction, input: string, context: any, filename: string): Promise { - const { internalState, repl, shellEvaluator } = this.runtimeState(); - if (!this.insideAutoComplete) { - repl.setPrompt(''); // Disable printing prompts while we're evaluating code. this.lineByLineInput.enableBlockOnNewLine(); } + const { internalState, repl, shellEvaluator } = this.runtimeState(); + try { const shellResult = await shellEvaluator.customEval(originalEval, input, context, filename); if (!this.insideAutoComplete) { From dab367a9dbc090f6c53501d6ae1cc25eff174bee Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 27 Apr 2021 17:28:17 +0200 Subject: [PATCH 3/3] fixup! fixup! fix(cli-repl): do not print prompt while evaluating MONGOSH-700 --- packages/cli-repl/src/async-repl.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/cli-repl/src/async-repl.ts b/packages/cli-repl/src/async-repl.ts index d44846810d..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); @@ -65,7 +70,7 @@ export function start(opts: AsyncREPLOptions): REPLServer { repl.emit(evalStart, { input } as EvalStartEvent); // Use public getPrompt() API once available (Node.js 15+) - const origPrompt = (repl as any).getPrompt?.() ?? (repl as any)._prompt; + const origPrompt = getPrompt(repl); repl.setPrompt(''); // Disable printing prompts while we're evaluating code. try { @@ -120,7 +125,9 @@ export function start(opts: AsyncREPLOptions): REPLServer { (replSigint as any)?.restore?.(); (processSigint as any)?.restore?.(); - repl.setPrompt(origPrompt); + if (getPrompt(repl) === '') { + repl.setPrompt(origPrompt); + } repl.removeListener('exit', exitListener); for (const listener of previousExitListeners) {