Skip to content

Commit 64f726a

Browse files
committed
fix(@clack/prompts): collapse carriage returns in line-based taskLog output
1 parent e53d32c commit 64f726a

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

packages/prompts/src/task-log.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ const appendRawMessage = (input: string, msg: string, prependNewline: boolean):
5959
return next;
6060
};
6161

62+
const collapseCarriageReturnUpdates = (input: string): string => {
63+
return input
64+
.split('\n')
65+
.map((line) => line.slice(line.lastIndexOf('\r') + 1))
66+
.join('\n');
67+
};
68+
6269
/**
6370
* Renders a log which clears on success and remains on failure
6471
*/
@@ -170,7 +177,7 @@ export const taskLog = (opts: TaskLogOptions) => {
170177
if (buffer.value !== '') {
171178
buffer.value += '\n';
172179
}
173-
buffer.value += sanitized;
180+
buffer.value += collapseCarriageReturnUpdates(sanitized);
174181
lastMessageWasRaw = false;
175182
}
176183
if (opts.limit !== undefined) {

packages/prompts/test/task-log.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,23 @@ describe.each(['true', 'false'])('taskLog (isCI = %s)', (isCI) => {
134134
expect(output.buffer).toMatchSnapshot();
135135
});
136136

137+
test('raw = false keeps only the last carriage return update when success shows the log', async () => {
138+
const log = prompts.taskLog({
139+
input,
140+
output,
141+
title: 'foo',
142+
});
143+
144+
log.message('◒ Cloning repository\r◐ Cloning repository\r◓ Cloning repository\r◇ Repository cloned');
145+
log.success('done!', { showLog: true });
146+
147+
const renderedLog = output.buffer.at(-1);
148+
expect(renderedLog).toContain('◇ Repository cloned');
149+
expect(renderedLog).not.toContain('◒ Cloning repository');
150+
expect(renderedLog).not.toContain('◐ Cloning repository');
151+
expect(renderedLog).not.toContain('◓ Cloning repository');
152+
});
153+
137154
test('prints empty lines', async () => {
138155
const log = prompts.taskLog({
139156
input,
@@ -225,6 +242,24 @@ describe.each(['true', 'false'])('taskLog (isCI = %s)', (isCI) => {
225242

226243
expect(output.buffer).toMatchSnapshot();
227244
});
245+
246+
test('raw = false keeps only the last carriage return update on error', () => {
247+
const log = prompts.taskLog({
248+
input,
249+
output,
250+
title: 'foo',
251+
});
252+
253+
log.message('◒ Cloning repository\r◐ Cloning repository\r◓ Cloning repository\r◇ Repository cloned');
254+
255+
log.error('some error!');
256+
257+
const renderedLog = output.buffer.at(-1);
258+
expect(renderedLog).toContain('◇ Repository cloned');
259+
expect(renderedLog).not.toContain('◒ Cloning repository');
260+
expect(renderedLog).not.toContain('◐ Cloning repository');
261+
expect(renderedLog).not.toContain('◓ Cloning repository');
262+
});
228263
});
229264

230265
describe('success', () => {

0 commit comments

Comments
 (0)