Fix incorrect cursor movement
ADD
packages/cli-reporter/stream.test.md
+# `stream.test.ts`
+
+**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/cli-reporter/stream.test.ts --update-snapshots` to update.
+
+## `nextLineInsertLeadingNewline will insert newline on next log`
+
+### `0 raw`
+
+```
+1
+```
+
+### `0 state`
+
+```javascript
+Object {
+ currentLine: 0
+ leadingNewline: false
+ lineSnapshots: Map []
+ nextLineInsertLeadingNewline: true
+ buffer: Array ["1"]
+}
+```
+
+### `final raw`
+
+```
+1
+2
+
+```
+
+### `final state`
+
+```javascript
+Object {
+ currentLine: 2
+ leadingNewline: true
+ lineSnapshots: Map []
+ nextLineInsertLeadingNewline: false
+ buffer: Array [
+ "1"
+ "2"
+ ]
+}
+```
+
+## `removes higher line`
+
+### `final raw`
+
+```
+1
+2
+5
+3
+4
+[4A[1G[1B[1G[2K3[1B[1G[2K4[1B[1G[2K
+```
+
+### `final state`
+
+```javascript
+Object {
+ currentLine: 4
+ leadingNewline: true
+ lineSnapshots: Map [
+ Array [
+ Object {close: Function close}
+ 1
+ ]
+ ]
+ nextLineInsertLeadingNewline: false
+ buffer: Array [
+ "1"
+ "2"
+ "3"
+ "4"
+ ]
+}
+```
+
+## `removes same line`
+
+### `final raw`
+
+```
+remove me[1G[2K
+```
+
+### `final state`
+
+```javascript
+Object {
+ currentLine: 0
+ leadingNewline: false
+ lineSnapshots: Map [
+ Array [
+ Object {close: Function close}
+ 0
+ ]
+ ]
+ nextLineInsertLeadingNewline: false
+ buffer: Array [""]
+}
+```
+
+## `replaces higher line`
+
+### `final raw`
+
+```
+1
+2
+5
+4
+[2A[1G[2K3[2B[1G
+```
+
+### `final state`
+
+```javascript
+Object {
+ currentLine: 4
+ leadingNewline: true
+ lineSnapshots: Map [
+ Array [
+ Object {close: Function close}
+ 2
+ ]
+ ]
+ nextLineInsertLeadingNewline: false
+ buffer: Array [
+ "1"
+ "2"
+ "3"
+ "4"
+ ]
+}
+```
+
+## `replaces same line`
+
+### `final raw`
+
+```
+remove me[1G[2Kok i did it
+```
+
+### `final state`
+
+```javascript
+Object {
+ currentLine: 0
+ leadingNewline: false
+ lineSnapshots: Map [
+ Array [
+ Object {close: Function close}
+ 0
+ ]
+ ]
+ nextLineInsertLeadingNewline: false
+ buffer: Array ["ok i did it"]
+}
+```

ADD
packages/cli-reporter/stream.test.ts
+import {ReporterStreamAttached} from "./types";
+import {DEFAULT_TERMINAL_FEATURES} from "@romefrontend/cli-environment";
+import {TestHelper, test} from "rome";
+import Reporter from "./Reporter";
+import {markup} from "@romefrontend/cli-layout";
+
+type StreamTestHelper = {
+ reporter: Reporter;
+ stream: ReporterStreamAttached;
+ intermediateSnapshot(): void;
+};
+
+function createStreamTest(callback: (helper: StreamTestHelper) => void) {
+ return (t: TestHelper) => {
+ let buff = "";
+
+ const reporter = new Reporter();
+
+ const {stream} = reporter.addStream({
+ format: "ansi",
+ features: {
+ ...DEFAULT_TERMINAL_FEATURES,
+ cursor: true,
+ },
+ write(chunk) {
+ buff += chunk;
+ },
+ });
+
+ let count = 0;
+
+ function intermediateSnapshot(prefix: string = String(count++)) {
+ t.namedSnapshot(`${prefix} raw`, buff);
+ t.namedSnapshot(`${prefix} state`, stream.state);
+ }
+
+ callback({reporter, stream, intermediateSnapshot});
+ intermediateSnapshot("final");
+ };
+}
+
+test(
+ "removes same line",
+ createStreamTest(({reporter}) => {
+ const lineSnapshot = reporter.getLineSnapshot();
+ reporter.log(
+ markup`remove me`,
+ {
+ // Wont have advanced to the next line
+ noNewline: true,
+ },
+ );
+ reporter.removeLine(lineSnapshot);
+ }),
+);
+
+test(
+ "removes higher line",
+ createStreamTest(({reporter}) => {
+ reporter.log(markup`1`);
+ reporter.log(markup`2`);
+ const lineSnapshot = reporter.getLineSnapshot();
+ reporter.log(markup`5`);
+ reporter.log(markup`3`);
+ reporter.log(markup`4`);
+ reporter.removeLine(lineSnapshot);
+ }),
+);
+
+test(
+ "replaces same line",
+ createStreamTest(({reporter}) => {
+ const lineSnapshot = reporter.getLineSnapshot();
+ reporter.log(
+ markup`remove me`,
+ {
+ // Wont have advanced to the next line
+ noNewline: true,
+ },
+ );
+ reporter.log(
+ markup`ok i did it`,
+ {
+ replaceLineSnapshot: lineSnapshot,
+ },
+ );
+ }),
+);
+
+test(
+ "replaces higher line",
+ createStreamTest(({reporter}) => {
+ reporter.log(markup`1`);
+ reporter.log(markup`2`);
+ const lineSnapshot = reporter.getLineSnapshot();
+ reporter.log(markup`5`);
+ reporter.log(markup`4`);
+ reporter.log(
+ markup`3`,
+ {
+ replaceLineSnapshot: lineSnapshot,
+ },
+ );
+ }),
+);
+
+test(
+ "nextLineInsertLeadingNewline will insert newline on next log",
+ createStreamTest(({reporter, intermediateSnapshot}) => {
+ reporter.log(
+ markup`1`,
+ {
+ preferNoNewline: true,
+ },
+ );
+ intermediateSnapshot();
+ reporter.log(markup`2`);
+ }),
+);

MODIFY
packages/cli-reporter/stream.ts
packages/cli-reporter/stream.ts
@@ -6,6 +6,15 @@ import {
} from "./types";
import {LogOptions} from "./Reporter";
import {ansiEscapes} from "@romefrontend/cli-layout";
+import {
+ Number0,
+ ob1Add,
+ ob1Dec,
+ ob1Get0,
+ ob1Inc,
+ ob1Number0,
+ ob1Sub,
+} from "@romefrontend/ob1";
export function getLeadingNewlineCount({state}: ReporterStreamAttached): number {
if (!state.leadingNewline) {
@@ -26,17 +35,16 @@ export function getLeadingNewlineCount({state}: ReporterStreamAttached): number
function calculateBufferPosition(
{state}: ReporterStreamAttached,
- targetLine: number,
+ targetLine: Number0,
): {
lineDiff: number;
bufferIndex: number;
} {
- let lineDiff = state.currentLine - targetLine;
+ let lineDiff = ob1Get0(ob1Sub(state.currentLine, targetLine));
let bufferIndex = state.buffer.length - lineDiff;
if (!state.leadingNewline) {
bufferIndex--;
- lineDiff--;
}
return {lineDiff, bufferIndex};
@@ -72,11 +80,11 @@ export function removeLine(
// Update snapshots
for (const [snapshot, line] of stream.state.lineSnapshots) {
- stream.state.lineSnapshots.set(snapshot, line - 1);
+ stream.state.lineSnapshots.set(snapshot, ob1Dec(line));
}
// Update line since we've shifted at least one
- stream.state.currentLine--;
+ stream.state.currentLine = ob1Dec(stream.state.currentLine);
// Go to the line right above where we want to remove
stream.write(ansiEscapes.cursorUp(lineDiff + 1), false);
@@ -97,7 +105,7 @@ export function removeLine(
export function createStreamState(): ReporterStreamState {
return {
lineSnapshots: new Map(),
- currentLine: 0,
+ currentLine: ob1Number0,
leadingNewline: false,
buffer: [],
nextLineInsertLeadingNewline: false,
@@ -125,7 +133,7 @@ export function log(
);
pushBuffer = true;
} else if (isANSICursorStream(stream)) {
- replaceLine += lineOffset;
+ replaceLine = ob1Add(replaceLine, lineOffset);
logReplace(stream, msg, replaceLine, stderr);
return;
}
@@ -185,14 +193,14 @@ function clearCurrentLine(stream: ReporterStreamAttached) {
function newline(stream: ReporterStreamAttached, stderr: boolean) {
stream.state.leadingNewline = true;
- stream.state.currentLine++;
+ stream.state.currentLine = ob1Inc(stream.state.currentLine);
stream.write("\n", stderr);
}
function logReplace(
stream: ReporterStreamAttached,
msg: string,
- targetLine: number,
+ targetLine: Number0,
stderr: boolean,
) {
const {lineDiff, bufferIndex} = calculateBufferPosition(stream, targetLine);

MODIFY
packages/cli-reporter/types.ts
packages/cli-reporter/types.ts
import {Event} from "@romefrontend/events";
import {TerminalFeatures} from "@romefrontend/cli-environment";
import {AnyMarkup, Markup} from "@romefrontend/cli-layout";
+import {Number0} from "@romefrontend/ob1";
export type SelectOption = {
label: Markup;
@@ -35,8 +36,8 @@ export type ReporterStreamLineSnapshot = {
};
export type ReporterStreamState = {
- lineSnapshots: Map<ReporterStreamLineSnapshot, number>;
- currentLine: number;
+ lineSnapshots: Map<ReporterStreamLineSnapshot, Number0>;
+ currentLine: Number0;
buffer: Array<string>;
leadingNewline: boolean;
nextLineInsertLeadingNewline: boolean;

Fix incorrect cursor movement (#889)