Skip to content

Commit 74d8afc

Browse files
Automatically expand removal for Tree sitter targets
1 parent ab072ee commit 74d8afc

File tree

2 files changed

+94
-8
lines changed

2 files changed

+94
-8
lines changed

packages/cursorless-engine/src/processTargets/targets/ScopeTypeTarget.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import type { Range, SimpleScopeTypeType } from "@cursorless/common";
2+
import type { Target } from "../../typings/target.types";
23
import type { CommonTargetParameters } from "./BaseTarget";
34
import { BaseTarget } from "./BaseTarget";
45
import { InteriorTarget } from "./InteriorTarget";
56
import { PlainTarget } from "./PlainTarget";
6-
import type { Target } from "../../typings/target.types";
77
import {
88
createContinuousRange,
99
createContinuousRangeFromRanges,
1010
} from "./util/createContinuousRange";
11-
import { getDelimitedSequenceRemovalRange } from "./util/insertionRemovalBehaviors/DelimitedSequenceInsertionRemovalBehavior";
11+
import {
12+
getDelimitedSequenceRemovalRange,
13+
getSmartRemovalTarget,
14+
} from "./util/insertionRemovalBehaviors/DelimitedSequenceInsertionRemovalBehavior";
1215
import {
1316
getTokenLeadingDelimiterTarget,
14-
getTokenRemovalRange,
1517
getTokenTrailingDelimiterTarget,
1618
} from "./util/insertionRemovalBehaviors/TokenInsertionRemovalBehavior";
1719

@@ -93,11 +95,23 @@ export class ScopeTypeTarget extends BaseTarget<ScopeTypeTargetParameters> {
9395
}
9496

9597
getRemovalRange(): Range {
96-
return this.removalRange_ != null
97-
? this.removalRange_
98-
: this.hasDelimiterRange_
99-
? getDelimitedSequenceRemovalRange(this)
100-
: getTokenRemovalRange(this);
98+
if (this.removalRange_ != null) {
99+
return this.removalRange_;
100+
}
101+
if (this.hasDelimiterRange_) {
102+
return getDelimitedSequenceRemovalRange(this);
103+
}
104+
return getSmartRemovalTarget(this).getRemovalRange();
105+
}
106+
107+
getRemovalHighlightRange(): Range {
108+
if (this.removalRange_ != null) {
109+
return this.removalRange_;
110+
}
111+
if (this.hasDelimiterRange_) {
112+
return getDelimitedSequenceRemovalRange(this);
113+
}
114+
return getSmartRemovalTarget(this).getRemovalHighlightRange();
101115
}
102116

103117
maybeCreateRichRangeTarget(
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import type { Range, TextDocument, TextEditor } from "@cursorless/common";
2+
import type { Target } from "../../../../typings/target.types";
3+
import { shrinkRangeToFitContent } from "../../../../util/selectionUtils";
4+
import { DocumentTarget } from "../../DocumentTarget";
5+
import { LineTarget } from "../../LineTarget";
6+
import { ParagraphTarget } from "../../ParagraphTarget";
7+
import { TokenTarget } from "../../TokenTarget";
8+
import { union } from "../../../../util/rangeUtils";
9+
10+
export function getSmartRemovalTarget(target: Target): Target {
11+
const { editor, isReversed } = target;
12+
const { document } = editor;
13+
const contentRange = union(target.contentRange, target.prefixRange);
14+
15+
if (!isLine(document, contentRange)) {
16+
return new TokenTarget({
17+
editor,
18+
isReversed,
19+
contentRange: contentRange,
20+
});
21+
}
22+
23+
if (isDocument(editor, contentRange)) {
24+
return new DocumentTarget({
25+
editor,
26+
isReversed,
27+
contentRange: document.range,
28+
});
29+
}
30+
31+
if (isParagraph(document, contentRange)) {
32+
return new ParagraphTarget({
33+
editor,
34+
isReversed,
35+
contentRange: contentRange,
36+
});
37+
}
38+
39+
return new LineTarget({
40+
editor,
41+
isReversed,
42+
contentRange: contentRange,
43+
});
44+
}
45+
46+
function isLine(document: TextDocument, contentRange: Range): boolean {
47+
const start = document.lineAt(contentRange.start).rangeTrimmed?.start;
48+
const end = document.lineAt(contentRange.end).rangeTrimmed?.end;
49+
return (
50+
start != null &&
51+
end != null &&
52+
start.isEqual(contentRange.start) &&
53+
end.isEqual(contentRange.end)
54+
);
55+
}
56+
57+
function isParagraph(document: TextDocument, contentRange: Range): boolean {
58+
const { start, end } = contentRange;
59+
return (
60+
(start.line === 0 || document.lineAt(start.line - 1).isEmptyOrWhitespace) &&
61+
(end.line === document.lineCount - 1 ||
62+
document.lineAt(end.line + 1).isEmptyOrWhitespace)
63+
);
64+
}
65+
66+
function isDocument(editor: TextEditor, contentRange: Range): boolean {
67+
const documentContentRange = shrinkRangeToFitContent(
68+
editor,
69+
editor.document.range,
70+
);
71+
return documentContentRange.isRangeEqual(contentRange);
72+
}

0 commit comments

Comments
 (0)