diff --git a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts b/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts index dd422d3f0e6fd..a299811803f92 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts @@ -682,7 +682,7 @@ export class CurrentActivityPrinter extends ActivityPrinterBase { // Display in the same block space, otherwise we're going to have silly empty lines. this.block.displayLines(lines); - this.block.removeEmptyLines(lines); + this.block.removeEmptyLines(); } private progressBar(width: number) { @@ -745,7 +745,7 @@ function colorFromStatusActivity(status?: string) { return chalk.red; } - if (status.startsWith('CREATE_') || status.startsWith('UPDATE_')) { + if (status.startsWith('CREATE_') || status.startsWith('UPDATE_') || status.startsWith('IMPORT_')) { return chalk.green; } // For stacks, it may also be 'UPDDATE_ROLLBACK_IN_PROGRESS' diff --git a/packages/aws-cdk/lib/api/util/display.ts b/packages/aws-cdk/lib/api/util/display.ts index a7071ed6a12a4..44e5b6c9fb1c0 100644 --- a/packages/aws-cdk/lib/api/util/display.ts +++ b/packages/aws-cdk/lib/api/util/display.ts @@ -7,6 +7,7 @@ const wrapAnsi = require('wrap-ansi'); */ export class RewritableBlock { private lastHeight = 0; + private trailingEmptyLines = 0; constructor(private readonly stream: NodeJS.WriteStream) { } @@ -22,14 +23,18 @@ export class RewritableBlock { } public displayLines(lines: string[]) { - lines = terminalWrap(this.width, expandNewlines(lines)).slice(0, getMaxBlockHeight(this.height, this.lastHeight, lines)); + lines = terminalWrap(this.width, expandNewlines(lines)); + lines = lines.slice(0, getMaxBlockHeight(this.height, this.lastHeight, lines)); this.stream.write(cursorUp(this.lastHeight)); for (const line of lines) { this.stream.write(cll() + line + '\n'); } + + this.trailingEmptyLines = Math.max(0, this.lastHeight - lines.length); + // Clear remainder of unwritten lines - for (let i = 0; i < this.lastHeight - lines.length; i++) { + for (let i = 0; i < this.trailingEmptyLines; i++) { this.stream.write(cll() + '\n'); } @@ -37,8 +42,8 @@ export class RewritableBlock { this.lastHeight = Math.max(this.lastHeight, lines.length); } - public removeEmptyLines(lines: string[]) { - this.stream.write(cursorUp(this.lastHeight - lines.length)); + public removeEmptyLines() { + this.stream.write(cursorUp(this.trailingEmptyLines)); } } @@ -62,26 +67,18 @@ function cll() { function terminalWrap(width: number | undefined, lines: string[]) { if (width === undefined) { return lines; } - const ret = new Array(); - for (const line of lines) { - ret.push(...wrapAnsi(line, width - 1, { - hard: true, - trim: true, - wordWrap: false, - }).split('\n')); - } - return ret; + return lines.flatMap(line => wrapAnsi(line, width - 1, { + hard: true, + trim: true, + wordWrap: false, + }).split('\n')); } /** * Make sure there are no hidden newlines in the gin strings */ function expandNewlines(lines: string[]): string[] { - const ret = new Array(); - for (const line of lines) { - ret.push(...line.split('\n')); - } - return ret; + return lines.flatMap(line => line.split('\n')); } function getMaxBlockHeight(windowHeight: number | undefined, lastHeight: number, lines: string[]): number { diff --git a/packages/aws-cdk/test/api/util/display.test.ts b/packages/aws-cdk/test/api/util/display.test.ts index 26b54b736b104..4d116078f18df 100644 --- a/packages/aws-cdk/test/api/util/display.test.ts +++ b/packages/aws-cdk/test/api/util/display.test.ts @@ -36,4 +36,27 @@ describe('Rewritable Block Tests', () => { expect(output.length).toEqual(6); }); + + test('display accounts for newlines in output', () => { + const output = stderr.inspectSync(() => { + block.displayLines(['before\nafter']); + }); + expect(output.length).toEqual(3); // cursorup + 2 lines + }); + + test('removeEmptyLines only removes trailing lines', () => { + stderr.inspectSync(() => { + block.displayLines(Array.from(Array(5).keys()).map(x => `${x}`)); + }); + stderr.inspectSync(() => { + // Leaves 3 empty lines + block.displayLines(Array.from(Array(2).keys()).map(x => `${x}`)); + }); + + const output = stderr.inspectSync(() => { + block.removeEmptyLines(); + }); + const expectedEmptyLines = 3; + expect(JSON.stringify(output)).toEqual(JSON.stringify([`\u001b[${expectedEmptyLines}A`])); + }); }); \ No newline at end of file