diff --git a/package.json b/package.json index 065a88ddc..eb2e06e9c 100644 --- a/package.json +++ b/package.json @@ -964,6 +964,11 @@ "command": "paredit.pushSexprRight", "title": "Push Sexp Right" }, + { + "category": "Calva Paredit", + "command": "paredit.pushSexprBackwardUp", + "title": "Push Sexp Backward Up" + }, { "category": "Calva Paredit", "command": "paredit.convolute", diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index 224243666..683fd7e12 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -625,4 +625,22 @@ export function pushSexprRight(doc: EditableDocument, start = doc.selectionLeft, if (forwardRange[0] !== currentRange[0]) { // there is a sexp to the right transpose(doc, start, currentRange[1], { fromRight: newPosOffset }); } +} + +export function pushSexprBackwardUp(doc: EditableDocument, start = doc.selectionLeft, end = doc.selectionRight) { + if (start == end) { + const p = start, + cursor = doc.getTokenCursor(p), + currentRange = cursor.rangeForCurrentForm(p), + currentText = doc.model.getText(...currentRange), + currentListRange = cursor.rangeForList(); + if (currentListRange !== undefined) { + const newPosOffset = p - currentRange[0], + newCursorPos = currentListRange[0] + newPosOffset; + doc.model.edit([ + new ModelEdit('deleteRange', [currentRange[0], currentRange[1] - currentRange[0]]), + new ModelEdit('insertString', [currentListRange[0], currentText, [p, p], [newCursorPos, newCursorPos]]) + ], { selection: new ModelEditSelection(newCursorPos) }); + } + } } \ No newline at end of file diff --git a/src/cursor-doc/token-cursor.ts b/src/cursor-doc/token-cursor.ts index 38b94dbce..1c5c4f7a8 100644 --- a/src/cursor-doc/token-cursor.ts +++ b/src/cursor-doc/token-cursor.ts @@ -343,7 +343,7 @@ export class LispTokenCursor extends TokenCursor { * Finds the range of the current list. If you are particular about which type of list, supply the `openingBracket` * @param openingBracket */ - rangeForList(openingBracket?: string): [[number, number], [number, number]] { + rangeForList(openingBracket?: string): [number, number] { const cursor = this.clone(); if (openingBracket === undefined) { if (!(cursor.backwardList() && cursor.backwardUpList())) { @@ -354,11 +354,11 @@ export class LispTokenCursor extends TokenCursor { return undefined; } } - const start = cursor.rowCol as [number, number]; + const start = cursor.offsetStart; if (!cursor.forwardSexp()) { return undefined; } - const end = cursor.rowCol as [number, number]; + const end = cursor.offsetEndß; return [start, end] } diff --git a/src/paredit/extension.ts b/src/paredit/extension.ts index 4fb53c4fb..4ade848af 100644 --- a/src/paredit/extension.ts +++ b/src/paredit/extension.ts @@ -193,6 +193,11 @@ const pareditCommands: PareditCommand[] = [ handler: paredit.pushSexprRight, replWindowCommand: "push-sexp-right" }, + { + command: 'paredit.pushSexprBackwardUp', + handler: paredit.pushSexprBackwardUp, + replWindowCommand: "push-sexp-backward-up" + }, { command: 'paredit.convolute', handler: paredit.convolute, diff --git a/src/webview/repl-console.ts b/src/webview/repl-console.ts index 3c461f972..a2665e541 100644 --- a/src/webview/repl-console.ts +++ b/src/webview/repl-console.ts @@ -364,6 +364,12 @@ export class ReplConsole { // this.readline.repaint(); // }); }, + "push-sexp-backward-up": () => { + this.readline.withUndo(() => { + paredit.pushSexprBackwardUp(this.readline); + this.readline.repaint(); + }); + }, "convolute-sexp": () => { console.warn("Convolute is disabled in the REPL window, because: https://github.com/BetterThanTomorrow/calva/issues/490"); // this.readline.withUndo(() => {