Skip to content

Commit 4f36bad

Browse files
Infer line scope from line number marks (#1268)
Fixes #1247 ## 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) - [x] I have not broken the cheatsheet
1 parent c1761c6 commit 4f36bad

File tree

3 files changed

+115
-6
lines changed

3 files changed

+115
-6
lines changed

src/core/inferFullTargets.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,41 @@ function shouldInferPreviousMark(
170170
function getPreservedModifiers(
171171
target: PartialPrimitiveTargetDescriptor,
172172
): Modifier[] | undefined {
173-
const preservedModifiers = target.modifiers?.filter(
174-
(modifier) => !["position", "inferPreviousMark"].includes(modifier.type),
175-
);
176-
return preservedModifiers == null || preservedModifiers.length === 0
177-
? undefined
178-
: preservedModifiers;
173+
const preservedModifiers =
174+
target.modifiers?.filter(
175+
(modifier) => !["position", "inferPreviousMark"].includes(modifier.type),
176+
) ?? [];
177+
if (preservedModifiers.length !== 0) {
178+
return preservedModifiers;
179+
}
180+
// In the absence of any other modifiers line number marks are infer as a containing line scope
181+
if (isLineNumberMark(target)) {
182+
return [
183+
{
184+
type: "containingScope",
185+
scopeType: {
186+
type: "line",
187+
},
188+
},
189+
];
190+
}
191+
return undefined;
192+
}
193+
194+
/**
195+
* Returns true if this target has a line number mark.
196+
* @param target The target to check for line number mark
197+
* @returns True if this target has a line number mark
198+
*/
199+
function isLineNumberMark(target: PartialPrimitiveTargetDescriptor): boolean {
200+
const isLineNumber = (mark?: Mark) => mark?.type === "lineNumber";
201+
if (isLineNumber(target.mark)) {
202+
return true;
203+
}
204+
if (target.mark?.type === "range") {
205+
return isLineNumber(target.mark.anchor) && isLineNumber(target.mark.active);
206+
}
207+
return false;
179208
}
180209

181210
function getPreviousMark(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
languageId: plaintext
2+
command:
3+
version: 4
4+
spokenForm: bring row one before batt
5+
action: {name: replaceWithTarget}
6+
targets:
7+
- type: primitive
8+
mark: {type: lineNumber, lineNumberType: modulo100, lineNumber: 0}
9+
- type: primitive
10+
mark: {type: decoratedSymbol, symbolColor: default, character: b}
11+
modifiers:
12+
- {type: position, position: before}
13+
usePrePhraseSnapshot: true
14+
initialState:
15+
documentContents: |-
16+
aaa
17+
ccc
18+
19+
b
20+
selections:
21+
- anchor: {line: 0, character: 0}
22+
active: {line: 0, character: 0}
23+
marks:
24+
default.b:
25+
start: {line: 3, character: 0}
26+
end: {line: 3, character: 1}
27+
finalState:
28+
documentContents: |-
29+
aaa
30+
ccc
31+
32+
aaa
33+
b
34+
selections:
35+
- anchor: {line: 0, character: 0}
36+
active: {line: 0, character: 0}
37+
fullTargets: [{type: primitive, mark: {type: lineNumber, lineNumberType: modulo100, lineNumber: 0}, modifiers: [{type: containingScope, scopeType: {type: line}}]}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: b}, modifiers: [{type: containingScope, scopeType: {type: line}}], positionModifier: {type: position, position: before}}]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
languageId: plaintext
2+
command:
3+
version: 4
4+
spokenForm: bring row one past two before batt
5+
action: {name: replaceWithTarget}
6+
targets:
7+
- type: primitive
8+
mark:
9+
type: range
10+
anchor: {type: lineNumber, lineNumberType: modulo100, lineNumber: 0}
11+
active: {type: lineNumber, lineNumberType: modulo100, lineNumber: 1}
12+
excludeAnchor: false
13+
excludeActive: false
14+
- type: primitive
15+
mark: {type: decoratedSymbol, symbolColor: default, character: b}
16+
modifiers:
17+
- {type: position, position: before}
18+
usePrePhraseSnapshot: true
19+
initialState:
20+
documentContents: |-
21+
aaa
22+
ccc
23+
24+
b
25+
selections:
26+
- anchor: {line: 0, character: 0}
27+
active: {line: 0, character: 0}
28+
marks:
29+
default.b:
30+
start: {line: 3, character: 0}
31+
end: {line: 3, character: 1}
32+
finalState:
33+
documentContents: |-
34+
aaa
35+
ccc
36+
37+
aaa
38+
ccc
39+
b
40+
selections:
41+
- anchor: {line: 0, character: 0}
42+
active: {line: 0, character: 0}
43+
fullTargets: [{type: primitive, mark: {type: range, anchor: {type: lineNumber, lineNumberType: modulo100, lineNumber: 0}, active: {type: lineNumber, lineNumberType: modulo100, lineNumber: 1}, excludeAnchor: false, excludeActive: false}, modifiers: [{type: containingScope, scopeType: {type: line}}]}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: b}, modifiers: [{type: containingScope, scopeType: {type: line}}], positionModifier: {type: position, position: before}}]

0 commit comments

Comments
 (0)