Skip to content

Commit

Permalink
refactor: neovim edit()
Browse files Browse the repository at this point in the history
  • Loading branch information
Cedric Halbronn committed Mar 21, 2024
1 parent 3704361 commit b91758d
Showing 1 changed file with 84 additions and 68 deletions.
152 changes: 84 additions & 68 deletions packages/cursorless-neovim/src/ide/neovim/NeovimEdit.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Edit } from "@cursorless/common";
import { Edit, Position, Range } from "@cursorless/common";
import { Window } from "neovim";
import { updateTextEditor } from "../../neovimHelpers";
import { neovimContext } from "../../singletons/context.singleton";
Expand All @@ -7,9 +7,6 @@ export default async function neovimEdit(
editor: Window,
edits: Edit[],
): Promise<boolean> {
const client = neovimContext().client;
const buffer = await client.window.buffer;

// TODO: bring row three after four (test it)

// We start applying the edits from the end of the document
Expand All @@ -24,77 +21,96 @@ export default async function neovimEdit(

for (const edit of edits) {
const { range, text, isReplace } = edit;
// Uniform newlines so we can easily split
const newlines = text.replace(/(?:\r\n|\r|\n)/g, "\n").split("\n");

if (text === "") {
// --- Delete

// only keep the end of the last line
const lastLine = (
await buffer.getLines({
start: range.end.line,
end: range.end.line + 1,
strictIndexing: true,
})
)[0];
const endOfLastLine = lastLine.slice(range.end.character);

// are we only modifying one line?
if (range.start.line === range.end.line) {
// only keep the beginning and end of the line
const singleLine =
lastLine.slice(0, range.start.character) + endOfLastLine;
// update that single line
await buffer.setLines(singleLine, {
start: range.start.line,
end: range.start.line + 1,
strictIndexing: true,
});
} else {
if (range.start.character === 0) {
// if we are deleting from the start of the first line, we need to exclude the first line
await buffer.setLines(endOfLastLine, {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
} else {
// only keep the beginning of the first line
const firstLine = (
await buffer.getLines({
start: range.start.line,
end: range.start.line + 1,
strictIndexing: true,
})
)[0];
const startOfFirstLine = firstLine.slice(0, range.start.character);
if (range.start.character === firstLine.length) {
// if we are deleting from the end of the first line, we need to append the last line to the first line
await buffer.setLines(startOfFirstLine + endOfLastLine, {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
continue;
}
await buffer.setLines([startOfFirstLine, endOfLastLine], {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
}
}
await neovimDelete(range);
} else if (range.isEmpty && !isReplace) {
// --- Insert
throw Error("neovimEdit(): Insert not implemented");
await neovimInsert(range.start, text);
} else {
// --- Replace
throw Error("neovimEdit(): Replace not implemented");
await neovimReplace(range, text);
}
}

// TODO: update our view of the TextEditor/TextDocument
await updateTextEditor();
return true;
}

async function neovimDelete(range: Range): Promise<void> {
const client = neovimContext().client;
const buffer = await client.window.buffer;

// only keep the end of the last line
const lastLine = (
await buffer.getLines({
start: range.end.line,
end: range.end.line + 1,
strictIndexing: true,
})
)[0];
const endOfLastLine = lastLine.slice(range.end.character);

// are we only modifying one line?
if (range.start.line === range.end.line) {
// only keep the beginning and end of the line
const singleLine = lastLine.slice(0, range.start.character) + endOfLastLine;
// update that single line
await buffer.setLines(singleLine, {
start: range.start.line,
end: range.start.line + 1,
strictIndexing: true,
});
return;
}

// we are modifying multiple lines

// are we not including the beginning of the first line?
if (range.start.character === 0) {
// if we are deleting from the start of the first line, we need to exclude the first line
await buffer.setLines(endOfLastLine, {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
return;
}

// only keep the beginning of the first line
const firstLine = (
await buffer.getLines({
start: range.start.line,
end: range.start.line + 1,
strictIndexing: true,
})
)[0];
const startOfFirstLine = firstLine.slice(0, range.start.character);

// are we not including the newline at the end of the first line?
if (range.start.character === firstLine.length) {
// if we are deleting from the end of the first line, we need to append the last line to the first line
await buffer.setLines(startOfFirstLine + endOfLastLine, {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
return;
}

await buffer.setLines([startOfFirstLine, endOfLastLine], {
start: range.start.line,
end: range.end.line + 1,
strictIndexing: true,
});
}

function neovimInsert(position: Position, text: string) {
// Uniform newlines so we can easily split
const newlines = text.replace(/(?:\r\n|\r|\n)/g, "\n").split("\n");
throw Error("neovimEdit(): Insert not implemented");
}

function neovimReplace(range: Range, text: string) {
// Uniform newlines so we can easily split
const newlines = text.replace(/(?:\r\n|\r|\n)/g, "\n").split("\n");
throw Error("neovimEdit(): Replace not implemented");
}

0 comments on commit b91758d

Please sign in to comment.