Skip to content

Commit 49ee08d

Browse files
committed
implement minimal update logic
1 parent eab6ef0 commit 49ee08d

File tree

1 file changed

+43
-7
lines changed

1 file changed

+43
-7
lines changed

src/log-update.ts

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,63 @@ const create = (stream: Writable, {showCursor = false} = {}): LogUpdate => {
1313
let previousOutput = '';
1414
let hasHiddenCursor = false;
1515

16+
function clear(): void {
17+
stream.write(ansiEscapes.eraseLines(previousLineCount));
18+
previousOutput = '';
19+
previousLineCount = 0;
20+
}
21+
1622
const render = (str: string) => {
1723
if (!showCursor && !hasHiddenCursor) {
1824
cliCursor.hide();
1925
hasHiddenCursor = true;
2026
}
2127

28+
if (str === '') {
29+
clear();
30+
return;
31+
}
32+
2233
const output = str + '\n';
2334
if (output === previousOutput) {
2435
return;
2536
}
2637

38+
const prevLines = previousOutput.split('\n');
39+
const newLines = output.split('\n');
40+
const newLinesCount = newLines.length;
41+
let updateSequence = '';
42+
43+
// If new output is shorter than previous output, erase the extra lines.
44+
const numExtraOldLines = previousLineCount - newLinesCount;
45+
if (numExtraOldLines > 0) {
46+
// Note eraseLines() erases upwards.
47+
updateSequence += ansiEscapes.eraseLines(numExtraOldLines);
48+
}
49+
50+
// Move back up to the start of previous output.
51+
updateSequence +=
52+
ansiEscapes.cursorUp(previousLineCount) + ansiEscapes.cursorLeft;
53+
54+
newLines.forEach((newLine, index) => {
55+
if (newLine !== prevLines[index]) {
56+
updateSequence += newLine + ansiEscapes.eraseEndLine;
57+
}
58+
59+
if (index < newLinesCount - 1) {
60+
// Note this could be more efficient if we used cursorDown() to move
61+
// multiple lines at once.
62+
updateSequence += ansiEscapes.cursorNextLine;
63+
}
64+
});
65+
66+
stream.write(updateSequence);
67+
2768
previousOutput = output;
28-
stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
29-
previousLineCount = output.split('\n').length;
69+
previousLineCount = newLinesCount;
3070
};
3171

32-
render.clear = () => {
33-
stream.write(ansiEscapes.eraseLines(previousLineCount));
34-
previousOutput = '';
35-
previousLineCount = 0;
36-
};
72+
render.clear = clear;
3773

3874
render.done = () => {
3975
previousOutput = '';

0 commit comments

Comments
 (0)