From b91758dddf70e9a2df698d7054eb8800603f802d Mon Sep 17 00:00:00 2001 From: Cedric Halbronn Date: Thu, 21 Mar 2024 16:26:23 +0000 Subject: [PATCH] refactor: neovim edit() --- .../src/ide/neovim/NeovimEdit.ts | 152 ++++++++++-------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/packages/cursorless-neovim/src/ide/neovim/NeovimEdit.ts b/packages/cursorless-neovim/src/ide/neovim/NeovimEdit.ts index 2d6e671035..e0a417e1b2 100644 --- a/packages/cursorless-neovim/src/ide/neovim/NeovimEdit.ts +++ b/packages/cursorless-neovim/src/ide/neovim/NeovimEdit.ts @@ -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"; @@ -7,9 +7,6 @@ export default async function neovimEdit( editor: Window, edits: Edit[], ): Promise { - 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 @@ -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 { + 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"); +}