fix(hashline): prevented terminal newline from exposing editable blank line
- Prevented `formatNumberedLines` from appending a synthetic empty line when encountering a terminal newline. - Added tests to ensure trailing newlines do not generate addressable blank lines.
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Stopped `formatNumberedLines` from exposing a terminal newline as an editable blank line; deleting that synthetic row previously produced a misleading no-op.
|
||||
|
||||
### Added
|
||||
|
||||
- Post-apply parse advisory: when the applied result stops parsing while the pre-edit content parsed, the response now carries a warning naming the first changed line. This catches balance-neutral misplacements — a statement swapped onto the wrong line number leaves no delimiter anomaly for the repair heuristics — which previously applied with zero feedback and surfaced only at the next compile.
|
||||
|
||||
@@ -139,8 +139,13 @@ export function formatNumberedLine(lineNumber: number, line: string): string {
|
||||
return `${lineNumber}${HL_LINE_BODY_SEP}${line}`;
|
||||
}
|
||||
|
||||
/** Format file text with hashline-mode line-number prefixes for display. */
|
||||
/**
|
||||
* Format file text with hashline-mode line-number prefixes for display.
|
||||
* A terminal newline terminates the preceding line; it is not an addressable
|
||||
* blank line.
|
||||
*/
|
||||
export function formatNumberedLines(text: string, startLine = 1): string {
|
||||
const lines = text.split("\n");
|
||||
if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
||||
return lines.map((line, i) => formatNumberedLine(startLine + i, line)).join("\n");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { applyEdits, parseLid, parsePatch, parsePatchStreaming, Tokenizer } from "@oh-my-pi/hashline";
|
||||
import {
|
||||
applyEdits,
|
||||
formatNumberedLines,
|
||||
parseLid,
|
||||
parsePatch,
|
||||
parsePatchStreaming,
|
||||
Tokenizer,
|
||||
} from "@oh-my-pi/hashline";
|
||||
|
||||
function applyPatch(text: string, diff: string): string {
|
||||
return applyEdits(text, parsePatch(diff).edits).text;
|
||||
@@ -98,6 +105,11 @@ describe("hashline format v4", () => {
|
||||
expect(applyEdits("a\nb\n", edits).text).toBe("a\nb\n");
|
||||
});
|
||||
|
||||
it("does not expose the terminal newline as an editable blank line", () => {
|
||||
expect(formatNumberedLines("a\nb\n")).toBe("1:a\n2:b");
|
||||
expect(formatNumberedLines("a\nb\n\n")).toBe("1:a\n2:b\n3:");
|
||||
});
|
||||
|
||||
it("treats a cut range ending at the trailing sentinel as ending at the last real line", () => {
|
||||
const edits = parsePatch("CUT 2-3").edits;
|
||||
expect(applyEdits("a\nb\n", edits).text).toBe("a\n");
|
||||
|
||||
Reference in New Issue
Block a user