Skip to content

Commit aad313b

Browse files
AndreasArvidssonpokeyphillco
authored
Added explicit mark (#1578)
Fixes #1577 ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [ ] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [ ] I have not broken the cheatsheet --------- Co-authored-by: Pokey Rule <[email protected]> Co-authored-by: Phil Cohen <[email protected]>
1 parent 5ad9ac9 commit aad313b

File tree

4 files changed

+110
-3
lines changed

4 files changed

+110
-3
lines changed

packages/common/src/types/command/PartialTargetDescriptor.types.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,37 @@ export interface RangeMark {
4343
excludeActive?: boolean;
4444
}
4545

46+
interface SimplePosition {
47+
readonly line: number;
48+
readonly character: number;
49+
}
50+
51+
interface SimpleRange {
52+
readonly start: SimplePosition;
53+
readonly end: SimplePosition;
54+
}
55+
56+
/**
57+
* Used to explicitly provide a range for use as a mark. Today, this mark type
58+
* is only used as a hack to enable us to support allowing other editors to
59+
* maintain their own hat map when using the Cursorless "sidecar"; see
60+
* https://github.com/cursorless-everywhere/notes for more information.
61+
*/
62+
export interface ExplicitMark {
63+
type: "explicit";
64+
editorId: string;
65+
range: SimpleRange;
66+
}
67+
4668
export type PartialMark =
4769
| CursorMark
4870
| ThatMark
4971
| SourceMark
5072
| DecoratedSymbolMark
5173
| NothingMark
5274
| LineNumberMark
53-
| RangeMark;
75+
| RangeMark
76+
| ExplicitMark;
5477

5578
export type SimpleSurroundingPairName =
5679
| "angleBrackets"

packages/cursorless-engine/src/processTargets/MarkStageFactoryImpl.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { ReadOnlyHatMap } from "@cursorless/common";
2+
import { TargetPipelineRunner } from ".";
23
import { StoredTargetMap } from "..";
4+
import { Mark } from "../typings/TargetDescriptor";
35
import { MarkStageFactory } from "./MarkStageFactory";
46
import { MarkStage } from "./PipelineStages.types";
57
import CursorStage from "./marks/CursorStage";
68
import DecoratedSymbolStage from "./marks/DecoratedSymbolStage";
9+
import ExplicitMarkStage from "./marks/ExplicitMarkStage";
710
import LineNumberStage from "./marks/LineNumberStage";
811
import NothingStage from "./marks/NothingStage";
912
import RangeMarkStage from "./marks/RangeMarkStage";
1013
import { StoredTargetStage } from "./marks/StoredTargetStage";
11-
import { Mark } from "../typings/TargetDescriptor";
12-
import { TargetPipelineRunner } from ".";
1314
import { TargetMarkStage } from "./marks/TargetMarkStage";
1415

1516
export class MarkStageFactoryImpl implements MarkStageFactory {
@@ -43,6 +44,8 @@ export class MarkStageFactoryImpl implements MarkStageFactory {
4344
return new NothingStage(mark);
4445
case "target":
4546
return new TargetMarkStage(this.targetPipelineRunner, mark);
47+
case "explicit":
48+
return new ExplicitMarkStage(mark);
4649
}
4750
}
4851
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ExplicitMark, Range } from "@cursorless/common";
2+
import { Target } from "../../typings/target.types";
3+
import { MarkStage } from "../PipelineStages.types";
4+
import { UntypedTarget } from "../targets";
5+
import { ide } from "../../singletons/ide.singleton";
6+
7+
export default class implements MarkStage {
8+
constructor(private mark: ExplicitMark) {}
9+
10+
run(): Target[] {
11+
const {
12+
editorId,
13+
range: { start, end },
14+
} = this.mark;
15+
16+
const editor = ide().visibleTextEditors.find((e) => e.id === editorId);
17+
18+
if (editor == null) {
19+
throw new Error(`Couldn't find editor '${editorId}'`);
20+
}
21+
22+
const contentRange = new Range(
23+
start.line,
24+
start.character,
25+
end.line,
26+
end.character,
27+
);
28+
29+
return [
30+
new UntypedTarget({
31+
editor,
32+
contentRange,
33+
isReversed: false,
34+
hasExplicitRange: false,
35+
}),
36+
];
37+
}
38+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
getCursorlessApi,
3+
openNewEditor,
4+
runCursorlessCommand,
5+
} from "@cursorless/vscode-common";
6+
import * as assert from "assert";
7+
import { Selection } from "vscode";
8+
import { endToEndTestSetup } from "../endToEndTestSetup";
9+
10+
suite("Explicit mark", async function () {
11+
endToEndTestSetup(this);
12+
13+
test("Clear explicit mark", explicitMark);
14+
});
15+
16+
async function explicitMark() {
17+
const { ide } = (await getCursorlessApi()).testHelpers!;
18+
const editor = await openNewEditor("foo bar baz");
19+
const editorId = ide.visibleTextEditors[0].id;
20+
21+
await runCursorlessCommand({
22+
version: 6,
23+
usePrePhraseSnapshot: false,
24+
action: {
25+
name: "clearAndSetSelection",
26+
target: {
27+
type: "primitive",
28+
mark: {
29+
type: "explicit",
30+
editorId,
31+
range: {
32+
start: { line: 0, character: 4 },
33+
end: { line: 0, character: 7 },
34+
},
35+
},
36+
},
37+
},
38+
});
39+
40+
assert.equal(editor.document.getText(), "foo baz");
41+
assert.equal(editor.selections.length, 1);
42+
assert.ok(editor.selections[0].isEqual(new Selection(0, 4, 0, 4)));
43+
}

0 commit comments

Comments
 (0)