Skip to content

Commit 94dadfc

Browse files
AndreasArvidssonpre-commit-ci[bot]pokey
authored
Implement our own types instead of vscode (#1128)
* Started working on our own replacement for vscode types * remove unused imports * More workl * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * more changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * More stuff * Stuff stuff * Some super secret clean up stuff * Additional changes beyond human comprehension * clean up * Trans dimensional super fixes * Mind boggling changes * Hopefully done with this suffering * Fixed circular dependencies * Updated fake ide * Added test for position * Added range test * Added getter to vscode editable editor implementation * Convert position * Added text line implementation * Better handling of selections * group document by uri * Remove on use to vscode converter * Clean up tests * Make sure functions use arrow format * Use weak map to keep track of text editors * cleanup * empty * use arrow functions * updated lock file * restore normal methods for position and range * Remove arrow expressions as method * added is active on the text editor * Error when trying to deselect all selections * added types * Make use of `@cursorless` imports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Moved vscode utilities * update * Fixed stupid bug * empty * stuff * stuff * Added to empty range on position * cleaned up vscode edit * clean up * clean up vscode focus editor * move creation of text editors into ide * cleanup * moved get node at location into editor * empty * remove spread * Add license reference * use full vscode implementation * Revert "moved get node at location into editor" This reverts commit 4c2ec1c. * remove location type * Switch `getNodeAtLocation` to use document * Use editable editor for performing edits * Add `ide` reference to editable text editor * docs * Tweak * tweak * Fix bug with id / editor generation * Remove unnecessary functions * Tweak name * merged vscode text editor implementations * Add back comments about range adjustment * Tweak docstrings * docs * add a couple tests * Updated line behavior * Test tweaks * updated behavior * added selection isEqual * `isEqual` => `isRangeEqual` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * cleanup * Capture more unit tests in launch config * move `openNewEditor` * Basic `TextLine` test * Selection + more range tests * yarn.lock tweak * more line tests Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com>
1 parent 255e889 commit 94dadfc

File tree

164 files changed

+2629
-1090
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+2629
-1090
lines changed

.eslintrc.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,7 @@
4848
}
4949
],
5050
"no-throw-literal": "warn",
51-
"semi": "off",
52-
"no-restricted-properties": [
53-
2,
54-
{
55-
"property": "activeTextEditor"
56-
}
57-
]
51+
"semi": "off"
5852
},
5953
"ignorePatterns": ["**/vendor/**/*.ts", "**/vendor/**/*.js"]
6054
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,18 +590,20 @@
590590
"@types/chai": "^4.3.3",
591591
"@types/glob": "^7.1.3",
592592
"@types/js-yaml": "^4.0.2",
593+
"@types/lodash": "^4.14.168",
593594
"@types/mocha": "^8.0.4",
594595
"@types/node": "^16.11.3",
595596
"@types/semver": "^7.3.9",
596597
"@types/sinon": "^10.0.2",
598+
"@types/uuid": "^8.3.4",
597599
"@types/vscode": "~1.61.0",
598600
"@typescript-eslint/eslint-plugin": "^5.20.0",
599601
"@typescript-eslint/parser": "^5.20.0",
600602
"@vscode/test-electron": "^2.1.3",
601603
"chai": "^4.3.6",
602604
"esbuild": "^0.11.12",
603-
"eslint": "^8.13.0",
604605
"eslint-config-prettier": "^8.5.0",
606+
"eslint": "^8.13.0",
605607
"fast-xml-parser": "^3.20.0",
606608
"glob": "^7.1.7",
607609
"js-yaml": "^4.1.0",
@@ -615,12 +617,12 @@
615617
"typescript": "4.6.3"
616618
},
617619
"dependencies": {
618-
"@types/lodash": "^4.14.168",
619620
"immer": "^9.0.15",
620621
"immutability-helper": "^3.1.1",
621622
"itertools": "^1.7.1",
622623
"lodash": "^4.17.21",
623624
"node-html-parser": "^5.3.3",
625+
"uuid": "^9.0.0",
624626
"vscode-uri": "^3.0.6"
625627
}
626628
}

src/actions/BringMoveSwap.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
import { Selection, TextEditor } from "@cursorless/common";
12
import { flatten } from "lodash";
2-
import { DecorationRangeBehavior, Selection, TextEditor } from "vscode";
3+
import { DecorationRangeBehavior } from "vscode";
34
import {
45
getSelectionInfo,
56
performEditsAndUpdateFullSelectionInfos,
67
} from "../core/updateSelections/updateSelections";
8+
import ide from "../libs/cursorless-engine/singletons/ide.singleton";
79
import { Target } from "../typings/target.types";
810
import { EditWithRangeUpdater, Graph } from "../typings/Types";
9-
import { selectionFromRange } from "../util/selectionUtils";
1011
import { setSelectionsWithoutFocusingEditor } from "../util/setSelectionsAndFocusEditor";
1112
import { getContentRange, runForEachEditor } from "../util/targetUtils";
1213
import { unifyRemovalTargets } from "../util/unifyRanges";
@@ -167,7 +168,7 @@ class BringMoveSwap implements Action {
167168
({ edit: { range }, originalTarget }) =>
168169
getSelectionInfo(
169170
editor.document,
170-
selectionFromRange(originalTarget.isReversed, range),
171+
range.toSelection(originalTarget.isReversed),
171172
DecorationRangeBehavior.OpenOpen,
172173
),
173174
);
@@ -180,26 +181,28 @@ class BringMoveSwap implements Action {
180181
),
181182
);
182183

184+
const editableEditor = ide().getEditableTextEditor(editor);
185+
183186
const [updatedEditSelections, cursorSelections]: Selection[][] =
184187
await performEditsAndUpdateFullSelectionInfos(
185188
this.graph.rangeUpdater,
186-
editor,
189+
editableEditor,
187190
filteredEdits.map(({ edit }) => edit),
188191
[editSelectionInfos, cursorSelectionInfos],
189192
);
190193

191194
// NB: We set the selections here because we don't trust vscode to
192195
// properly move the cursor on a bring. Sometimes it will smear an
193196
// empty selection
194-
setSelectionsWithoutFocusingEditor(editor, cursorSelections);
197+
setSelectionsWithoutFocusingEditor(editableEditor, cursorSelections);
195198

196199
return edits.map((edit, index): MarkEntry => {
197200
const selection = updatedEditSelections[index];
198201
const range = edit.edit.updateRange(selection);
199202
const target = edit.originalTarget;
200203
return {
201204
editor,
202-
selection: selectionFromRange(target.isReversed, range),
205+
selection: range.toSelection(target.isReversed),
203206
isSource: edit.isSource,
204207
target,
205208
};

src/actions/Clear.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ide from "../libs/cursorless-engine/singletons/ide.singleton";
12
import { PlainTarget } from "../processTargets/targets";
23
import { Target } from "../typings/target.types";
34
import { Graph } from "../typings/Types";
@@ -29,7 +30,7 @@ export default class Clear implements Action {
2930

3031
if (thatMark != null) {
3132
await setSelectionsAndFocusEditor(
32-
editor,
33+
ide().getEditableTextEditor(editor),
3334
thatMark.map(({ selection }) => selection),
3435
);
3536
}

src/actions/CommandAction.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { flatten } from "lodash";
22
import { commands } from "vscode";
33
import { selectionToThatTarget } from "../core/commandRunner/selectionToThatTarget";
44
import { callFunctionAndUpdateSelections } from "../core/updateSelections/updateSelections";
5+
import ide from "../libs/cursorless-engine/singletons/ide.singleton";
56
import { Target } from "../typings/target.types";
67
import { Graph } from "../typings/Types";
78
import {
8-
focusEditor,
99
setSelectionsAndFocusEditor,
1010
setSelectionsWithoutFocusingEditor,
1111
} from "../util/setSelectionsAndFocusEditor";
@@ -15,7 +15,6 @@ import {
1515
runOnTargetsForEachEditor,
1616
} from "../util/targetUtils";
1717
import { Action, ActionReturnValue } from "./actions.types";
18-
import { getActiveTextEditor } from "../ide/vscode/activeTextEditor";
1918

2019
export interface CommandOptions {
2120
command?: string;
@@ -53,7 +52,11 @@ export default class CommandAction implements Action {
5352
);
5453

5554
// For command to the work we have to have the correct editor focused
56-
await setSelectionsAndFocusEditor(editor, targetSelections, false);
55+
await setSelectionsAndFocusEditor(
56+
ide().getEditableTextEditor(editor),
57+
targetSelections,
58+
false,
59+
);
5760

5861
const [updatedOriginalSelections, updatedTargetSelections] =
5962
await callFunctionAndUpdateSelections(
@@ -70,7 +73,10 @@ export default class CommandAction implements Action {
7073
// very end. This code can run on multiple editors in the course of
7174
// one command, so we want to avoid focusing the editor multiple
7275
// times.
73-
setSelectionsWithoutFocusingEditor(editor, updatedOriginalSelections);
76+
setSelectionsWithoutFocusingEditor(
77+
ide().getEditableTextEditor(editor),
78+
updatedOriginalSelections,
79+
);
7480
}
7581

7682
// If the document hasn't changed then we just return the original targets
@@ -120,7 +126,7 @@ export default class CommandAction implements Action {
120126
ensureSingleTarget(targets);
121127
}
122128

123-
const originalEditor = getActiveTextEditor();
129+
const originalEditor = ide().activeEditableTextEditor;
124130

125131
const thatTargets = await this.runCommandAndUpdateSelections(
126132
targets,
@@ -131,12 +137,12 @@ export default class CommandAction implements Action {
131137
if (
132138
actualOptions.restoreSelection &&
133139
originalEditor != null &&
134-
originalEditor !== getActiveTextEditor()
140+
!originalEditor.isActive
135141
) {
136142
// NB: We just do one editor focus at the end, instead of using
137143
// setSelectionsAndFocusEditor because the command might operate on
138144
// multiple editors, so we just do one focus at the end.
139-
await focusEditor(originalEditor);
145+
await originalEditor.focus();
140146
}
141147

142148
return { thatTargets };

src/actions/Deselect.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Selection } from "vscode";
1+
import ide from "../libs/cursorless-engine/singletons/ide.singleton";
22
import { Target } from "../typings/target.types";
33
import { Graph } from "../typings/Types";
44
import { setSelectionsWithoutFocusingEditor } from "../util/setSelectionsAndFocusEditor";
@@ -20,12 +20,14 @@ export default class Deselect implements Action {
2020
return intersection && (!intersection.isEmpty || selection.isEmpty);
2121
}),
2222
);
23-
// The editor requires at least one selection. Keep "primary" selection active
23+
24+
if (newSelections.length === 0) {
25+
throw new SelectionRequiredError();
26+
}
27+
2428
setSelectionsWithoutFocusingEditor(
25-
editor,
26-
newSelections.length > 0
27-
? newSelections
28-
: [new Selection(editor.selection.active, editor.selection.active)],
29+
ide().getEditableTextEditor(editor),
30+
newSelections,
2931
);
3032
});
3133

@@ -34,3 +36,10 @@ export default class Deselect implements Action {
3436
};
3537
}
3638
}
39+
40+
class SelectionRequiredError extends Error {
41+
constructor() {
42+
super("Can't deselect every selection. At least one is required");
43+
this.name = "SelectionRequiredError";
44+
}
45+
}

src/actions/EditNew/EditNew.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1+
import ide from "../../libs/cursorless-engine/singletons/ide.singleton";
12
import { containingLineIfUntypedStage } from "../../processTargets/modifiers/commonContainingScopeIfUntypedStages";
23
import PositionStage from "../../processTargets/modifiers/PositionStage";
34
import { ModifierStage } from "../../processTargets/PipelineStages.types";
45
import { Target } from "../../typings/target.types";
56
import { Graph } from "../../typings/Types";
6-
import { selectionFromRange } from "../../util/selectionUtils";
77
import { setSelectionsAndFocusEditor } from "../../util/setSelectionsAndFocusEditor";
88
import { createThatMark, ensureSingleEditor } from "../../util/targetUtils";
99
import { Action, ActionReturnValue } from "../actions.types";
1010
import { State } from "./EditNew.types";
11-
import { runNotebookCellTargets } from "./runNotebookCellTargets";
1211
import { runCommandTargets } from "./runCommandTargets";
1312
import { runEditTargets } from "./runEditTargets";
13+
import { runNotebookCellTargets } from "./runNotebookCellTargets";
1414

1515
export class EditNew implements Action {
1616
getFinalStages(): ModifierStage[] {
@@ -29,7 +29,9 @@ export class EditNew implements Action {
2929
return runNotebookCellTargets(this.graph, targets);
3030
}
3131

32-
const editor = ensureSingleEditor(targets);
32+
const editableEditor = ide().getEditableTextEditor(
33+
ensureSingleEditor(targets),
34+
);
3335

3436
/**
3537
* Keeps track of the desired cursor positions and "that" marks as we
@@ -41,13 +43,13 @@ export class EditNew implements Action {
4143
cursorRanges: new Array(targets.length).fill(undefined) as undefined[],
4244
};
4345

44-
state = await runCommandTargets(this.graph, editor, state);
45-
state = await runEditTargets(this.graph, editor, state);
46+
state = await runCommandTargets(this.graph, editableEditor, state);
47+
state = await runEditTargets(this.graph, editableEditor, state);
4648

4749
const newSelections = state.targets.map((target, index) =>
48-
selectionFromRange(target.isReversed, state.cursorRanges[index]!),
50+
state.cursorRanges[index]!.toSelection(target.isReversed),
4951
);
50-
await setSelectionsAndFocusEditor(editor, newSelections);
52+
await setSelectionsAndFocusEditor(editableEditor, newSelections);
5153

5254
return {
5355
thatSelections: createThatMark(state.targets, state.thatRanges),

src/actions/EditNew/EditNew.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Range } from "vscode";
2-
import { Target } from "../../typings/target.types";
1+
import type { Range } from "@cursorless/common";
2+
import type { Target } from "../../typings/target.types";
33

44
/**
55
* Internal type to be used for storing a reference to a target that will use a

src/actions/EditNew/runCommandTargets.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { commands, TextEditor } from "vscode";
1+
import { EditableTextEditor } from "@cursorless/common";
2+
import { commands } from "vscode";
23
import { callFunctionAndUpdateRanges } from "../../core/updateSelections/updateSelections";
34
import { Graph } from "../../typings/Types";
45
import { CommandTarget, State } from "./EditNew.types";
@@ -16,7 +17,7 @@ import { CommandTarget, State } from "./EditNew.types";
1617
*/
1718
export async function runCommandTargets(
1819
graph: Graph,
19-
editor: TextEditor,
20+
editor: EditableTextEditor,
2021
state: State,
2122
): Promise<State> {
2223
const commandTargets: CommandTarget[] = state.targets

src/actions/EditNew/runEditTargets.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { Selection, EditableTextEditor } from "@cursorless/common";
12
import { zip } from "lodash";
2-
import { DecorationRangeBehavior, Range, Selection, TextEditor } from "vscode";
3+
import { DecorationRangeBehavior } from "vscode";
34
import { performEditsAndUpdateSelectionsWithBehavior } from "../../core/updateSelections/updateSelections";
45
import { Graph } from "../../typings/Types";
56
import { EditTarget, State } from "./EditNew.types";
@@ -19,7 +20,7 @@ import { EditTarget, State } from "./EditNew.types";
1920
*/
2021
export async function runEditTargets(
2122
graph: Graph,
22-
editor: TextEditor,
23+
editor: EditableTextEditor,
2324
state: State,
2425
): Promise<State> {
2526
const editTargets: EditTarget[] = state.targets
@@ -43,7 +44,7 @@ export async function runEditTargets(
4344
);
4445

4546
const thatSelections = {
46-
selections: state.thatRanges.map(toSelection),
47+
selections: state.thatRanges.map((r) => r.toSelection(false)),
4748
};
4849

4950
// We need to remove undefined cursor locations. Note that these undefined
@@ -57,11 +58,11 @@ export async function runEditTargets(
5758
const cursorIndices = cursorInfos.map(({ index }) => index);
5859

5960
const cursorSelections = {
60-
selections: cursorInfos.map(({ range }) => toSelection(range!)),
61+
selections: cursorInfos.map(({ range }) => range!.toSelection(false)),
6162
};
6263

6364
const editSelections = {
64-
selections: edits.map((edit) => toSelection(edit.range)),
65+
selections: edits.map((edit) => edit.range.toSelection(false)),
6566
rangeBehavior: DecorationRangeBehavior.OpenOpen,
6667
};
6768

@@ -96,7 +97,3 @@ export async function runEditTargets(
9697
cursorRanges: updatedCursorRanges,
9798
};
9899
}
99-
100-
function toSelection(range: Range) {
101-
return new Selection(range.start, range.end);
102-
}

src/actions/EditNew/runNotebookCellTargets.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { commands, Selection } from "vscode";
1+
import { Selection } from "@cursorless/common";
2+
import { commands } from "vscode";
23
import { NotebookCellPositionTarget } from "../../processTargets/targets";
34
import { Target } from "../../typings/target.types";
45
import { Graph } from "../../typings/Types";
@@ -20,8 +21,8 @@ export async function runNotebookCellTargets(
2021
// Inserting a new jupyter cell above pushes the previous one down two lines
2122
if (command === "jupyter.insertCellAbove") {
2223
thatMark[0].selection = new Selection(
23-
thatMark[0].selection.anchor.translate({ lineDelta: 2 }),
24-
thatMark[0].selection.active.translate({ lineDelta: 2 }),
24+
thatMark[0].selection.anchor.translate(2, undefined),
25+
thatMark[0].selection.active.translate(2, undefined),
2526
);
2627
}
2728

0 commit comments

Comments
 (0)