diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..e6ce25b7b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "hbenl.vscode-mocha-test-adapter"] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index a74aac81a..9fb1aad79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Changes to Calva. ## [Unreleased] +- Refactor some internal document and selection APIs in preparation for multiple selections, addressing [#610](https://github.com/BetterThanTomorrow/calva/issues/610) - [Add default Clojure associations for file extensions `.lpy`](https://github.com/BetterThanTomorrow/calva/issues/2415) ## [2.0.414] - 2024-02-24 diff --git a/src/api/ranges.ts b/src/api/ranges.ts index 15f5f7421..19b45169e 100644 --- a/src/api/ranges.ts +++ b/src/api/ranges.ts @@ -4,7 +4,7 @@ import * as getText from '../util/get-text'; const wrapSelectionAndTextFunction = ( f: (document: vscode.TextDocument, position: vscode.Position) => [vscode.Range, string] ) => { - return (editor = vscode.window.activeTextEditor, position = editor?.selection?.active) => { + return (editor = vscode.window.activeTextEditor, position = editor?.selections?.[0]?.active) => { if (editor && position && editor.document && editor.document.languageId === 'clojure') { return f(editor.document, position); } else { diff --git a/src/calva-fmt/src/format.ts b/src/calva-fmt/src/format.ts index 54dd4030c..eccbf45b7 100644 --- a/src/calva-fmt/src/format.ts +++ b/src/calva-fmt/src/format.ts @@ -32,7 +32,7 @@ export async function indentPosition(position: vscode.Position, document: vscode undoStopBefore: false, }) .then((onFulfilled) => { - editor.selection = new vscode.Selection(newPosition, newPosition); + editor.selections = [new vscode.Selection(newPosition, newPosition)]; return onFulfilled; }); } else if (delta < 0) { @@ -43,7 +43,7 @@ export async function indentPosition(position: vscode.Position, document: vscode undoStopBefore: false, }) .then((onFulfilled) => { - editor.selection = new vscode.Selection(newPosition, newPosition); + editor.selections = [new vscode.Selection(newPosition, newPosition)]; return onFulfilled; }); } @@ -103,7 +103,7 @@ export async function formatPositionInfo( extraConfig = {} ) { const doc: vscode.TextDocument = editor.document; - const index = doc.offsetAt(editor.selection.active); + const index = doc.offsetAt(editor.selections[0].active); const cursor = getDocument(doc).getTokenCursor(index); const formatRange = _calculateFormatRange(extraConfig, cursor, index); @@ -208,20 +208,24 @@ export async function formatPosition( { undoStopAfter: false, undoStopBefore: false } ) .then((onFulfilled: boolean) => { - editor.selection = new vscode.Selection( - doc.positionAt(formattedInfo.newIndex), - doc.positionAt(formattedInfo.newIndex) - ); + editor.selections = [ + new vscode.Selection( + doc.positionAt(formattedInfo.newIndex), + doc.positionAt(formattedInfo.newIndex) + ), + ]; return onFulfilled; }); } if (formattedInfo) { return new Promise((resolve, _reject) => { if (formattedInfo.newIndex != formattedInfo.previousIndex) { - editor.selection = new vscode.Selection( - doc.positionAt(formattedInfo.newIndex), - doc.positionAt(formattedInfo.newIndex) - ); + editor.selections = [ + new vscode.Selection( + doc.positionAt(formattedInfo.newIndex), + doc.positionAt(formattedInfo.newIndex) + ), + ]; } resolve(true); }); diff --git a/src/calva-fmt/src/infer.ts b/src/calva-fmt/src/infer.ts index 19bb3776c..f6f5ef3e7 100644 --- a/src/calva-fmt/src/infer.ts +++ b/src/calva-fmt/src/infer.ts @@ -23,7 +23,7 @@ interface ResultOptions { } export function inferParensCommand(editor: vscode.TextEditor) { - const position: vscode.Position = editor.selection.active, + const position: vscode.Position = editor.selections[0].active, document = editor.document, currentText = document.getText(), r: ResultOptions = inferParens({ @@ -37,7 +37,7 @@ export function inferParensCommand(editor: vscode.TextEditor) { } export function indentCommand(editor: vscode.TextEditor, spacing: string, forward: boolean = true) { - const prevPosition: vscode.Position = editor.selection.active, + const prevPosition: vscode.Position = editor.selections[0].active, document = editor.document; let deletedText = '', doEdit = true; @@ -71,7 +71,7 @@ export function indentCommand(editor: vscode.TextEditor, spacing: string, forwar ) .then((_onFulfilled: boolean) => { if (doEdit) { - const position: vscode.Position = editor.selection.active, + const position: vscode.Position = editor.selections[0].active, currentText = document.getText(), r: ResultOptions = inferIndents({ text: currentText, diff --git a/src/calva-fmt/src/providers/ontype_formatter.ts b/src/calva-fmt/src/providers/ontype_formatter.ts index adf78ca4a..d536e1876 100644 --- a/src/calva-fmt/src/providers/ontype_formatter.ts +++ b/src/calva-fmt/src/providers/ontype_formatter.ts @@ -53,7 +53,7 @@ export class FormatOnTypeEditProvider implements vscode.OnTypeFormattingEditProv } const editor = util.getActiveTextEditor(); - const pos = editor.selection.active; + const pos = editor.selections[0].active; if (formatterConfig.formatOnTypeEnabled()) { if (vscode.workspace.getConfiguration('calva.fmt').get('newIndentEngine')) { await formatter.indentPosition(pos, document); diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 137914793..df0eab5e4 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -63,7 +63,11 @@ export function printTextToRichCommentCommand(args: { [x: string]: string }) { async function printTextToRichComment(text: string, position?: number) { const doc = util.getDocument({}); const mirrorDoc = docMirror.getDocument(doc); - return paredit.addRichComment(mirrorDoc, position ? position : mirrorDoc.selection.active, text); + return paredit.addRichComment( + mirrorDoc, + position ? position : mirrorDoc.selections[0].active, + text + ); } export async function getExamplesHover( @@ -175,7 +179,7 @@ async function clojureDocsLookup( p?: vscode.Position ): Promise { const doc = d ? d : util.getDocument({}); - const position = p ? p : util.getActiveTextEditor().selection.active; + const position = p ? p : util.getActiveTextEditor().selections[0].active; const symbol = util.getWordAtPosition(doc, position); const [ns, _] = namespace.getNamespace(doc, p); const session = replSession.getSession(util.getFileType(doc)); diff --git a/src/converters.ts b/src/converters.ts index a669a8a3b..2b110e34f 100644 --- a/src/converters.ts +++ b/src/converters.ts @@ -4,7 +4,7 @@ import * as config from './config'; function getText() { const editor = vscode.window.activeTextEditor; - const selection = editor.selection; + const selection = editor.selections[0]; const doc = editor.document; return doc.getText( selection.active.isEqual(selection.anchor) diff --git a/src/cursor-doc/backspace-on-whitespace.ts b/src/cursor-doc/backspace-on-whitespace.ts index 7b4e8bc48..d70d0ffd2 100644 --- a/src/cursor-doc/backspace-on-whitespace.ts +++ b/src/cursor-doc/backspace-on-whitespace.ts @@ -10,7 +10,7 @@ export function backspaceOnWhitespace( ) { const origIndent = getIndent(doc.model, cursor.offsetStart, config); const onCloseToken = cursor.getToken().type === 'close'; - let start = doc.selection.anchor; + let start = doc.selections[0].anchor; let token = cursor.getToken(); if (token.type === 'ws') { start = cursor.offsetEnd; diff --git a/src/cursor-doc/cursor-context.ts b/src/cursor-doc/cursor-context.ts index f80a2bc19..22e5bbd83 100644 --- a/src/cursor-doc/cursor-context.ts +++ b/src/cursor-doc/cursor-context.ts @@ -15,7 +15,7 @@ export type CursorContext = typeof allCursorContexts[number]; * Returns true if documentOffset is either at the first char of the token under the cursor, or * in the whitespace between the token and the first preceding EOL, otherwise false */ -export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selection.active) { +export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selections[0].active) { const tokenCursor = doc.getTokenCursor(offset); let startOfLine = false; // only at start if we're in ws, or at the 1st char of a non-ws sexp @@ -33,7 +33,7 @@ export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selectio * Returns true if position is after the last char of the last lisp token on the line, including * any trailing whitespace or EOL, otherwise false */ -export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selection.active) { +export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selections[0].active) { const tokenCursor = doc.getTokenCursor(offset); if (tokenCursor.getToken().type === 'eol') { return true; @@ -58,7 +58,7 @@ export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selection. export function determineContexts( doc: EditableDocument, - offset = doc.selection.active + offset = doc.selections[0].active ): CursorContext[] { const tokenCursor = doc.getTokenCursor(offset); const contexts: CursorContext[] = []; diff --git a/src/cursor-doc/model.ts b/src/cursor-doc/model.ts index c6a7a5428..919dc50cc 100644 --- a/src/cursor-doc/model.ts +++ b/src/cursor-doc/model.ts @@ -36,9 +36,16 @@ export class TextLine { } export type ModelEditFunction = 'insertString' | 'changeRange' | 'deleteRange'; - -export class ModelEdit { - constructor(public editFn: ModelEditFunction, public args: any[]) {} +export type ModelEditArgs = T extends 'insertString' + ? Parameters + : T extends 'changeRange' + ? Parameters + : T extends 'deleteRange' + ? Parameters + : never; + +export class ModelEdit { + constructor(public editFn: T, public args: Readonly>) {} } /** @@ -93,7 +100,7 @@ export type ModelEditOptions = { undoStopBefore?: boolean; formatDepth?: number; skipFormat?: boolean; - selection?: ModelEditSelection; + selections?: ModelEditSelection[]; }; export interface EditableModel { @@ -104,7 +111,7 @@ export interface EditableModel { * For some EditableModel's these are performed as one atomic set of edits. * @param edits */ - edit: (edits: ModelEdit[], options: ModelEditOptions) => Thenable; + edit: (edits: ModelEdit[], options: ModelEditOptions) => Thenable; getText: (start: number, end: number, mustBeWithin?: boolean) => string; getLineText: (line: number) => string; @@ -113,7 +120,7 @@ export interface EditableModel { } export interface EditableDocument { - selection: ModelEditSelection; + selections: ModelEditSelection[]; model: EditableModel; selectionStack: ModelEditSelection[]; getTokenCursor: (offset?: number, previous?: boolean) => LispTokenCursor; @@ -365,7 +372,7 @@ export class LineInputModel implements EditableModel { * Doesn't need to be atomic in the LineInputModel. * @param edits */ - edit(edits: ModelEdit[], options: ModelEditOptions): Thenable { + edit(edits: ModelEdit[], options: ModelEditOptions): Thenable { return new Promise((resolve, reject) => { for (const edit of edits) { switch (edit.editFn) { @@ -388,8 +395,8 @@ export class LineInputModel implements EditableModel { break; } } - if (this.document && options.selection) { - this.document.selection = options.selection; + if (this.document && options.selections) { + this.document.selections = options.selections; } resolve(true); }); @@ -544,7 +551,7 @@ export class StringDocument implements EditableDocument { } } - selection: ModelEditSelection; + selections: ModelEditSelection[]; model: LineInputModel; @@ -566,16 +573,16 @@ export class StringDocument implements EditableDocument { getSelectionText: () => string; delete() { - const p = this.selection.anchor; + const p = this.selections[0].anchor; return this.model.edit([new ModelEdit('deleteRange', [p, 1])], { - selection: new ModelEditSelection(p), + selections: [new ModelEditSelection(p)], }); } backspace() { - const p = this.selection.anchor; + const p = this.selections[0].anchor; return this.model.edit([new ModelEdit('deleteRange', [p - 1, 1])], { - selection: new ModelEditSelection(p - 1), + selections: [new ModelEditSelection(p - 1)], }); } } diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index 7aca7888d..cdff9242c 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -19,21 +19,21 @@ import { currentForm } from '../api/ranges'; export async function killRange( doc: EditableDocument, range: [number, number], - start = doc.selection.anchor, - end = doc.selection.active + start = doc.selections[0].anchor, + end = doc.selections[0].active ) { const [left, right] = [Math.min(...range), Math.max(...range)]; return doc.model.edit([new ModelEdit('deleteRange', [left, right - left, [start, end]])], { - selection: new ModelEditSelection(left), + selections: [new ModelEditSelection(left)], }); } export function moveToRangeLeft(doc: EditableDocument, range: [number, number]) { - doc.selection = new ModelEditSelection(Math.min(range[0], range[1])); + doc.selections = [new ModelEditSelection(Math.min(range[0], range[1]))]; } export function moveToRangeRight(doc: EditableDocument, range: [number, number]) { - doc.selection = new ModelEditSelection(Math.max(range[0], range[1])); + doc.selections = [new ModelEditSelection(Math.max(range[0], range[1]))]; } export function selectRange(doc: EditableDocument, range: [number, number]) { @@ -41,28 +41,28 @@ export function selectRange(doc: EditableDocument, range: [number, number]) { } export function selectRangeForward(doc: EditableDocument, range: [number, number]) { - const selectionLeft = doc.selection.anchor; + const selectionLeft = doc.selections[0].anchor; const rangeRight = Math.max(range[0], range[1]); growSelectionStack(doc, [selectionLeft, rangeRight]); } export function selectRangeBackward(doc: EditableDocument, range: [number, number]) { - const selectionRight = doc.selection.anchor; + const selectionRight = doc.selections[0].anchor; const rangeLeft = Math.min(range[0], range[1]); growSelectionStack(doc, [selectionRight, rangeLeft]); } export function selectForwardSexp(doc: EditableDocument) { const rangeFn = - doc.selection.active >= doc.selection.anchor + doc.selections[0].active >= doc.selections[0].anchor ? forwardSexpRange - : (doc: EditableDocument) => forwardSexpRange(doc, doc.selection.active, true); + : (doc: EditableDocument) => forwardSexpRange(doc, doc.selections[0].active, true); selectRangeForward(doc, rangeFn(doc)); } export function selectRight(doc: EditableDocument) { const rangeFn = - doc.selection.active >= doc.selection.anchor + doc.selections[0].active >= doc.selections[0].anchor ? forwardHybridSexpRange : (doc: EditableDocument) => forwardHybridSexpRange(doc); selectRangeForward(doc, rangeFn(doc)); @@ -70,26 +70,26 @@ export function selectRight(doc: EditableDocument) { export function selectForwardSexpOrUp(doc: EditableDocument) { const rangeFn = - doc.selection.active >= doc.selection.anchor + doc.selections[0].active >= doc.selections[0].anchor ? forwardSexpOrUpRange - : (doc: EditableDocument) => forwardSexpOrUpRange(doc, doc.selection.active, true); + : (doc: EditableDocument) => forwardSexpOrUpRange(doc, doc.selections[0].active, true); selectRangeForward(doc, rangeFn(doc)); } export function selectBackwardSexp(doc: EditableDocument) { const rangeFn = - doc.selection.active <= doc.selection.anchor + doc.selections[0].active <= doc.selections[0].anchor ? backwardSexpRange - : (doc: EditableDocument) => backwardSexpRange(doc, doc.selection.active, false); + : (doc: EditableDocument) => backwardSexpRange(doc, doc.selections[0].active, false); selectRangeBackward(doc, rangeFn(doc)); } export function selectForwardDownSexp(doc: EditableDocument) { const rangeFn = - doc.selection.active >= doc.selection.anchor - ? (doc: EditableDocument) => rangeToForwardDownList(doc, doc.selection.active, true) - : (doc: EditableDocument) => rangeToForwardDownList(doc, doc.selection.active, true); + doc.selections[0].active >= doc.selections[0].anchor + ? (doc: EditableDocument) => rangeToForwardDownList(doc, doc.selections[0].active, true) + : (doc: EditableDocument) => rangeToForwardDownList(doc, doc.selections[0].active, true); selectRangeForward(doc, rangeFn(doc)); } @@ -98,27 +98,27 @@ export function selectBackwardDownSexp(doc: EditableDocument) { } export function selectForwardUpSexp(doc: EditableDocument) { - selectRangeForward(doc, rangeToForwardUpList(doc, doc.selection.active)); + selectRangeForward(doc, rangeToForwardUpList(doc, doc.selections[0].active)); } export function selectBackwardUpSexp(doc: EditableDocument) { const rangeFn = - doc.selection.active <= doc.selection.anchor - ? (doc: EditableDocument) => rangeToBackwardUpList(doc, doc.selection.active, false) - : (doc: EditableDocument) => rangeToBackwardUpList(doc, doc.selection.active, false); + doc.selections[0].active <= doc.selections[0].anchor + ? (doc: EditableDocument) => rangeToBackwardUpList(doc, doc.selections[0].active, false) + : (doc: EditableDocument) => rangeToBackwardUpList(doc, doc.selections[0].active, false); selectRangeBackward(doc, rangeFn(doc)); } export function selectBackwardSexpOrUp(doc: EditableDocument) { const rangeFn = - doc.selection.active <= doc.selection.anchor - ? (doc: EditableDocument) => backwardSexpOrUpRange(doc, doc.selection.active, false) - : (doc: EditableDocument) => backwardSexpOrUpRange(doc, doc.selection.active, false); + doc.selections[0].active <= doc.selections[0].anchor + ? (doc: EditableDocument) => backwardSexpOrUpRange(doc, doc.selections[0].active, false) + : (doc: EditableDocument) => backwardSexpOrUpRange(doc, doc.selections[0].active, false); selectRangeBackward(doc, rangeFn(doc)); } export function selectCloseList(doc: EditableDocument) { - selectRangeForward(doc, rangeToForwardList(doc, doc.selection.active)); + selectRangeForward(doc, rangeToForwardList(doc, doc.selections[0].active)); } export function selectOpenList(doc: EditableDocument) { @@ -131,7 +131,7 @@ export function selectOpenList(doc: EditableDocument) { */ export function rangeForDefun( doc: EditableDocument, - offset: number = doc.selection.active, + offset: number = doc.selections[0].active, commentCreatesTopLevel = true ): [number, number] { const cursor = doc.getTokenCursor(offset); @@ -154,7 +154,7 @@ enum GoUpSexpOption { */ function _forwardSexpRange( doc: EditableDocument, - offset = Math.max(doc.selection.anchor, doc.selection.active), + offset = Math.max(doc.selections[0].anchor, doc.selections[0].active), goUpSexp: GoUpSexpOption, goPastWhitespace = false ): [number, number] { @@ -189,7 +189,7 @@ function _forwardSexpRange( */ function _backwardSexpRange( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active), + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active), goUpSexp: GoUpSexpOption, goPastWhitespace = false ): [number, number] { @@ -228,7 +228,7 @@ function _backwardSexpRange( export function forwardSexpRange( doc: EditableDocument, - offset = Math.max(doc.selection.anchor, doc.selection.active), + offset = Math.max(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _forwardSexpRange(doc, offset, GoUpSexpOption.Never, goPastWhitespace); @@ -236,7 +236,7 @@ export function forwardSexpRange( export function backwardSexpRange( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active), + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _backwardSexpRange(doc, offset, GoUpSexpOption.Never, goPastWhitespace); @@ -244,7 +244,7 @@ export function backwardSexpRange( export function forwardListRange( doc: EditableDocument, - start: number = doc.selection.active + start: number = doc.selections[0].active ): [number, number] { const cursor = doc.getTokenCursor(start); cursor.forwardList(); @@ -253,7 +253,7 @@ export function forwardListRange( export function backwardListRange( doc: EditableDocument, - start: number = doc.selection.active + start: number = doc.selections[0].active ): [number, number] { const cursor = doc.getTokenCursor(start); cursor.backwardList(); @@ -276,7 +276,7 @@ export function backwardListRange( */ export function forwardHybridSexpRange( doc: EditableDocument, - offset = Math.max(doc.selection.anchor, doc.selection.active), + offset = Math.max(doc.selections[0].anchor, doc.selections[0].active), squashWhitespace = true ): [number, number] { let cursor = doc.getTokenCursor(offset); @@ -352,7 +352,7 @@ export function forwardHybridSexpRange( export function rangeToForwardUpList( doc: EditableDocument, - offset: number = Math.max(doc.selection.anchor, doc.selection.active), + offset: number = Math.max(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _forwardSexpRange(doc, offset, GoUpSexpOption.Required, goPastWhitespace); @@ -360,7 +360,7 @@ export function rangeToForwardUpList( export function rangeToBackwardUpList( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active), + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _backwardSexpRange(doc, offset, GoUpSexpOption.Required, goPastWhitespace); @@ -368,7 +368,7 @@ export function rangeToBackwardUpList( export function forwardSexpOrUpRange( doc: EditableDocument, - offset = Math.max(doc.selection.anchor, doc.selection.active), + offset = Math.max(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _forwardSexpRange(doc, offset, GoUpSexpOption.WhenAtLimit, goPastWhitespace); @@ -376,7 +376,7 @@ export function forwardSexpOrUpRange( export function backwardSexpOrUpRange( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active), + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { return _backwardSexpRange(doc, offset, GoUpSexpOption.WhenAtLimit, goPastWhitespace); @@ -384,7 +384,7 @@ export function backwardSexpOrUpRange( export function rangeToForwardDownList( doc: EditableDocument, - offset: number = Math.max(doc.selection.anchor, doc.selection.active), + offset: number = Math.max(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { const cursor = doc.getTokenCursor(offset); @@ -400,7 +400,7 @@ export function rangeToForwardDownList( export function rangeToBackwardDownList( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active), + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active), goPastWhitespace = false ): [number, number] { const cursor = doc.getTokenCursor(offset); @@ -422,7 +422,7 @@ export function rangeToBackwardDownList( export function rangeToForwardList( doc: EditableDocument, - offset: number = Math.max(doc.selection.anchor, doc.selection.active) + offset: number = Math.max(doc.selections[0].anchor, doc.selections[0].active) ): [number, number] { const cursor = doc.getTokenCursor(offset); if (cursor.forwardList()) { @@ -434,7 +434,7 @@ export function rangeToForwardList( export function rangeToBackwardList( doc: EditableDocument, - offset: number = Math.min(doc.selection.anchor, doc.selection.active) + offset: number = Math.min(doc.selections[0].anchor, doc.selections[0].active) ): [number, number] { const cursor = doc.getTokenCursor(offset); if (cursor.backwardList()) { @@ -448,8 +448,8 @@ export async function wrapSexpr( doc: EditableDocument, open: string, close: string, - start: number = doc.selection.anchor, - end: number = doc.selection.active, + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active, options = { skipFormat: false } ) { const cursor = doc.getTokenCursor(end); @@ -472,7 +472,7 @@ export async function wrapSexpr( ]), ], { - selection: new ModelEditSelection(start + open.length), + selections: [new ModelEditSelection(start + open.length)], skipFormat: options.skipFormat, } ); @@ -486,7 +486,7 @@ export async function wrapSexpr( new ModelEdit('insertString', [range[0], open]), ], { - selection: new ModelEditSelection(start + open.length), + selections: [new ModelEditSelection(start + open.length)], skipFormat: options.skipFormat, } ); @@ -497,8 +497,8 @@ export async function rewrapSexpr( doc: EditableDocument, open: string, close: string, - start: number = doc.selection.anchor, - end: number = doc.selection.active + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active ): Promise> { const cursor = doc.getTokenCursor(end); if (cursor.backwardList()) { @@ -515,13 +515,13 @@ export async function rewrapSexpr( new ModelEdit('changeRange', [oldCloseStart, oldCloseEnd, close]), new ModelEdit('changeRange', [oldOpenStart, oldOpenEnd, open]), ], - { selection: new ModelEditSelection(end + d) } + { selections: [new ModelEditSelection(end + d)] } ); } } } -export async function splitSexp(doc: EditableDocument, start: number = doc.selection.active) { +export async function splitSexp(doc: EditableDocument, start: number = doc.selections[0].active) { const cursor = doc.getTokenCursor(start); if (!cursor.withinString() && !(cursor.isWhiteSpace() || cursor.previousIsWhiteSpace())) { cursor.forwardWhitespace(); @@ -534,7 +534,7 @@ export async function splitSexp(doc: EditableDocument, start: number = doc.selec return doc.model.edit( [new ModelEdit('changeRange', [splitPos, splitPos, `${close}${open}`])], { - selection: new ModelEditSelection(splitPos + 1), + selections: [new ModelEditSelection(splitPos + 1)], } ); } @@ -548,7 +548,7 @@ export async function splitSexp(doc: EditableDocument, start: number = doc.selec */ export async function joinSexp( doc: EditableDocument, - start: number = doc.selection.active + start: number = doc.selections[0].active ): Promise> { const cursor = doc.getTokenCursor(start); cursor.backwardWhitespace(); @@ -569,7 +569,7 @@ export async function joinSexp( [prevEnd, prevEnd], ]), ], - { selection: new ModelEditSelection(prevEnd), formatDepth: 2 } + { selections: [new ModelEditSelection(prevEnd)], formatDepth: 2 } ); } } @@ -577,7 +577,7 @@ export async function joinSexp( export async function spliceSexp( doc: EditableDocument, - start: number = doc.selection.active, + start: number = doc.selections[0].active, undoStopBefore = true ): Promise> { const cursor = doc.getTokenCursor(start); @@ -596,7 +596,7 @@ export async function spliceSexp( new ModelEdit('changeRange', [end, end + close.raw.length, '']), new ModelEdit('changeRange', [beginning - open.raw.length, beginning, '']), ], - { undoStopBefore, selection: new ModelEditSelection(start - 1) } + { undoStopBefore, selections: [new ModelEditSelection(start - 1)] } ); } } @@ -606,7 +606,7 @@ export async function killBackwardList(doc: EditableDocument, [start, end]: [num return doc.model.edit( [new ModelEdit('changeRange', [start, end, '', [end, end], [start, start]])], { - selection: new ModelEditSelection(start), + selections: [new ModelEditSelection(start)], } ); } @@ -626,13 +626,13 @@ export async function killForwardList(doc: EditableDocument, [start, end]: [numb [start, start], ]), ], - { selection: new ModelEditSelection(start) } + { selections: [new ModelEditSelection(start)] } ); } export async function forwardSlurpSexp( doc: EditableDocument, - start: number = doc.selection.active, + start: number = doc.selections[0].active, extraOpts = { formatDepth: 1 } ) { const cursor = doc.getTokenCursor(start); @@ -652,8 +652,8 @@ export async function forwardSlurpSexp( const replacedText = doc.model.getText(wsStartOffset, wsEndOffset); const changeArgs = replacedText.indexOf('\n') >= 0 - ? [currentCloseOffset, currentCloseOffset + close.length, ''] - : [wsStartOffset, wsEndOffset, ' ']; + ? ([currentCloseOffset, currentCloseOffset + close.length, ''] as const) + : ([wsStartOffset, wsEndOffset, ' '] as const); return doc.model.edit( [ new ModelEdit('insertString', [newCloseOffset, close]), @@ -677,7 +677,7 @@ export async function forwardSlurpSexp( export async function backwardSlurpSexp( doc: EditableDocument, - start: number = doc.selection.active, + start: number = doc.selections[0].active, extraOpts = {} ) { const cursor = doc.getTokenCursor(start); @@ -711,7 +711,10 @@ export async function backwardSlurpSexp( } } -export async function forwardBarfSexp(doc: EditableDocument, start: number = doc.selection.active) { +export async function forwardBarfSexp( + doc: EditableDocument, + start: number = doc.selections[0].active +) { const cursor = doc.getTokenCursor(start); cursor.forwardList(); if (cursor.getToken().type == 'close') { @@ -726,7 +729,7 @@ export async function forwardBarfSexp(doc: EditableDocument, start: number = doc ], start >= cursor.offsetStart ? { - selection: new ModelEditSelection(cursor.offsetStart), + selections: [new ModelEditSelection(cursor.offsetStart)], formatDepth: 2, } : { formatDepth: 2 } @@ -736,7 +739,7 @@ export async function forwardBarfSexp(doc: EditableDocument, start: number = doc export async function backwardBarfSexp( doc: EditableDocument, - start: number = doc.selection.active + start: number = doc.selections[0].active ) { const cursor = doc.getTokenCursor(start); cursor.backwardList(); @@ -755,7 +758,7 @@ export async function backwardBarfSexp( ], start <= cursor.offsetStart ? { - selection: new ModelEditSelection(cursor.offsetStart), + selections: [new ModelEditSelection(cursor.offsetStart)], formatDepth: 2, } : { formatDepth: 2 } @@ -767,33 +770,33 @@ export function open( doc: EditableDocument, open: string, close: string, - start: number = doc.selection.active + start: number = doc.selections[0].active ) { - const [cs, ce] = [doc.selection.anchor, doc.selection.active]; + const [cs, ce] = [doc.selections[0].anchor, doc.selections[0].active]; doc.insertString(open + doc.getSelectionText() + close); if (cs != ce) { - doc.selection = new ModelEditSelection(cs + open.length, ce + open.length); + doc.selections = [new ModelEditSelection(cs + open.length, ce + open.length)]; } else { - doc.selection = new ModelEditSelection(start + open.length); + doc.selections = [new ModelEditSelection(start + open.length)]; } } export async function close( doc: EditableDocument, close: string, - start: number = doc.selection.active + start: number = doc.selections[0].active ) { const cursor = doc.getTokenCursor(start); const inString = cursor.withinString(); cursor.forwardWhitespace(false); if (cursor.getToken().raw === close) { - doc.selection = new ModelEditSelection(cursor.offsetEnd); + doc.selections = [new ModelEditSelection(cursor.offsetEnd)]; } else { if (!inString && cursor.docIsBalanced()) { // Do nothing when there is balance } else { return doc.model.edit([new ModelEdit('insertString', [start, close])], { - selection: new ModelEditSelection(start + close.length), + selections: [new ModelEditSelection(start + close.length)], }); } } @@ -803,7 +806,7 @@ function onlyWhitespaceLeftOfCursor(doc: EditableDocument, cursor: LispTokenCurs const token = cursor.getToken(); if (token.type === 'ws') { return token.offset === 0; - } else if (doc.selection.anchor > cursor.offsetStart) { + } else if (doc.selections[0].anchor > cursor.offsetStart) { return false; } const prevToken = cursor.getPrevToken(); @@ -826,7 +829,7 @@ function backspaceOnWhitespaceEdit( ]), ], { - selection: new ModelEditSelection(changeArgs.end + changeArgs.indent), + selections: [new ModelEditSelection(changeArgs.end + changeArgs.indent)], skipFormat: true, } ); @@ -835,8 +838,8 @@ function backspaceOnWhitespaceEdit( export async function backspace( doc: EditableDocument, config?: FormatterConfig, - start: number = doc.selection.anchor, - end: number = doc.selection.active + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active ): Promise { if (start != end) { return doc.backspace(); @@ -855,14 +858,14 @@ export async function backspace( } else if (doc.model.getText(start - 2, start, true) == '\\"') { // delete quoted double quote return doc.model.edit([new ModelEdit('deleteRange', [start - 2, 2])], { - selection: new ModelEditSelection(start - 2), + selections: [new ModelEditSelection(start - 2)], }); } else if (prevToken.type === 'open' && nextToken.type === 'close') { // delete empty list return doc.model.edit( [new ModelEdit('deleteRange', [start - prevToken.raw.length, prevToken.raw.length + 1])], { - selection: new ModelEditSelection(start - prevToken.raw.length), + selections: [new ModelEditSelection(start - prevToken.raw.length)], } ); } else if (!isTopLevel && !cursor.withinString() && onlyWhitespaceLeftOfCursor(doc, cursor)) { @@ -870,7 +873,7 @@ export async function backspace( return backspaceOnWhitespaceEdit(doc, cursor, config); } else { if (['open', 'close'].includes(prevToken.type) && cursor.docIsBalanced()) { - doc.selection = new ModelEditSelection(start - prevToken.raw.length); + doc.selections = [new ModelEditSelection(start - prevToken.raw.length)]; return new Promise((resolve) => resolve(true)); } else { return doc.backspace(); @@ -881,8 +884,8 @@ export async function backspace( export async function deleteForward( doc: EditableDocument, - start: number = doc.selection.anchor, - end: number = doc.selection.active + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active ) { if (start != end) { await doc.delete(); @@ -893,18 +896,18 @@ export async function deleteForward( const p = start; if (doc.model.getText(p, p + 2, true) == '\\"') { return doc.model.edit([new ModelEdit('deleteRange', [p, 2])], { - selection: new ModelEditSelection(p), + selections: [new ModelEditSelection(p)], }); } else if (prevToken.type === 'open' && nextToken.type === 'close') { return doc.model.edit( [new ModelEdit('deleteRange', [p - prevToken.raw.length, prevToken.raw.length + 1])], { - selection: new ModelEditSelection(p - prevToken.raw.length), + selections: [new ModelEditSelection(p - prevToken.raw.length)], } ); } else { if (['open', 'close'].includes(nextToken.type) && cursor.docIsBalanced()) { - doc.selection = new ModelEditSelection(p + 1); + doc.selections = [new ModelEditSelection(p + 1)]; return new Promise((resolve) => resolve(true)); } else { return doc.delete(); @@ -915,8 +918,8 @@ export async function deleteForward( export async function stringQuote( doc: EditableDocument, - start: number = doc.selection.anchor, - end: number = doc.selection.active + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active ) { if (start != end) { doc.insertString('"'); @@ -927,7 +930,7 @@ export async function stringQuote( if (cursor.getToken().type == 'close') { if (doc.model.getText(0, start).endsWith('\\')) { return doc.model.edit([new ModelEdit('changeRange', [start, start, '"'])], { - selection: new ModelEditSelection(start + 1), + selections: [new ModelEditSelection(start + 1)], }); } else { return close(doc, '"', start); @@ -935,17 +938,17 @@ export async function stringQuote( } else { if (doc.model.getText(0, start).endsWith('\\')) { return doc.model.edit([new ModelEdit('changeRange', [start, start, '"'])], { - selection: new ModelEditSelection(start + 1), + selections: [new ModelEditSelection(start + 1)], }); } else { return doc.model.edit([new ModelEdit('changeRange', [start, start, '\\"'])], { - selection: new ModelEditSelection(start + 2), + selections: [new ModelEditSelection(start + 2)], }); } } } else { return doc.model.edit([new ModelEdit('changeRange', [start, start, '""'])], { - selection: new ModelEditSelection(start + 1), + selections: [new ModelEditSelection(start + 1)], }); } } @@ -953,8 +956,8 @@ export async function stringQuote( export function growSelection( doc: EditableDocument, - start: number = doc.selection.anchor, - end: number = doc.selection.active + start: number = doc.selections[0].anchor, + end: number = doc.selections[0].active ) { const startC = doc.getTokenCursor(start); const endC = doc.getTokenCursor(end); @@ -1010,16 +1013,16 @@ export function growSelectionStack(doc: EditableDocument, range: [number, number const [start, end] = range; if (doc.selectionStack.length > 0) { const prev = doc.selectionStack[doc.selectionStack.length - 1]; - if (!(doc.selection.anchor == prev.anchor && doc.selection.active == prev.active)) { + if (!(doc.selections[0].anchor == prev.anchor && doc.selections[0].active == prev.active)) { setSelectionStack(doc); } else if (prev.anchor === range[0] && prev.active === range[1]) { return; } } else { - doc.selectionStack = [doc.selection]; + doc.selectionStack = [doc.selections[0]]; } - doc.selection = new ModelEditSelection(start, end); - doc.selectionStack.push(doc.selection); + doc.selections = [new ModelEditSelection(start, end)]; + doc.selectionStack.push(doc.selections[0]); } export function shrinkSelection(doc: EditableDocument) { @@ -1027,22 +1030,22 @@ export function shrinkSelection(doc: EditableDocument) { const latest = doc.selectionStack.pop(); if ( doc.selectionStack.length && - latest.anchor == doc.selection.anchor && - latest.active == doc.selection.active + latest.anchor == doc.selections[0].anchor && + latest.active == doc.selections[0].active ) { - doc.selection = doc.selectionStack[doc.selectionStack.length - 1]; + doc.selections = [doc.selectionStack[doc.selectionStack.length - 1]]; } } } -export function setSelectionStack(doc: EditableDocument, selection = doc.selection) { - doc.selectionStack = [selection]; +export function setSelectionStack(doc: EditableDocument, selections = doc.selections) { + doc.selectionStack = [selections[0]]; } export async function raiseSexp( doc: EditableDocument, - start = doc.selection.anchor, - end = doc.selection.active + start = doc.selections[0].anchor, + end = doc.selections[0].active ) { const cursor = doc.getTokenCursor(end); const [formStart, formEnd] = cursor.rangeForCurrentForm(start); @@ -1059,9 +1062,11 @@ export async function raiseSexp( return doc.model.edit( [new ModelEdit('changeRange', [startCursor.offsetStart, endCursor.offsetEnd, raised])], { - selection: new ModelEditSelection( - isCaretTrailing ? startCursor.offsetStart + raised.length : startCursor.offsetStart - ), + selections: [ + new ModelEditSelection( + isCaretTrailing ? startCursor.offsetStart + raised.length : startCursor.offsetStart + ), + ], } ); } @@ -1071,8 +1076,8 @@ export async function raiseSexp( export async function convolute( doc: EditableDocument, - start = doc.selection.anchor, - end = doc.selection.active + start = doc.selections[0].anchor, + end = doc.selections[0].active ) { if (start == end) { const cursorStart = doc.getTokenCursor(end); @@ -1111,8 +1116,8 @@ export async function convolute( export async function transpose( doc: EditableDocument, - left = doc.selection.anchor, - right = doc.selection.active, + left = doc.selections[0].anchor, + right = doc.selections[0].active, newPosOffset: { fromLeft?: number; fromRight?: number } = {} ) { const cursor = doc.getTokenCursor(right); @@ -1152,7 +1157,7 @@ export async function transpose( [newCursorPos, newCursorPos], ]), ], - { selection: new ModelEditSelection(newCursorPos) } + { selections: [new ModelEditSelection(newCursorPos)] } ); } } @@ -1226,8 +1231,8 @@ export function currentSexpsRange( export async function dragSexprBackward( doc: EditableDocument, pairForms = bindingForms, - left = doc.selection.anchor, - right = doc.selection.active + left = doc.selections[0].anchor, + right = doc.selections[0].active ) { const cursor = doc.getTokenCursor(right); const usePairs = isInPairsList(cursor, pairForms); @@ -1245,7 +1250,7 @@ export async function dragSexprBackward( new ModelEdit('changeRange', [currentRange[0], currentRange[1], leftText]), new ModelEdit('changeRange', [backRange[0], backRange[1], currentText]), ], - { selection: new ModelEditSelection(backRange[0] + newPosOffset) } + { selections: [new ModelEditSelection(backRange[0] + newPosOffset)] } ); } } @@ -1253,8 +1258,8 @@ export async function dragSexprBackward( export async function dragSexprForward( doc: EditableDocument, pairForms = bindingForms, - left = doc.selection.anchor, - right = doc.selection.active + left = doc.selections[0].anchor, + right = doc.selections[0].active ) { const cursor = doc.getTokenCursor(right); const usePairs = isInPairsList(cursor, pairForms); @@ -1273,9 +1278,11 @@ export async function dragSexprForward( new ModelEdit('changeRange', [currentRange[0], currentRange[1], rightText]), ], { - selection: new ModelEditSelection( - currentRange[1] + (forwardRange[1] - currentRange[1]) - newPosOffset - ), + selections: [ + new ModelEditSelection( + currentRange[1] + (forwardRange[1] - currentRange[1]) - newPosOffset + ), + ], } ); } @@ -1299,7 +1306,7 @@ export type WhitespaceInfo = { */ export function collectWhitespaceInfo( doc: EditableDocument, - p = doc.selection.active + p = doc.selections[0].active ): WhitespaceInfo { const cursor = doc.getTokenCursor(p); const currentRange = cursor.rangeForCurrentForm(p); @@ -1327,7 +1334,7 @@ export function collectWhitespaceInfo( }; } -export async function dragSexprBackwardUp(doc: EditableDocument, p = doc.selection.active) { +export async function dragSexprBackwardUp(doc: EditableDocument, p = doc.selections[0].active) { const wsInfo = collectWhitespaceInfo(doc, p); const cursor = doc.getTokenCursor(p); const currentRange = cursor.rangeForCurrentForm(p); @@ -1336,7 +1343,7 @@ export async function dragSexprBackwardUp(doc: EditableDocument, p = doc.selecti const newPosOffset = p - currentRange[0]; const newCursorPos = listStart + newPosOffset; const listIndent = cursor.getToken().offset; - let dragText: string, deleteEdit: ModelEdit; + let dragText: string, deleteEdit: ModelEdit<'deleteRange'>; if (wsInfo.hasLeftWs) { dragText = doc.model.getText(...currentRange) + @@ -1360,7 +1367,7 @@ export async function dragSexprBackwardUp(doc: EditableDocument, p = doc.selecti new ModelEdit('insertString', [listStart, dragText, [p, p], [newCursorPos, newCursorPos]]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: false, undoStopBefore: true, } @@ -1368,7 +1375,7 @@ export async function dragSexprBackwardUp(doc: EditableDocument, p = doc.selecti } } -export async function dragSexprForwardDown(doc: EditableDocument, p = doc.selection.active) { +export async function dragSexprForwardDown(doc: EditableDocument, p = doc.selections[0].active) { const wsInfo = collectWhitespaceInfo(doc, p); const currentRange = doc.getTokenCursor(p).rangeForCurrentForm(p); const newPosOffset = p - currentRange[0]; @@ -1394,7 +1401,7 @@ export async function dragSexprForwardDown(doc: EditableDocument, p = doc.select new ModelEdit('deleteRange', [currentRange[0], deleteLength]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: false, undoStopBefore: true, } @@ -1403,7 +1410,7 @@ export async function dragSexprForwardDown(doc: EditableDocument, p = doc.select } } -export async function dragSexprForwardUp(doc: EditableDocument, p = doc.selection.active) { +export async function dragSexprForwardUp(doc: EditableDocument, p = doc.selections[0].active) { const wsInfo = collectWhitespaceInfo(doc, p); const cursor = doc.getTokenCursor(p); const currentRange = cursor.rangeForCurrentForm(p); @@ -1426,7 +1433,7 @@ export async function dragSexprForwardUp(doc: EditableDocument, p = doc.selectio new ModelEdit('deleteRange', [deleteStart, deleteLength]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: false, undoStopBefore: true, } @@ -1434,7 +1441,7 @@ export async function dragSexprForwardUp(doc: EditableDocument, p = doc.selectio } } -export async function dragSexprBackwardDown(doc: EditableDocument, p = doc.selection.active) { +export async function dragSexprBackwardDown(doc: EditableDocument, p = doc.selections[0].active) { const wsInfo = collectWhitespaceInfo(doc, p); const currentRange = doc.getTokenCursor(p).rangeForCurrentForm(p); const newPosOffset = p - currentRange[0]; @@ -1463,7 +1470,7 @@ export async function dragSexprBackwardDown(doc: EditableDocument, p = doc.selec ]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: false, undoStopBefore: true, } @@ -1483,7 +1490,7 @@ function adaptContentsToRichComment(contents: string): string { export async function addRichComment( doc: EditableDocument, - p = doc.selection.active, + p = doc.selections[0].active, contents?: string ) { const richComment = `(comment\n ${ @@ -1524,7 +1531,7 @@ export async function addRichComment( ]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: true, undoStopBefore: false, } @@ -1551,7 +1558,7 @@ export async function addRichComment( ]), ], { - selection: new ModelEditSelection(newCursorPos), + selections: [new ModelEditSelection(newCursorPos)], skipFormat: false, undoStopBefore: true, } diff --git a/src/custom-snippets.ts b/src/custom-snippets.ts index bc64daeb4..f88da67a7 100644 --- a/src/custom-snippets.ts +++ b/src/custom-snippets.ts @@ -39,7 +39,7 @@ async function evaluateCodeOrKeyOrSnippet(codeOrKeyOrSnippet?: string | SnippetD const editor = util.getActiveTextEditor(); const [editorNS, _] = editor && editor.document && editor.document.languageId === 'clojure' - ? namespace.getNamespace(editor.document, editor.selection.active) + ? namespace.getNamespace(editor.document, editor.selections[0].active) : undefined; const editorRepl = editor && editor.document && editor.document.languageId === 'clojure' @@ -157,20 +157,20 @@ async function getSnippetDefinition(codeOrKey: string, editorNS: string, editorR export function makeContext(editor: vscode.TextEditor, ns: string, editorNS: string, repl: string) { return { - currentLine: editor.selection.active.line, - currentColumn: editor.selection.active.character, + currentLine: editor.selections[0].active.line, + currentColumn: editor.selections[0].active.character, currentFilename: editor.document.fileName, ns, editorNS, repl, - selection: editor.document.getText(editor.selection), + selection: editor.document.getText(editor.selections[0]), selectionWithBracketTrail: getText.selectionAddingBrackets( editor.document, - editor.selection.active + editor.selections[0].active ), currentFileText: getText.currentFileText(editor.document), ...(editor.document.languageId === 'clojure' - ? getText.currentClojureContext(editor.document, editor.selection.active) + ? getText.currentClojureContext(editor.document, editor.selections[0].active) : {}), }; } diff --git a/src/doc-mirror/index.ts b/src/doc-mirror/index.ts index a61687aa1..6b9632551 100644 --- a/src/doc-mirror/index.ts +++ b/src/doc-mirror/index.ts @@ -10,6 +10,7 @@ import { ModelEditOptions, LineInputModel, ModelEditSelection, + ModelEditFunction, } from '../cursor-doc/model'; import { isUndefined } from 'lodash'; @@ -24,7 +25,7 @@ export class DocumentModel implements EditableModel { this.lineInputModel = new LineInputModel(this.lineEndingLength); } - edit(modelEdits: ModelEdit[], options: ModelEditOptions): Thenable { + edit(modelEdits: ModelEdit[], options: ModelEditOptions): Thenable { const editor = utilities.getActiveTextEditor(), undoStopBefore = !!options.undoStopBefore; return editor @@ -50,8 +51,8 @@ export class DocumentModel implements EditableModel { ) .then((isFulfilled) => { if (isFulfilled) { - if (options.selection) { - this.document.selection = options.selection; + if (options.selections) { + this.document.selections = options.selections; } if (!options.skipFormat) { return formatter.formatPosition(editor, true, { @@ -127,7 +128,7 @@ export class MirroredDocument implements EditableDocument { selectionStack: ModelEditSelection[] = []; public getTokenCursor( - offset: number = this.selection.active, + offset: number = this.selections[0].active, previous: boolean = false ): LispTokenCursor { return this.model.getTokenCursor(offset, previous); @@ -135,36 +136,36 @@ export class MirroredDocument implements EditableDocument { public insertString(text: string) { const editor = utilities.getActiveTextEditor(), - selection = editor.selection, + selection = editor.selections[0], wsEdit = new vscode.WorkspaceEdit(), // TODO: prob prefer selection.active or .start - edit = vscode.TextEdit.insert(this.document.positionAt(this.selection.anchor), text); + edit = vscode.TextEdit.insert(this.document.positionAt(this.selections[0].anchor), text); wsEdit.set(this.document.uri, [edit]); void vscode.workspace.applyEdit(wsEdit).then((_v) => { - editor.selection = selection; + editor.selections = [selection]; }); } - set selection(selection: ModelEditSelection) { + set selections(selections: ModelEditSelection[]) { const editor = utilities.getActiveTextEditor(), document = editor.document, - anchor = document.positionAt(selection.anchor), - active = document.positionAt(selection.active); - editor.selection = new vscode.Selection(anchor, active); + anchor = document.positionAt(selections[0].anchor), + active = document.positionAt(selections[0].active); + editor.selections = [new vscode.Selection(anchor, active)]; editor.revealRange(new vscode.Range(active, active)); } - get selection(): ModelEditSelection { + get selections(): ModelEditSelection[] { const editor = utilities.getActiveTextEditor(), document = editor.document, - anchor = document.offsetAt(editor.selection.anchor), - active = document.offsetAt(editor.selection.active); - return new ModelEditSelection(anchor, active); + anchor = document.offsetAt(editor.selections[0].anchor), + active = document.offsetAt(editor.selections[0].active); + return [new ModelEditSelection(anchor, active)]; } public getSelectionText() { const editor = utilities.getActiveTextEditor(), - selection = editor.selection; + selection = editor.selections[0]; return this.document.getText(selection); } diff --git a/src/edit.ts b/src/edit.ts index 7b38f151c..e127b1e1c 100644 --- a/src/edit.ts +++ b/src/edit.ts @@ -11,7 +11,7 @@ export function continueCommentCommand() { const document = util.tryToGetDocument({}); if (document && document.languageId === 'clojure') { const editor = util.getActiveTextEditor(); - const position = editor.selection.active; + const position = editor.selections[0].active; const cursor = docMirror.getDocument(document).getTokenCursor(); if (cursor.getToken().type !== 'comment') { if (cursor.getPrevToken().type === 'comment') { @@ -35,7 +35,7 @@ export function continueCommentCommand() { .then((fulfilled) => { if (fulfilled) { const newPosition = position.with(position.line + 1, newText.length); - editor.selection = new vscode.Selection(newPosition, newPosition); + editor.selections = [new vscode.Selection(newPosition, newPosition)]; } }); } @@ -69,7 +69,7 @@ export function replace( export function prettyPrintReplaceCurrentForm(options = { enabled: true }) { const editor = util.getActiveTextEditor(); const document = editor.document; - const selection = editor.selection; + const selection = editor.selections[0]; const range = selection.isEmpty ? select.getFormSelection(document, selection.active, false) : selection; diff --git a/src/evaluate.ts b/src/evaluate.ts index 1f768c6d1..010018f22 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -61,7 +61,7 @@ async function addAsComment( wsEdit = new vscode.WorkspaceEdit(); wsEdit.set(editor.document.uri, [edit]); await vscode.workspace.applyEdit(wsEdit); - editor.selection = selection; + editor.selections = [selection]; } // TODO: Clean up this mess @@ -141,14 +141,14 @@ async function evaluateCodeUpdatingUI( void vscode.workspace.applyEdit(wsEdit); } else { if (editor && options.comment) { - await addAsComment(c, value, selection, editor, editor.selection); + await addAsComment(c, value, selection, editor, editor.selections[0]); } if (editor && !outputWindow.isResultsDoc(editor.document)) { annotations.decorateSelection( value, selection, editor, - editor.selection.active, + editor.selections[0].active, resultLocation, annotations.AnnotationStatus.SUCCESS ); @@ -180,14 +180,14 @@ async function evaluateCodeUpdatingUI( outputWindow.appendLine(outputWindowError, async (resultLocation, afterResultLocation) => { if (selection) { const editorError = util.stripAnsi(err.length ? err.join('\n') : e); - const currentCursorPos = editor.selection.active; + const currentCursorPos = editor.selections[0].active; if (editor && options.comment) { await addAsComment( selection.start.character, editorError, selection, editor, - editor.selection + editor.selections[0] ); } if (editor && !outputWindow.isResultsDoc(editor.document)) { @@ -284,19 +284,19 @@ function printWarningForError(e: any) { } function _currentSelectionElseCurrentForm(editor: vscode.TextEditor): getText.SelectionAndText { - if (editor.selection.isEmpty) { - return getText.currentFormText(editor?.document, editor.selection.active); + if (editor.selections[0].isEmpty) { + return getText.currentFormText(editor?.document, editor.selections[0].active); } else { - return [editor.selection, editor.document.getText(editor.selection)]; + return [editor.selections[0], editor.document.getText(editor.selections[0])]; } } function _currentTopLevelFormText(editor: vscode.TextEditor): getText.SelectionAndText { - return getText.currentTopLevelFormText(editor?.document, editor?.selection.active); + return getText.currentTopLevelFormText(editor?.document, editor?.selections[0].active); } function _currentEnclosingFormText(editor: vscode.TextEditor): getText.SelectionAndText { - return getText.currentEnclosingFormText(editor?.document, editor?.selection.active); + return getText.currentEnclosingFormText(editor?.document, editor?.selections[0].active); } function evaluateSelectionReplace(document = {}, options = {}) { @@ -428,7 +428,7 @@ function evaluateUsingTextAndSelectionGetter( Object.assign({}, options, { pprintOptions: getConfig().prettyPrintingOptions, selectionFn: (editor: vscode.TextEditor) => { - const [selection, code] = getter(editor?.document, editor?.selection.active); + const [selection, code] = getter(editor?.document, editor?.selections[0].active); return [selection, formatter(code)]; }, }) @@ -438,7 +438,7 @@ function evaluateUsingTextAndSelectionGetter( function evaluateToCursor(document = {}, options = {}) { if (util.getConnectedState()) { evaluateUsingTextAndSelectionGetter( - vscode.window.activeTextEditor.selection.isEmpty + vscode.window.activeTextEditor.selections[0].isEmpty ? getText.currentEnclosingFormToCursor : getText.selectionAddingBrackets, (code) => `${code}`, diff --git a/src/extension-test/unit/common/text-notation.ts b/src/extension-test/unit/common/text-notation.ts index ed674cf4f..98aa8770e 100644 --- a/src/extension-test/unit/common/text-notation.ts +++ b/src/extension-test/unit/common/text-notation.ts @@ -45,7 +45,7 @@ function textNotationToTextAndSelection(s: string): [string, { anchor: number; a export function docFromTextNotation(s: string): model.StringDocument { const [text, selection] = textNotationToTextAndSelection(s); const doc = new model.StringDocument(text); - doc.selection = new model.ModelEditSelection(selection.anchor, selection.active); + doc.selections = [new model.ModelEditSelection(selection.anchor, selection.active)]; return doc; } @@ -63,5 +63,5 @@ export function text(doc: model.StringDocument): string { * selection from a document */ export function textAndSelection(doc: model.StringDocument): [string, [number, number]] { - return [text(doc), [doc.selection.anchor, doc.selection.active]]; + return [text(doc), [doc.selections[0].anchor, doc.selections[0].active]]; } diff --git a/src/extension-test/unit/cursor-doc/paredit-test.ts b/src/extension-test/unit/cursor-doc/paredit-test.ts index 73a888040..de542f6f8 100644 --- a/src/extension-test/unit/cursor-doc/paredit-test.ts +++ b/src/extension-test/unit/cursor-doc/paredit-test.ts @@ -17,7 +17,7 @@ describe('paredit', () => { beforeEach(() => { doc = new model.StringDocument(docText); - doc.selection = startSelection.clone(); + doc.selections = [startSelection.clone()]; }); describe('movement', () => { @@ -216,7 +216,7 @@ describe('paredit', () => { const a = docFromTextNotation('(a|\n e) g)'); const b = docFromTextNotation('(a|\n| e)'); const expected = textAndSelection(b)[1]; - const actual = paredit.forwardHybridSexpRange(a, a.selection.active, false); + const actual = paredit.forwardHybridSexpRange(a, a.selections[0].active, false); expect(actual).toEqual(expected); }); @@ -636,21 +636,21 @@ describe('paredit', () => { doc = new model.StringDocument(docText); }); it('dragSexprBackward: #f•(#b •[:f :b :z])•#x•#y•|1•#å#ä#ö => #x•#y•1•#f•(#b •[:f :b :z])•#å#ä#ö', async () => { - doc.selection = new ModelEditSelection(26, 26); + doc.selections = [new ModelEditSelection(26, 26)]; await paredit.dragSexprBackward(doc); expect(doc.model.getText(0, Infinity)).toBe('#x\n#y\n1\n#f\n(#b \n[:f :b :z])\n#å#ä#ö'); }); it('dragSexprForward: #f•|(#b •[:f :b :z])•#x•#y•1#å#ä#ö => #x•#y•1•#f•|(#b •[:f :b :z])•#å#ä#ö', async () => { - doc.selection = new ModelEditSelection(3, 3); + doc.selections = [new ModelEditSelection(3, 3)]; await paredit.dragSexprForward(doc); expect(doc.model.getText(0, Infinity)).toBe('#x\n#y\n1\n#f\n(#b \n[:f :b :z])\n#å#ä#ö'); - expect(doc.selection).toEqual(new ModelEditSelection(11)); + expect(doc.selections).toEqual([new ModelEditSelection(11)]); }); it('dragSexprForward: #f•(#b •[:f :b :z])•#x•#y•|1•#å#ä#ö => #f•(#b •[:f :b :z])•#x•#y•|1•#å#ä#ö', async () => { - doc.selection = new ModelEditSelection(26, 26); + doc.selections = [new ModelEditSelection(26, 26)]; await paredit.dragSexprForward(doc); expect(doc.model.getText(0, Infinity)).toBe('#f\n(#b \n[:f :b :z])\n#x\n#y\n1\n#å#ä#ö'); - expect(doc.selection).toEqual(new ModelEditSelection(26)); + expect(doc.selections).toEqual([new ModelEditSelection(26)]); }); }); }); @@ -662,14 +662,14 @@ describe('paredit', () => { const a = docFromTextNotation('(def foo [:foo :bar |<|:baz|<|])'); const selDoc = docFromTextNotation('(def foo [:foo |:bar| :baz])'); const b = docFromTextNotation('(def foo [:foo |<|:bar :baz|<|])'); - paredit.selectRangeBackward(a, [selDoc.selection.anchor, selDoc.selection.active]); + paredit.selectRangeBackward(a, [selDoc.selections[0].anchor, selDoc.selections[0].active]); expect(textAndSelection(a)).toEqual(textAndSelection(b)); }); it('Contracts forward selection and extends backwards', () => { const a = docFromTextNotation('(def foo [:foo :bar |>|:baz|>|])'); const selDoc = docFromTextNotation('(def foo [:foo |:bar| :baz])'); const b = docFromTextNotation('(def foo [:foo |<|:bar |<|:baz])'); - paredit.selectRangeBackward(a, [selDoc.selection.anchor, selDoc.selection.active]); + paredit.selectRangeBackward(a, [selDoc.selections[0].anchor, selDoc.selections[0].active]); expect(textAndSelection(a)).toEqual(textAndSelection(b)); }); }); @@ -679,27 +679,27 @@ describe('paredit', () => { const barSelection = new ModelEditSelection(15, 19), bazRange = [20, 24] as [number, number], barBazSelection = new ModelEditSelection(15, 24); - doc.selection = barSelection; + doc.selections = [barSelection]; paredit.selectRangeForward(doc, bazRange); - expect(doc.selection).toEqual(barBazSelection); + expect(doc.selections).toEqual([barBazSelection]); }); it('(def foo [<:foo :bar< >|:baz>|]) => (def foo [>:foo :bar :baz>])', () => { const [fooLeft, barRight] = [10, 19], barFooSelection = new ModelEditSelection(barRight, fooLeft), bazRange = [20, 24] as [number, number], fooBazSelection = new ModelEditSelection(19, 24); - doc.selection = barFooSelection; + doc.selections = [barFooSelection]; paredit.selectRangeForward(doc, bazRange); - expect(doc.selection).toEqual(fooBazSelection); + expect(doc.selections).toEqual([fooBazSelection]); }); it('(def foo [<:foo :bar< <|:baz<|]) => (def foo [>:foo :bar :baz>])', () => { const [fooLeft, barRight] = [10, 19], barFooSelection = new ModelEditSelection(barRight, fooLeft), bazRange = [24, 20] as [number, number], fooBazSelection = new ModelEditSelection(19, 24); - doc.selection = barFooSelection; + doc.selections = [barFooSelection]; paredit.selectRangeForward(doc, bazRange); - expect(doc.selection).toEqual(fooBazSelection); + expect(doc.selections).toEqual([fooBazSelection]); }); }); }); @@ -719,7 +719,7 @@ describe('paredit', () => { expect(doc.selectionStack[doc.selectionStack.length - 1]).toEqual(selectionBefore); }); it('should not add selections identical to the topmost', () => { - const selectionBefore = doc.selection.clone(); + const selectionBefore = doc.selections[0].clone(); paredit.growSelectionStack(doc, range); paredit.growSelectionStack(doc, range); paredit.shrinkSelection(doc); @@ -737,25 +737,25 @@ describe('paredit', () => { }); it('grows selection to binding pairs', () => { const a = docFromTextNotation('(a (let [b c |e| f]))'); - const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active); + const aSelection = new ModelEditSelection(a.selections[0].anchor, a.selections[0].active); const b = docFromTextNotation('(a (let [b c |e f|]))'); - const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active); + const bSelection = new ModelEditSelection(b.selections[0].anchor, b.selections[0].active); paredit.growSelection(a); expect(a.selectionStack).toEqual([aSelection, bSelection]); }); it('grows selection to all of binding box when binding pairs are selected', () => { const a = docFromTextNotation('(a (let [b c |e f|]))'); - const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active); + const aSelection = new ModelEditSelection(a.selections[0].anchor, a.selections[0].active); const b = docFromTextNotation('(a (let [|b c e f|]))'); - const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active); + const bSelection = new ModelEditSelection(b.selections[0].anchor, b.selections[0].active); paredit.growSelection(a); expect(a.selectionStack).toEqual([aSelection, bSelection]); }); it('grows selection to the binding box when all binding pairs are selected', () => { const a = docFromTextNotation('(a (let [|b c e f|]))'); - const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active); + const aSelection = new ModelEditSelection(a.selections[0].anchor, a.selections[0].active); const b = docFromTextNotation('(a (let |[b c e f]|))'); - const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active); + const bSelection = new ModelEditSelection(b.selections[0].anchor, b.selections[0].active); paredit.growSelection(a); expect(a.selectionStack).toEqual([aSelection, bSelection]); }); diff --git a/src/extension-test/unit/cursor-doc/token-cursor-test.ts b/src/extension-test/unit/cursor-doc/token-cursor-test.ts index 5f02de07d..f614060f1 100644 --- a/src/extension-test/unit/cursor-doc/token-cursor-test.ts +++ b/src/extension-test/unit/cursor-doc/token-cursor-test.ts @@ -7,16 +7,16 @@ describe('Token Cursor', () => { it('it moves past whitespace', () => { const a = docFromTextNotation('a •|c'); const b = docFromTextNotation('a| •c'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardWhitespace(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('it moves past whitespace from inside symbol', () => { const a = docFromTextNotation('a •c|c'); const b = docFromTextNotation('a| •cc'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardWhitespace(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); @@ -24,126 +24,126 @@ describe('Token Cursor', () => { it('moves from beginning to end of symbol', () => { const a = docFromTextNotation('(|c•#f)'); const b = docFromTextNotation('(c|•#f)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('forwardSexp with newline', () => { const a = docFromTextNotation('|(a\n(b))'); const b = docFromTextNotation('(a\n(b))|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('forwardSexp with newline (MS-Windows)', () => { const a = docFromTextNotation('|(a\r\n(b))'); const b = docFromTextNotation('(a\r\n(b))|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('moves from beginning to end of nested list ', () => { const a = docFromTextNotation('|(a(b(c•#f•(#b •[:f])•#z•1)))'); const b = docFromTextNotation('(a(b(c•#f•(#b •[:f])•#z•1)))|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Includes reader tag as part of a list form', () => { const a = docFromTextNotation('(c|•#f•(#b •[:f :b :z])•#z•1)'); const b = docFromTextNotation('(c•#f•(#b •[:f :b :z])|•#z•1)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Includes reader tag as part of a symbol', () => { const a = docFromTextNotation('(c•#f•(#b •[:f :b :z])|•#z•1)'); const b = docFromTextNotation('(c•#f•(#b •[:f :b :z])•#z•1|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move out of a list', () => { const a = docFromTextNotation('(c•#f•(#b •[:f :b :z])•#z•1|)'); const b = docFromTextNotation('(c•#f•(#b •[:f :b :z])•#z•1|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skip metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a |^{:a 1} (= 1 1))'); const b = docFromTextNotation('(a ^{:a 1} (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skip metadata and reader if skipMetadata is true', () => { const a = docFromTextNotation('(a |^{:a 1} #a (= 1 1))'); const b = docFromTextNotation('(a ^{:a 1} #a (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skip reader and metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a |#a ^{:a 1} (= 1 1))'); const b = docFromTextNotation('(a #a ^{:a 1} (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips multiple metadata maps if skipMetadata is true', () => { const a = docFromTextNotation('(a |^{:a 1} ^{:b 2} (= 1 1))'); const b = docFromTextNotation('(a ^{:a 1} ^{:b 2} (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips symbol shorthand for metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a| ^String (= 1 1))'); const b = docFromTextNotation('(a ^String (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips keyword shorthand for metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a| ^:hello (= 1 1))'); const b = docFromTextNotation('(a ^:hello (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips multiple keyword shorthands for metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a| ^:hello ^:world (= 1 1))'); const b = docFromTextNotation('(a ^:hello ^:world (= 1 1)|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not skip ignored forms if skipIgnoredForms is false', () => { const a = docFromTextNotation('(a| #_1 #_2 3)'); const b = docFromTextNotation('(a #_|1 #_2 3)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skip ignored forms if skipIgnoredForms is true', () => { const a = docFromTextNotation('(a| #_1 #_2 3)'); const b = docFromTextNotation('(a #_1 #_2 3|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('should skip stacked ignored forms if skipIgnoredForms is true', () => { const a = docFromTextNotation('(a| #_ #_ 1 2 3)'); const b = docFromTextNotation('(a #_ #_ 1 2 3|)'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardSexp(true, true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); xit('Does not move past unbalanced top level form', () => { //TODO: Figure out why this doesn't work const d = docFromTextNotation('|(foo "bar"'); - const cursor: LispTokenCursor = d.getTokenCursor(d.selection.anchor); + const cursor: LispTokenCursor = d.getTokenCursor(d.selections[0].anchor); const offsetStart = cursor.offsetStart; cursor.forwardSexp(); expect(cursor.offsetStart).toBe(offsetStart); @@ -154,79 +154,79 @@ describe('Token Cursor', () => { it('moves from end to beginning of symbol', () => { const a = docFromTextNotation('(a(b(c|•#f•(#b •[:f :b :z])•#z•1)))'); const b = docFromTextNotation('(a(b(|c•#f•(#b •[:f :b :z])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('moves from end to beginning of nested list ', () => { const a = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])•#z•1)))|'); const b = docFromTextNotation('|(a(b(c•#f•(#b •[:f :b :z])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Includes reader tag as part of a list form', () => { const a = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])|•#z•1)))'); const b = docFromTextNotation('(a(b(c•|#f•(#b •[:f :b :z])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Includes reader tag as part of a symbol', () => { const a = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])•#z•1|)))'); const b = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])•|#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move out of a list', () => { const a = docFromTextNotation('(a(|b(c•#f•(#b •[:f :b :z])•#z•1)))'); const b = docFromTextNotation('(a(|b(c•#f•(#b •[:f :b :z])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skip metadata if skipMetadata is true', () => { const a = docFromTextNotation('(a ^{:a 1} (= 1 1)|)'); const b = docFromTextNotation('(a |^{:a 1} (= 1 1))'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Treats metadata as part of the sexp if skipMetadata is true', () => { const a = docFromTextNotation('(a ^{:a 1}| (= 1 1))'); const b = docFromTextNotation('(a |^{:a 1} (= 1 1))'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips multiple metadata maps if skipMetadata is true', () => { const a = docFromTextNotation('(a ^{:a 1} ^{:b 2} (= 1 1)|)'); const b = docFromTextNotation('(a |^{:a 1} ^{:b 2} (= 1 1))'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Treats metadata and readers as part of the sexp if skipMetadata is true', () => { const a = docFromTextNotation('#bar •^baz•|[:a :b :c]•x'); const b = docFromTextNotation('|#bar •^baz•[:a :b :c]•x'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Treats reader and metadata as part of the sexp if skipMetadata is true', () => { const a = docFromTextNotation('^bar •#baz•|[:a :b :c]•x'); const b = docFromTextNotation('|^bar •#baz•[:a :b :c]•x'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Treats readers and metadata:s mixed as part of the sexp from behind the sexp if skipMetadata is true', () => { const a = docFromTextNotation('^d #c ^b •#a•[:a :b :c]|•x'); const b = docFromTextNotation('|^d #c ^b •#a•[:a :b :c]•x'); - const cursor = a.getTokenCursor(a.selection.anchor); + const cursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(true, true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); @@ -234,44 +234,44 @@ describe('Token Cursor', () => { it('Puts cursor to the right of the following open paren', () => { const a = docFromTextNotation('(a |(b 1))'); const b = docFromTextNotation('(a (|b 1))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Puts cursor to the right of the following open curly brace:', () => { const a = docFromTextNotation('(a |{:b 1}))'); const b = docFromTextNotation('(a {|:b 1}))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Puts cursor to the right of the following open bracket', () => { const a = docFromTextNotation('(a| [1 2]))'); const b = docFromTextNotation('(a [|1 2]))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it(`Puts cursor to the right of the following opening quoted list`, () => { const a = docFromTextNotation(`(a| '(b 1))`); const b = docFromTextNotation(`(a '(|b 1))`); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Skips whitespace', () => { const a = docFromTextNotation('(a|• (b 1))'); const b = docFromTextNotation('(a• (|b 1))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not skip metadata', () => { const a = docFromTextNotation('(a| ^{:x 1} (b 1))'); const b = docFromTextNotation('(a ^{|:x 1} (b 1))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); @@ -279,84 +279,84 @@ describe('Token Cursor', () => { it('Moves down, skipping metadata', () => { const a = docFromTextNotation('(|a #b ^{:x 1} (c 1))'); const b = docFromTextNotation('(a #b ^{:x 1} (|c 1))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downListSkippingMeta(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Moves down when there is no metadata', () => { const a = docFromTextNotation('(|a #b (c 1))'); const b = docFromTextNotation('(a #b (|c 1))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.downListSkippingMeta(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); it('upList', () => { const a = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])•#z•1|)))'); const b = docFromTextNotation('(a(b(c•#f•(#b •[:f :b :z])•#z•1)|))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.upList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); describe('forwardList', () => { it('Finds end of list', () => { const a = docFromTextNotation('(|foo (bar baz) [])'); const b = docFromTextNotation('(foo (bar baz) []|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds end of list through readers and meta', () => { const a = docFromTextNotation('(|#a ^{:b c} #d (bar baz) [])'); const b = docFromTextNotation('(#a ^{:b c} #d (bar baz) []|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move at top level', () => { const a = docFromTextNotation('|foo (bar baz)'); const b = docFromTextNotation('|foo (bar baz)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move at top level when unbalanced document from extra closings', () => { const a = docFromTextNotation('|foo (bar baz))'); const b = docFromTextNotation('|foo (bar baz))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move at top level when unbalanced document from extra opens', () => { const a = docFromTextNotation('|foo ((bar baz)'); const b = docFromTextNotation('|foo ((bar baz)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move when unbalanced from extra opens', () => { const a = docFromTextNotation('(|['); const b = docFromTextNotation('(|['); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move when at end of list, returns true', () => { const a = docFromTextNotation('(|)'); const b = docFromTextNotation('(|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardList(); expect(result).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds the list end when unbalanced from extra closes outside the current list', () => { const a = docFromTextNotation('(|a #b []))'); const b = docFromTextNotation('(a #b []|))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); @@ -364,66 +364,66 @@ describe('Token Cursor', () => { it('Finds start of list', () => { const a = docFromTextNotation('(((c•(#b •[:f])•#z•|1)))'); const b = docFromTextNotation('(((|c•(#b •[:f])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds start of list through readers', () => { const a = docFromTextNotation('(((c•#a• #f•(#b •[:f])•#z•|1)))'); const b = docFromTextNotation('(((|c•#a• #f•(#b •[:f])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds start of list through metadata', () => { const a = docFromTextNotation('(((c•^{:a c} (#b •[:f])•#z•|1)))'); const b = docFromTextNotation('(((|c•^{:a c} (#b •[:f])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move at top level', () => { const a = docFromTextNotation('foo |(bar baz)'); const b = docFromTextNotation('foo |(bar baz)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move when at start of unbalanced list', () => { // https://github.com/BetterThanTomorrow/calva/issues/1573 // https://github.com/BetterThanTomorrow/calva/commit/d77359fcea16bc052ab829853d5711434330a375 const a = docFromTextNotation('([|'); const b = docFromTextNotation('([|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardList(); expect(result).toBe(false); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Does not move to start of an unbalanced list when outer list is also unbalanced', () => { // NB: This is a bit arbitrary, this test documents the current behaviour const a = docFromTextNotation('(let [a| a'); const b = docFromTextNotation('(let [a| a'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(false); }); it('Moves to start of an unbalanced list when outer list is balanced', () => { // NB: This is a bit arbitrary, this test documents the current behaviour const a = docFromTextNotation('(let [a| a)'); const b = docFromTextNotation('(let [|a a)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Finds the list start when unbalanced from extra closes outside the current list', () => { const a = docFromTextNotation('([]|))'); const b = docFromTextNotation('(|[]))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardList(); expect(result).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); @@ -431,41 +431,41 @@ describe('Token Cursor', () => { it('Finds end of list', () => { const a = docFromTextNotation('([#{|c•(#b •[:f])•#z•1}])'); const b = docFromTextNotation('([#{c•(#b •[:f])•#z•1}]|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardListOfType(')'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Finds end of vector', () => { const a = docFromTextNotation('([(c•(#b| •[:f])•#z•1)])'); const b = docFromTextNotation('([(c•(#b •[:f])•#z•1)|])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardListOfType(']'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Finds end of map', () => { const a = docFromTextNotation('({:a [(c•(#|b •[:f])•#z•|1)]})'); const b = docFromTextNotation('({:a [(c•(#b •[:f])•#z•1)]|})'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardListOfType('}'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Does not move when list is unbalanced from missing open', () => { const a = docFromTextNotation('|])'); const b = docFromTextNotation('|])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardListOfType(')'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(false); }); it('Does not move when list type is not found', () => { const a = docFromTextNotation('([|])'); const b = docFromTextNotation('([|])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.forwardListOfType('}'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(false); }); }); @@ -474,25 +474,25 @@ describe('Token Cursor', () => { it('Finds start of list', () => { const a = docFromTextNotation('([#{c•(#b •[:f])•#z•|1}])'); const b = docFromTextNotation('(|[#{c•(#b •[:f])•#z•1}])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('('); expect(result).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds start of vector', () => { const a = docFromTextNotation('([(c•(#b •[:f])•#z•|1)])'); const b = docFromTextNotation('([|(c•(#b •[:f])•#z•1)])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('['); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Finds start of map', () => { const a = docFromTextNotation('({:a [(c•(#b •[:f])•#z•|1)]})'); const b = docFromTextNotation('({|:a [(c•(#b •[:f])•#z•1)]})'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('{'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Does not move when list type is unbalanced from missing close', () => { @@ -500,18 +500,18 @@ describe('Token Cursor', () => { // https://github.com/BetterThanTomorrow/calva/issues/1573 const a = docFromTextNotation('([|'); const b = docFromTextNotation('([|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('('); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(false); }); it('Moves backward in unbalanced list when outer list is balanced', () => { // https://github.com/BetterThanTomorrow/calva/issues/1585 const a = docFromTextNotation('(let [a|)'); const b = docFromTextNotation('(let [|a)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('['); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Moves backward in balanced list when inner list is unbalanced', () => { @@ -519,17 +519,17 @@ describe('Token Cursor', () => { // https://github.com/BetterThanTomorrow/calva/issues/1585 const a = docFromTextNotation('(let [a|)'); const b = docFromTextNotation('(|let [a)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('('); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(true); }); it('Does not move when list type is not found', () => { const a = docFromTextNotation('([|])'); const b = docFromTextNotation('([|])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); const result = cursor.backwardListOfType('{'); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); expect(result).toBe(false); }); }); @@ -537,32 +537,32 @@ describe('Token Cursor', () => { it('backwardUpList', () => { const a = docFromTextNotation('(a(b(c•#f•(#b •|[:f :b :z])•#z•1)))'); const b = docFromTextNotation('(a(b(c•#f•|(#b •[:f :b :z])•#z•1)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardUpList(); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); describe('Navigation in and around strings', () => { it('backwardList moves to start of string', () => { const a = docFromTextNotation('(str [] "", "foo" "f | b b" " f b b " "\\"" \\")'); const b = docFromTextNotation('(str [] "", "foo" "|f b b" " f b b " "\\"" \\")'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardList(); - expect(cursor.offsetStart).toEqual(b.selection.anchor); + expect(cursor.offsetStart).toEqual(b.selections[0].anchor); }); it('forwardList moves to end of string', () => { const a = docFromTextNotation('(str [] "", "foo" "f | b b" " f b b " "\\"" \\")'); const b = docFromTextNotation('(str [] "", "foo" "f b b|" " f b b " "\\"" \\")'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.forwardList(); - expect(cursor.offsetStart).toEqual(b.selection.anchor); + expect(cursor.offsetStart).toEqual(b.selections[0].anchor); }); it('backwardSexpr inside string moves past quoted characters', () => { const a = docFromTextNotation('(str [] "foo \\"| bar")'); const b = docFromTextNotation('(str [] "foo |\\" bar")'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toEqual(b.selection.anchor); + expect(cursor.offsetStart).toEqual(b.selections[0].anchor); }); }); @@ -570,16 +570,16 @@ describe('Token Cursor', () => { it('Backward sexp bypasses prompt', () => { const a = docFromTextNotation('foo•clj꞉foo꞉> |'); const b = docFromTextNotation('|foo•clj꞉foo꞉> '); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(); - expect(cursor.offsetStart).toEqual(b.selection.active); + expect(cursor.offsetStart).toEqual(b.selections[0].active); }); it('Backward sexp not skipping comments bypasses prompt finding its start', () => { const a = docFromTextNotation('foo•clj꞉foo꞉> |'); const b = docFromTextNotation('foo•|clj꞉foo꞉> '); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); cursor.backwardSexp(false); - expect(cursor.offsetStart).toEqual(b.selection.active); + expect(cursor.offsetStart).toEqual(b.selections[0].active); }); }); @@ -587,165 +587,165 @@ describe('Token Cursor', () => { it('0: selects from within non-list form', () => { const a = docFromTextNotation('(a|aa (bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x'); const b = docFromTextNotation('(|aaa| (bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('0: selects from within non-list form including reader tag', () => { const a = docFromTextNotation('(#a a|aa (foo bar)))'); const b = docFromTextNotation('(|#a aaa| (foo bar)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('0: selects from within non-list form including multiple reader tags', () => { const a = docFromTextNotation('(#aa #a #b a|aa (foo bar)))'); const b = docFromTextNotation('(|#aa #a #b aaa| (foo bar)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('0: selects from within non-list form including metadata', () => { const a = docFromTextNotation('(^aa #a a|aa (foo bar)))'); const b = docFromTextNotation('(|^aa #a aaa| (foo bar)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('0: selects from within non-list form including readers and metadata', () => { const a = docFromTextNotation('(^aa #a a|aa (foo bar))'); const b = docFromTextNotation('(|^aa #a aaa| (foo bar))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('0: selects from within non-list form including metadata and readers', () => { const a = docFromTextNotation('(#a ^aa a|aa (foo bar))'); const b = docFromTextNotation('(|#a ^aa aaa| (foo bar))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('1: selects from adjacent when after form', () => { const a = docFromTextNotation('(aaa •x•#(a b c)|)•#baz•yyy•)'); const b = docFromTextNotation('(aaa •x•|#(a b c)|)•#baz•yyy•)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('1: selects from adjacent when after form, including reader tags', () => { const a = docFromTextNotation('(x• #a #b •#(a b c)|)•#baz•yyy•)'); const b = docFromTextNotation('(x• |#a #b •#(a b c)|)•#baz•yyy•)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('1: selects from adjacent when after form, including readers and meta data', () => { const a = docFromTextNotation('(x• ^a #b •#(a b c)|)•#baz•yyy•)'); const b = docFromTextNotation('(x• |^a #b •#(a b c)|)•#baz•yyy•)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('1: selects from adjacent when after form, including meta data and readers', () => { const a = docFromTextNotation('(x• #a ^b •#(a b c)|)•#baz•yyy•)'); const b = docFromTextNotation('(x• |#a ^b •#(a b c)|)•#baz•yyy•)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form', () => { const a = docFromTextNotation('#bar •#baz•[:a :b :c]•x•|#(a b c)'); const b = docFromTextNotation('#bar •#baz•[:a :b :c]•x•|#(a b c)|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, including reader tags', () => { const a = docFromTextNotation('|#bar •#baz•[:a :b :c]•x'); const b = docFromTextNotation('|#bar •#baz•[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, including meta data', () => { const a = docFromTextNotation('|^bar •[:a :b :c]•x'); const b = docFromTextNotation('|^bar •[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, including meta data and reader', () => { const a = docFromTextNotation('|^bar •#baz•[:a :b :c]•x'); const b = docFromTextNotation('|^bar •#baz•[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, including preceding reader and meta data', () => { const a = docFromTextNotation('^bar •#baz•|[:a :b :c]•x'); const b = docFromTextNotation('|^bar •#baz•[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, including preceding meta data and reader', () => { const a = docFromTextNotation('#bar •^baz•|[:a :b :c]•x'); const b = docFromTextNotation('|#bar •^baz•[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before form, or in readers', () => { const a = docFromTextNotation('ccc •#foo•|•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy'); const b = docFromTextNotation('ccc •|#foo••(#bar •#baz•[:a :b :c]•x•#(a b c))|•#baz•yyy'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects from adjacent before a form with reader tags', () => { const a = docFromTextNotation('#bar |•#baz•[:a :b :c]•x'); const b = docFromTextNotation('|#bar •#baz•[:a :b :c]|•x'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('3: selects previous form, if on the same line', () => { const a = docFromTextNotation('z z | •foo• • bar'); const b = docFromTextNotation('z |z| •foo• • bar'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('4: selects next form, if on the same line', () => { const a = docFromTextNotation('yyy•| z z z •foo• • bar'); const b = docFromTextNotation('yyy• |z| z z •foo• • bar'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('5: selects previous form, if any', () => { const a = docFromTextNotation('yyy• z z z •foo• |• bar'); const b = docFromTextNotation('yyy• z z z •|foo|• • bar'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('5: selects previous form, if any, when next form has metadata', () => { const a = docFromTextNotation('z•foo•|•^{:a b}•bar'); const b = docFromTextNotation('z•|foo|••^{:a b}•bar'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('6: selects next form, if any', () => { const a = docFromTextNotation(' | • (foo {:a b})•(c)'); const b = docFromTextNotation(' • |(foo {:a b})|•(c)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('7: selects enclosing form, if any', () => { const a = docFromTextNotation('(|) • (foo {:a b})•(c)'); const b = docFromTextNotation('|()| • (foo {:a b})•(c)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects anonymous function when cursor is before #', () => { const a = docFromTextNotation('(map |#(println %) [1 2])'); const b = docFromTextNotation('(map |#(println %)| [1 2])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('2: selects anonymous function when cursor is after # and before (', () => { const a = docFromTextNotation('(map #|(println %) [1 2])'); const b = docFromTextNotation('(map |#(println %)| [1 2])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('8: does not croak on unbalance', () => { // This hangs the structural editing in the real editor // https://github.com/BetterThanTomorrow/calva/issues/1573 const a = docFromTextNotation('([|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); - expect(cursor.rangeForCurrentForm(a.selection.anchor)).toBeUndefined(); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); + expect(cursor.rangeForCurrentForm(a.selections[0].anchor)).toBeUndefined(); }); }); @@ -757,8 +757,8 @@ describe('Token Cursor', () => { const b = docFromTextNotation( 'aaa |(bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar))| (ddd eee)' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range when in current form is top level', () => { const a = docFromTextNotation( @@ -767,8 +767,8 @@ describe('Token Cursor', () => { const b = docFromTextNotation( 'aaa (bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar)) |(ddd eee)|' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range when in ”solid” top level form', () => { const a = docFromTextNotation( @@ -777,8 +777,8 @@ describe('Token Cursor', () => { const b = docFromTextNotation( '|aaa| (bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar)) (ddd eee)' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds something when there is unbalance', () => { const a = docFromTextNotation( @@ -787,72 +787,72 @@ describe('Token Cursor', () => { const b = docFromTextNotation( '(ns xxx)•(def xxx•|{()"#"\\$" #"(?!\\w)"))))))))))))))))))))))))))))))))))))))))|' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); describe('Rich Comment Form top level context', () => { it('Finds range for a top level form inside a comment', () => { const a = docFromTextNotation('aaa (comment [bbb cc|c] ddd)'); const b = docFromTextNotation('aaa (comment |[bbb ccc]| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level map inside a comment', () => { const a = docFromTextNotation('aaa (comment {bbb cc|c} ddd)'); const b = docFromTextNotation('aaa (comment |{bbb ccc}| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); // https://github.com/BetterThanTomorrow/calva/issues/2290 describe('Rich Comment Form top level context from inside form', () => { it('Finds range for a top level function call inside a comment from inside a string', () => { const a = docFromTextNotation('aaa (comment (bbb "cc|c") ddd)'); const b = docFromTextNotation('aaa (comment |(bbb "ccc")| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level shortcut lambda function inside a comment from inside a string', () => { const a = docFromTextNotation('aaa (comment #(bbb "cc|c") ddd)'); const b = docFromTextNotation('aaa (comment |#(bbb "ccc")| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level quoted list inside a comment from inside a string', () => { const a = docFromTextNotation(`aaa (comment '(bbb "cc|c") ddd)`); const b = docFromTextNotation(`aaa (comment |'(bbb "ccc")| ddd)`); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level map inside a comment from inside a string', () => { const a = docFromTextNotation('aaa (comment {bbb "cc|c"} ddd)'); const b = docFromTextNotation('aaa (comment |{bbb "ccc"}| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level map inside a comment from inside a form', () => { const a = docFromTextNotation('aaa (comment {bbb [cc|c]} ddd)'); const b = docFromTextNotation('aaa (comment |{bbb [ccc]}| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level set inside a comment from inside a string', () => { const a = docFromTextNotation('aaa (comment #{bbb "cc|c"} ddd)'); const b = docFromTextNotation('aaa (comment |#{bbb "ccc"}| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds range for a top level vector inside a comment from inside a string', () => { const a = docFromTextNotation('aaa (comment [bbb "cc|c"] ddd)'); const b = docFromTextNotation('aaa (comment |[bbb "ccc"]| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); }); it('Finds range for a top level form inside a comment inside a form', () => { const a = docFromTextNotation('a (b (comment [c |d] e))'); const b = docFromTextNotation('a (b (comment |[c d]| e))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds top level comment range if comment special treatment is disabled', () => { const a = docFromTextNotation( @@ -861,21 +861,21 @@ describe('Token Cursor', () => { const b = docFromTextNotation( 'aaa |(comment (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar))| (ddd eee)' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active, false)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active, false)).toEqual(textAndSelection(b)[1]); }); it('Finds comment range for empty comment form', () => { // Unimportant use case, just documenting how it behaves const a = docFromTextNotation('aaa (comment | ) bbb'); const b = docFromTextNotation('aaa (|comment| ) bbb'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Does not find comment range when comments are nested', () => { const a = docFromTextNotation('aaa (comment (comment [bbb ccc] | ddd))'); const b = docFromTextNotation('aaa (comment (comment |[bbb ccc]| ddd))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds comment range when current form is top level comment form', () => { const a = docFromTextNotation( @@ -884,33 +884,33 @@ describe('Token Cursor', () => { const b = docFromTextNotation( 'aaa (bbb (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar)) |(comment eee)|' ); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Includes reader tag', () => { const a = docFromTextNotation('aaa (comment #r [bbb ccc|] ddd)'); const b = docFromTextNotation('aaa (comment |#r [bbb ccc]| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds the preceding range when cursor is between to forms on the same line', () => { const a = docFromTextNotation('aaa (comment [bbb ccc] | ddd)'); const b = docFromTextNotation('aaa (comment |[bbb ccc]| ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds the succeeding range when cursor is at the start of the line', () => { const a = docFromTextNotation('aaa (comment [bbb ccc]• | ddd)'); const b = docFromTextNotation('aaa (comment [bbb ccc]• |ddd|)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Finds the preceding comment symbol range when cursor is between that and something else on the same line', () => { // This is a bit funny, but is not an important use case const a = docFromTextNotation('aaa (comment | [bbb ccc] ddd)'); const b = docFromTextNotation('aaa (|comment| [bbb ccc] ddd)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); - expect(cursor.rangeForDefun(a.selection.active)).toEqual(textAndSelection(b)[1]); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); + expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]); }); it('Can find the comment range for a top level form inside a comment', () => { const a = docFromTextNotation( @@ -920,25 +920,25 @@ describe('Token Cursor', () => { 'aaa |(comment (ccc •#foo•(#bar •#baz•[:a :b :c]•x•#(a b c))•#baz•yyy• z z z •foo• • bar))| (ddd eee)' ); const cursor: LispTokenCursor = a.getTokenCursor(0); - expect(cursor.rangeForDefun(a.selection.anchor, false)).toEqual(textAndSelection(b)[1]); + expect(cursor.rangeForDefun(a.selections[0].anchor, false)).toEqual(textAndSelection(b)[1]); }); it('Finds closest form inside multiple nested comments', () => { const a = docFromTextNotation('aaa (comment (comment [bbb ccc] | ddd))'); const b = docFromTextNotation('aaa (comment (comment |[bbb ccc]| ddd))'); const cursor: LispTokenCursor = a.getTokenCursor(0); - expect(cursor.rangeForDefun(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + expect(cursor.rangeForDefun(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('Finds the preceding range when cursor is between two forms on the same line', () => { const a = docFromTextNotation('aaa (comment [bbb ccc] | ddd)'); const b = docFromTextNotation('aaa (comment |[bbb ccc]| ddd)'); const cursor: LispTokenCursor = a.getTokenCursor(0); - expect(cursor.rangeForDefun(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + expect(cursor.rangeForDefun(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); it('Finds top level form when deref in comment', () => { const a = docFromTextNotation('(comment @(foo [bar|]))'); const b = docFromTextNotation('(comment |@(foo [bar])|)'); const cursor: LispTokenCursor = a.getTokenCursor(0); - expect(cursor.rangeForDefun(a.selection.anchor)).toEqual(textAndSelection(b)[1]); + expect(cursor.rangeForDefun(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]); }); }); }); @@ -947,14 +947,14 @@ describe('Token Cursor', () => { describe('getFunctionName', () => { it('Finds function name in the current list', () => { const a = docFromTextNotation('(foo [|])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.getFunctionName()).toEqual('foo'); }); it('Does not croak finding function name in unbalance', () => { // This hung the structural editing in the real editor // https://github.com/BetterThanTomorrow/calva/issues/1573 const a = docFromTextNotation('([|'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.getFunctionName()).toBeUndefined(); }); }); @@ -973,39 +973,39 @@ describe('Token Cursor', () => { describe('atTopLevel', () => { it('Returns true when at top level', () => { const a = docFromTextNotation('(foo []) |(bar :baz)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel()).toEqual(true); }); it('Returns true when at top level in rich comment if instructed so', () => { const a = docFromTextNotation('( comment (foo []) |(bar :baz))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel(true)).toEqual(true); }); it('Returns true when at a top level map in rich comment if instructed so', () => { const a = docFromTextNotation('( comment (foo []) |{bar :baz})'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel(true)).toEqual(true); }); // TODO: Figure out if this should be how it works // Related to: https://github.com/BetterThanTomorrow/calva/issues/2109 it('Returns true when at top level in rich comment if instructed so, even if comment is not at top level', () => { const a = docFromTextNotation('(a ( comment (foo []) |(bar :baz)))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel(true)).toEqual(true); }); it('Returns true when at a top level map in rich comment if instructed so, even if comment is not at top level', () => { const a = docFromTextNotation('(a ( comment (foo []) |{bar :baz}))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel(true)).toEqual(true); }); it('Returns false when at top level in rich comment if not instructed to treat it so', () => { const a = docFromTextNotation('( comment (foo []) |(bar :baz))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel()).toEqual(false); }); it('Returns false when not at top level', () => { const a = docFromTextNotation('(foo |[])'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.active); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active); expect(cursor.atTopLevel()).toEqual(false); }); }); @@ -1013,24 +1013,24 @@ describe('Token Cursor', () => { describe('docIsBalanced', () => { it('Reports balance for balanced structure', () => { const doc = docFromTextNotation('(a)•|(b)'); - const cursor: LispTokenCursor = doc.getTokenCursor(doc.selection.active); + const cursor: LispTokenCursor = doc.getTokenCursor(doc.selections[0].active); expect(cursor.docIsBalanced()).toBe(true); }); it('Detects unbalance when lacking opening brackets', () => { const doc = docFromTextNotation('(a)•|(b))'); - const cursor: LispTokenCursor = doc.getTokenCursor(doc.selection.active); + const cursor: LispTokenCursor = doc.getTokenCursor(doc.selections[0].active); expect(cursor.docIsBalanced()).toBe(false); }); // TODO: Fix this xit('Detects unbalance when lacking closing brackets', () => { const doc = docFromTextNotation('(a)•|(b'); - const cursor: LispTokenCursor = doc.getTokenCursor(doc.selection.active); + const cursor: LispTokenCursor = doc.getTokenCursor(doc.selections[0].active); expect(cursor.docIsBalanced()).toBe(false); }); // TODO: Fix this too xit('Detects unbalance when lacking man closing brackets', () => { const doc = docFromTextNotation('(a)•|([{((((b)'); - const cursor: LispTokenCursor = doc.getTokenCursor(doc.selection.active); + const cursor: LispTokenCursor = doc.getTokenCursor(doc.selections[0].active); expect(cursor.docIsBalanced()).toBe(false); }); }); @@ -1039,37 +1039,37 @@ describe('Token Cursor', () => { it('Finds current function start', () => { const a = docFromTextNotation('(a b |c)'); const b = docFromTextNotation('(|a b c)'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.backwardFunction()).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds current function start when nested', () => { const a = docFromTextNotation('(a b (c d|))'); const b = docFromTextNotation('(a b (|c d))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.backwardFunction()).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds current function start when nested and inside non-function', () => { const a = docFromTextNotation('(a b (c d [e f|]))'); const b = docFromTextNotation('(a b (|c d [e f]))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.backwardFunction()).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds current function start when nested in rich comment', () => { const a = docFromTextNotation('(comment a b (c d|))'); const b = docFromTextNotation('(comment a b (|c d))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.backwardFunction()).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); it('Finds parent function start', () => { const a = docFromTextNotation('(a b (c d|))'); const b = docFromTextNotation('(|a b (c d))'); - const cursor: LispTokenCursor = a.getTokenCursor(a.selection.anchor); + const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].anchor); expect(cursor.backwardFunction(1)).toBe(true); - expect(cursor.offsetStart).toBe(b.selection.anchor); + expect(cursor.offsetStart).toBe(b.selections[0].anchor); }); }); }); diff --git a/src/extension-test/unit/util/cursor-get-text-test.ts b/src/extension-test/unit/util/cursor-get-text-test.ts index 60aa70e6e..1715bc3b4 100644 --- a/src/extension-test/unit/util/cursor-get-text-test.ts +++ b/src/extension-test/unit/util/cursor-get-text-test.ts @@ -7,8 +7,8 @@ describe('get text', () => { it('Finds top level function at top', () => { const a = docFromTextNotation('(foo bar)•(deftest a-test• (baz |gaz))'); const b = docFromTextNotation('(foo bar)•(deftest |a-test|• (baz gaz))'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; - expect(getText.currentTopLevelDefined(a, a.selection.active)).toEqual([ + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; + expect(getText.currentTopLevelDefined(a, a.selections[0].active)).toEqual([ range, b.model.getText(...range), ]); @@ -17,8 +17,8 @@ describe('get text', () => { it('Finds top level function when nested', () => { const a = docFromTextNotation('(foo bar)•(with-test• (deftest a-test• (baz |gaz)))'); const b = docFromTextNotation('(foo bar)•(with-test• (deftest |a-test|• (baz gaz)))'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; - expect(getText.currentTopLevelDefined(a, a.selection.active)).toEqual([ + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; + expect(getText.currentTopLevelDefined(a, a.selections[0].active)).toEqual([ range, b.model.getText(...range), ]); @@ -28,8 +28,8 @@ describe('get text', () => { // https://github.com/BetterThanTomorrow/calva/issues/1086 const a = docFromTextNotation('(foo bar)•(with-test• (t/deftest a-test• (baz |gaz)))'); const b = docFromTextNotation('(foo bar)•(with-test• (t/deftest |a-test|• (baz gaz)))'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; - expect(getText.currentTopLevelDefined(a, a.selection.active)).toEqual([ + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; + expect(getText.currentTopLevelDefined(a, a.selections[0].active)).toEqual([ range, b.model.getText(...range), ]); @@ -38,8 +38,8 @@ describe('get text', () => { it('Finds top level function when function has metadata', () => { const a = docFromTextNotation('(foo bar)•(deftest ^{:some :thing} a-test• (baz |gaz))'); const b = docFromTextNotation('(foo bar)•(deftest ^{:some :thing} |a-test|• (baz gaz))'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; - expect(getText.currentTopLevelDefined(a, a.selection.active)).toEqual([ + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; + expect(getText.currentTopLevelDefined(a, a.selections[0].active)).toEqual([ range, b.model.getText(...range), ]); @@ -50,7 +50,7 @@ describe('get text', () => { it('Finds top level form', () => { const a = docFromTextNotation('(foo bar)•(deftest a-test• (baz |gaz))'); const b = docFromTextNotation('(foo bar)•|(deftest a-test• (baz gaz))|'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; expect(getText.currentTopLevelForm(a)).toEqual([range, b.model.getText(...range)]); }); }); @@ -59,7 +59,7 @@ describe('get text', () => { it('Current enclosing form from start to cursor, then folded', () => { const a = docFromTextNotation('(foo bar)•(deftest a-test• [baz ; f|oo• gaz])'); const b = docFromTextNotation('(foo bar)•(deftest a-test• |[baz| ; foo• gaz])'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; const trail = ']'; expect(getText.currentEnclosingFormToCursor(a)).toEqual([ range, @@ -72,7 +72,7 @@ describe('get text', () => { it('Finds top level form from start to cursor', () => { const a = docFromTextNotation('(foo bar)•(deftest a-test• [baz ; f|oo• gaz])'); const b = docFromTextNotation('(foo bar)•|(deftest a-test• [baz| ; foo• gaz])'); - const range: [number, number] = [b.selection.anchor, b.selection.active]; + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; const trail = '])'; expect(getText.currentTopLevelFormToCursor(a)).toEqual([ range, @@ -87,7 +87,7 @@ describe('get text', () => { const b = docFromTextNotation( '|(foo bar)•(deftest a-test• [baz| ; foo• gaz])•(bar baz)' ); - const range: [number, number] = [b.selection.anchor, b.selection.active]; + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; const trail = '])'; expect(getText.startOfFileToCursor(a)).toEqual([ range, @@ -101,7 +101,7 @@ describe('get text', () => { const b = docFromTextNotation( '|(foo bar)(comment• (deftest a-test• [baz| ; foo• gaz])•(bar baz))' ); - const range: [number, number] = [b.selection.anchor, b.selection.active]; + const range: [number, number] = [b.selections[0].anchor, b.selections[0].active]; const trail = ']))'; expect(getText.startOfFileToCursor(a)).toEqual([ range, @@ -113,7 +113,7 @@ describe('get text', () => { describe('selectionAddingBrackets', () => { it('Folds the missing brackets of the selection with brackets from the text behind the selection', () => { const doc = docFromTextNotation('(a b) |(c {:d [1 2 3|] :e :f} d) [4 5 6]'); - const range: [number, number] = [doc.selection.anchor, doc.selection.active]; + const range: [number, number] = [doc.selections[0].anchor, doc.selections[0].active]; const trail = ']})'; expect(getText.selectionAddingBrackets(doc)).toEqual([ range, diff --git a/src/lsp/commands/lsp-commands.ts b/src/lsp/commands/lsp-commands.ts index 411825b2d..5932d3acc 100644 --- a/src/lsp/commands/lsp-commands.ts +++ b/src/lsp/commands/lsp-commands.ts @@ -78,8 +78,8 @@ const getLSPCommandParams = () => { return; } - const line = editor.selection.start.line; - const column = editor.selection.start.character; + const line = editor.selections[0].start.line; + const column = editor.selections[0].start.character; const doc_uri = `${document.uri.scheme}://${document.uri.path}`; return [doc_uri, line, column]; }; @@ -126,12 +126,9 @@ function sendCommand(clients: defs.LspClientStore, command: string, args?: any[] const codeLensReferencesHandler: LSPCommandHandler = async (params) => { const [_, line, character] = params.args; - calva_utils.getActiveTextEditor().selection = new vscode.Selection( - line - 1, - character - 1, - line - 1, - character - 1 - ); + calva_utils.getActiveTextEditor().selections = [ + new vscode.Selection(line - 1, character - 1, line - 1, character - 1), + ]; await vscode.commands.executeCommand('editor.action.referenceSearch.trigger'); }; @@ -139,7 +136,7 @@ const resolveMacroAsCommandHandler: LSPCommandHandler = (params) => { const activeTextEditor = calva_utils.tryToGetActiveTextEditor(); if (activeTextEditor?.document?.languageId === 'clojure') { const documentUri = decodeURIComponent(activeTextEditor.document.uri.toString()); - const { line, character } = activeTextEditor.selection.active; + const { line, character } = activeTextEditor.selections[0].active; sendCommandRequest(params.clients, RESOLVE_MACRO_AS_COMMAND, [ documentUri, line + 1, diff --git a/src/nrepl/repl-start.ts b/src/nrepl/repl-start.ts index a3b4b9900..37acb4a64 100644 --- a/src/nrepl/repl-start.ts +++ b/src/nrepl/repl-start.ts @@ -250,7 +250,7 @@ export async function startStandaloneRepl( ); const firstPos = mainEditor.document.positionAt(0); - mainEditor.selection = new vscode.Selection(firstPos, firstPos); + mainEditor.selections = [new vscode.Selection(firstPos, firstPos)]; mainEditor.revealRange(new vscode.Range(firstPos, firstPos)); await vscode.window.showTextDocument(mainDoc, { preview: false, diff --git a/src/paredit/extension.ts b/src/paredit/extension.ts index d05a77b3a..2f71d9bb2 100644 --- a/src/paredit/extension.ts +++ b/src/paredit/extension.ts @@ -291,7 +291,7 @@ const pareditCommands: PareditCommand[] = [ await copyRangeToClipboard(doc, range); } await paredit.killForwardList(doc, range).then((isFulfilled) => { - return paredit.spliceSexp(doc, doc.selection.active, false); + return paredit.spliceSexp(doc, doc.selections[0].active, false); }); }, }, @@ -303,7 +303,7 @@ const pareditCommands: PareditCommand[] = [ await copyRangeToClipboard(doc, range); } await paredit.killBackwardList(doc, range).then((isFulfilled) => { - return paredit.spliceSexp(doc, doc.selection.active, false); + return paredit.spliceSexp(doc, doc.selections[0].active, false); }); }, }, diff --git a/src/providers/hover.ts b/src/providers/hover.ts index a09f48974..ebb2abab5 100644 --- a/src/providers/hover.ts +++ b/src/providers/hover.ts @@ -48,12 +48,12 @@ export async function provideHover( hoverLine: position.line + 1, hoverColumn: position.character + 1, hoverFilename: document.fileName, - currentLine: editor.selection.active.line, - currentColumn: editor.selection.active.character, + currentLine: editor.selections[0].active.line, + currentColumn: editor.selections[0].active.character, currentFilename: editor.document.fileName, - selection: editor.document.getText(editor.selection), + selection: editor.document.getText(editor.selections[0]), currentFileText: getText.currentFileText(editor.document), - ...getText.currentClojureContext(editor.document, editor.selection.active), + ...getText.currentClojureContext(editor.document, editor.selections[0].active), ...getText.currentClojureContext(document, position, 'hover'), }; diff --git a/src/results-output/repl-history.ts b/src/results-output/repl-history.ts index bd0f2d4af..a2d9a42de 100644 --- a/src/results-output/repl-history.ts +++ b/src/results-output/repl-history.ts @@ -17,7 +17,7 @@ let lastTextAtPrompt: string | undefined = undefined; function setReplHistoryCommandsActiveContext(editor: vscode.TextEditor): void { if (editor && util.getConnectedState() && isResultsDoc(editor.document)) { const document = editor.document; - const selection = editor.selection; + const selection = editor.selections[0]; const positionAtEndOfContent = document.positionAt( getIndexAfterLastNonWhitespace(document.getText()) ); diff --git a/src/results-output/results-doc.ts b/src/results-output/results-doc.ts index 8ac1a9262..0c4902e8d 100644 --- a/src/results-output/results-doc.ts +++ b/src/results-output/results-doc.ts @@ -188,7 +188,7 @@ export async function initResultsDoc(): Promise { const resultsEditor = await vscode.window.showTextDocument(resultsDoc, getViewColumn(), true); const firstPos = resultsEditor.document.positionAt(0); const lastPos = resultsDoc.positionAt(Infinity); - resultsEditor.selection = new vscode.Selection(lastPos, lastPos); + resultsEditor.selections = [new vscode.Selection(lastPos, lastPos)]; resultsEditor.revealRange(new vscode.Range(firstPos, firstPos)); } if (isInitialized) { @@ -238,7 +238,7 @@ export function setNamespaceFromCurrentFile() { const session = replSession.getSession(); const [ns, _] = namespace.getNamespace( util.tryToGetDocument({}), - vscode.window.activeTextEditor?.selection?.active + vscode.window.activeTextEditor?.selections[0]?.active ); setSession(session, ns); replSession.updateReplSessionType(); @@ -249,11 +249,11 @@ async function appendFormGrabbingSessionAndNS(topLevel: boolean) { const session = replSession.getSession(); const [ns, _] = namespace.getNamespace( util.tryToGetDocument({}), - vscode.window.activeTextEditor?.selection?.active + vscode.window.activeTextEditor?.selections[0]?.active ); const editor = util.getActiveTextEditor(); const doc = editor.document; - const selection = editor.selection; + const selection = editor.selections[0]; let code = ''; if (selection.isEmpty) { const formSelection = select.getFormSelection(doc, selection.active, topLevel); diff --git a/src/select.ts b/src/select.ts index 5daaf498e..5bcd4d2dd 100644 --- a/src/select.ts +++ b/src/select.ts @@ -49,12 +49,12 @@ function selectForm( ) { const editor = util.getActiveTextEditor(), doc = util.getDocument(document), - selection = editor.selection; + selection = editor.selections[0]; if (selection.isEmpty) { const codeSelection = selectionFn(doc, selection.active, toplevel); if (codeSelection) { - editor.selection = codeSelection; + editor.selections = [codeSelection]; } } } diff --git a/src/testRunner.ts b/src/testRunner.ts index d5a781eac..142e6df63 100644 --- a/src/testRunner.ts +++ b/src/testRunner.ts @@ -322,7 +322,7 @@ async function runNamespaceTests(controller: vscode.TestController, document: vs const session = getSession(util.getFileType(document)); const [currentDocNs, _] = namespace.getNamespace( doc, - vscode.window.activeTextEditor?.selection?.active + vscode.window.activeTextEditor?.selections[0]?.active ); await loadTestNS(currentDocNs, session); const namespacesToRunTestsFor = [ @@ -335,14 +335,17 @@ async function runNamespaceTests(controller: vscode.TestController, document: vs function getTestUnderCursor() { const editor = util.tryToGetActiveTextEditor(); if (editor) { - return getText.currentTopLevelDefined(editor?.document, editor?.selection.active)[1]; + return getText.currentTopLevelDefined(editor?.document, editor?.selections[0].active)[1]; } } async function runTestUnderCursor(controller: vscode.TestController) { const doc = util.tryToGetDocument({}); const session = getSession(util.getFileType(doc)); - const [ns, _] = namespace.getNamespace(doc, vscode.window.activeTextEditor?.selection?.active); + const [ns, _] = namespace.getNamespace( + doc, + vscode.window.activeTextEditor?.selections[0]?.active + ); const test = getTestUnderCursor(); if (test) { diff --git a/src/util/cursor-get-text.ts b/src/util/cursor-get-text.ts index 3e8a96024..f72ee91a1 100644 --- a/src/util/cursor-get-text.ts +++ b/src/util/cursor-get-text.ts @@ -8,7 +8,7 @@ export type RangeAndText = [[number, number], string] | [undefined, '']; export function currentTopLevelDefined( doc: EditableDocument, - active: number = doc.selection.active + active: number = doc.selections[0].active ): RangeAndText { const defunCursor = doc.getTokenCursor(active); const defunStart = defunCursor.rangeForDefun(active)[0]; @@ -34,8 +34,8 @@ export function currentTopLevelDefined( } export function currentTopLevelForm(doc: EditableDocument): RangeAndText { - const defunCursor = doc.getTokenCursor(doc.selection.active); - const defunRange = defunCursor.rangeForDefun(doc.selection.active); + const defunCursor = doc.getTokenCursor(doc.selections[0].active); + const defunRange = defunCursor.rangeForDefun(doc.selections[0].active); return defunRange ? [defunRange, doc.model.getText(...defunRange)] : [undefined, '']; } @@ -64,25 +64,25 @@ function rangeToCursor( } export function currentEnclosingFormToCursor(doc: EditableDocument): RangeAndText { - const cursor = doc.getTokenCursor(doc.selection.active); + const cursor = doc.getTokenCursor(doc.selections[0].active); const enclosingRange = cursor.rangeForList(1); - return rangeToCursor(doc, enclosingRange, enclosingRange[0], doc.selection.active); + return rangeToCursor(doc, enclosingRange, enclosingRange[0], doc.selections[0].active); } export function currentTopLevelFormToCursor(doc: EditableDocument): RangeAndText { - const cursor = doc.getTokenCursor(doc.selection.active); - const defunRange = cursor.rangeForDefun(doc.selection.active); - return rangeToCursor(doc, defunRange, defunRange[0], doc.selection.active); + const cursor = doc.getTokenCursor(doc.selections[0].active); + const defunRange = cursor.rangeForDefun(doc.selections[0].active); + return rangeToCursor(doc, defunRange, defunRange[0], doc.selections[0].active); } export function startOfFileToCursor(doc: EditableDocument): RangeAndText { - const cursor = doc.getTokenCursor(doc.selection.active); - const defunRange = cursor.rangeForDefun(doc.selection.active, false); - return rangeToCursor(doc, defunRange, 0, doc.selection.active); + const cursor = doc.getTokenCursor(doc.selections[0].active); + const defunRange = cursor.rangeForDefun(doc.selections[0].active, false); + return rangeToCursor(doc, defunRange, 0, doc.selections[0].active); } export function selectionAddingBrackets(doc: EditableDocument): RangeAndText { - const [left, right] = [doc.selection.anchor, doc.selection.active].sort((a, b) => a - b); + const [left, right] = [doc.selections[0].anchor, doc.selections[0].active].sort((a, b) => a - b); const cursor = doc.getTokenCursor(left); cursor.forwardSexp(true, true, true); const rangeEnd = cursor.offsetStart; diff --git a/src/util/get-text.ts b/src/util/get-text.ts index c475d75d0..616f0904c 100644 --- a/src/util/get-text.ts +++ b/src/util/get-text.ts @@ -69,7 +69,7 @@ export function _currentFunction(doc: vscode.TextDocument, topLevel = false): Se const tokenCursor = cursorDoc.getTokenCursor(); if (topLevel) { tokenCursor.set( - cursorDoc.getTokenCursor(tokenCursor.rangeForDefun(cursorDoc.selection.active)[1] - 1) + cursorDoc.getTokenCursor(tokenCursor.rangeForDefun(cursorDoc.selections[0].active)[1] - 1) ); } const [start, end] = tokenCursor.getFunctionSexpRange(); diff --git a/src/util/ns-form.ts b/src/util/ns-form.ts index 15dd3f08a..d8b4d6d19 100644 --- a/src/util/ns-form.ts +++ b/src/util/ns-form.ts @@ -50,7 +50,7 @@ function nsSymbolOfCurrentForm( export function nsFromCursorDoc( cursorDoc: model.EditableDocument, - p: number = cursorDoc.selection.active, + p: number = cursorDoc.selections[0].active, _maxRecursionDepth: number = 100, // used internally for recursion _depth: number = 0 // used internally for recursion ): [string, string] | null { diff --git a/src/utilities.ts b/src/utilities.ts index 984247db4..4fa255c7e 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -385,7 +385,7 @@ function filterVisibleRanges( function scrollToBottom(editor: vscode.TextEditor) { const lastPos = editor.document.positionAt(Infinity); - editor.selection = new vscode.Selection(lastPos, lastPos); + editor.selections = [new vscode.Selection(lastPos, lastPos)]; editor.revealRange(new vscode.Range(lastPos, lastPos)); } diff --git a/src/when-contexts.ts b/src/when-contexts.ts index 29f1be164..94a2e81f7 100644 --- a/src/when-contexts.ts +++ b/src/when-contexts.ts @@ -16,7 +16,7 @@ export function setCursorContextIfChanged(editor: vscode.TextEditor) { ) { return; } - const contexts = determineCursorContexts(editor.document, editor.selection.active); + const contexts = determineCursorContexts(editor.document, editor.selections[0].active); setCursorContexts(contexts); }