Fix cursor movement on Windows

This commit is contained in:
Andras Schmelczer 2025-04-03 21:44:45 +01:00
commit 5328e3b0f6
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
4 changed files with 30 additions and 38 deletions

View file

@ -19,10 +19,9 @@ describe("lineAndColumnToPosition", () => {
expect(position).toBe(0); expect(position).toBe(0);
}); });
it("should handle a single-line string correctly", () => { it("with carrige return", () => {
const text = "SingleLine"; expect(lineAndColumnToPosition("a\nb", 1, 1)).toBe(3);
const position = lineAndColumnToPosition(text, 0, 5); expect(lineAndColumnToPosition("a\r\nb", 1, 1)).toBe(3);
expect(position).toBe(5);
}); });
it("should handle multi-line strings with varying lengths", () => { it("should handle multi-line strings with varying lengths", () => {

View file

@ -13,7 +13,7 @@ export function lineAndColumnToPosition(
line: number, line: number,
column: number column: number
): number { ): number {
const lines = text.split("\n"); const lines = text.replace("\r", "").split("\n");
if (line >= lines.length) { if (line >= lines.length) {
throw new Error(`Line number ${line} is out of range.`); throw new Error(`Line number ${line} is out of range.`);

View file

@ -1,63 +1,55 @@
import { positionToLineAndColumn } from "./position-to-line-and-column"; import { positionToLineAndColumn } from "./position-to-line-and-column";
describe("positionToLineAndColumn", () => { describe("positionToLineAndColumn", () => {
test("converts position to line and column in a single line text", () => {
const text = "Hello, world!";
expect(positionToLineAndColumn(text, 0)).toEqual({
line: 0,
column: 1
});
expect(positionToLineAndColumn(text, 7)).toEqual({
line: 0,
column: 8
});
expect(positionToLineAndColumn(text, 12)).toEqual({
line: 0,
column: 13
});
});
test("converts position to line and column in multi-line text", () => { test("converts position to line and column in multi-line text", () => {
const text = "First line\nSecond line\nThird line"; const text = "ab\ncd\n";
expect(positionToLineAndColumn(text, 0)).toEqual({ expect(positionToLineAndColumn(text, 0)).toEqual({
line: 0,
column: 0
});
expect(positionToLineAndColumn(text, 1)).toEqual({
line: 0, line: 0,
column: 1 column: 1
}); });
expect(positionToLineAndColumn(text, 10)).toEqual({ expect(positionToLineAndColumn(text, 2)).toEqual({
line: 0, line: 0,
column: 11 column: 2
}); });
expect(positionToLineAndColumn(text, 15)).toEqual({ expect(positionToLineAndColumn(text, 3)).toEqual({
line: 1, line: 1,
column: 5 column: 0
}); });
expect(positionToLineAndColumn(text, 26)).toEqual({ expect(positionToLineAndColumn(text, 4)).toEqual({
line: 1,
column: 1
});
expect(positionToLineAndColumn(text, 6)).toEqual({
line: 2, line: 2,
column: 4 column: 0
}); });
}); });
test("handles positions at line breaks", () => { test("with carrige returns", () => {
const text = "Line\nBreak"; expect(positionToLineAndColumn("a\nb", 3)).toEqual({
expect(positionToLineAndColumn(text, 4)).toEqual({ line: 1,
line: 0, column: 1
column: 5
}); });
expect(positionToLineAndColumn(text, 5)).toEqual({
expect(positionToLineAndColumn("a\r\nb", 3)).toEqual({
line: 1, line: 1,
column: 1 column: 1
}); });
}); });
test("handles empty input", () => { test("handles empty input", () => {
expect(positionToLineAndColumn("", 0)).toEqual({ line: 0, column: 1 }); expect(positionToLineAndColumn("", 0)).toEqual({ line: 0, column: 0 });
}); });
test("handles positions at the end of text", () => { test("handles positions at the end of text", () => {
const text = "End"; const text = "End";
expect(positionToLineAndColumn(text, 3)).toEqual({ expect(positionToLineAndColumn(text, 3)).toEqual({
line: 0, line: 0,
column: 4 column: 3
}); });
}); });

View file

@ -3,7 +3,7 @@
* *
* @param text The text content to analyze * @param text The text content to analyze
* @param position The character position to convert * @param position The character position to convert
* @returns An object containing line and column numbers (0-based index for line, 1-based index for column) * @returns An object containing line and column numbers
* @throws Will throw an error if the position is negative or exceeds the text length * @throws Will throw an error if the position is negative or exceeds the text length
*/ */
export function positionToLineAndColumn( export function positionToLineAndColumn(
@ -20,11 +20,12 @@ export function positionToLineAndColumn(
); );
} }
text = text.replace("\r", "");
const textUpToPosition = text.substring(0, position); const textUpToPosition = text.substring(0, position);
const lines = textUpToPosition.split("\n"); const lines = textUpToPosition.split("\n");
const line = lines.length - 1; // 0-based index const line = lines.length - 1;
const column = lines[lines.length - 1].length + 1; // 1-based index const column = lines[lines.length - 1].length;
return { line, column }; return { line, column };
} }