Skip to content

Commit 57aeb8f

Browse files
Implemented strict here selection type (#352)
* Implemented strict here selection type * Initial backwards compatibility * Start to refactor * More changes * Attempt to make new raw selections work * Fix bug and add a bunch of tests * Remove unused function Co-authored-by: Pokey Rule <pokey.rule@gmail.com>
1 parent e17c60f commit 57aeb8f

21 files changed

+316
-68
lines changed

.vscode/settings.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
1313
"typescript.tsc.autoDetect": "off",
1414
"cSpell.words": [
15-
"subword",
15+
"Autoformatting",
1616
"eqeqeq",
1717
"nonlocal",
18-
"pojo"
18+
"pojo",
19+
"subword"
1920
]
2021
}

src/actions/BringMoveSwap.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,12 @@ class BringMoveSwap implements Action {
115115
let text = source.selection.editor.document.getText(
116116
source.selection.selection
117117
);
118-
return i > 0 && destination.selectionContext.containingListDelimiter
119-
? destination.selectionContext.containingListDelimiter + text
118+
const selectionContext = destination.selectionContext
119+
.isRawSelection
120+
? source.selectionContext
121+
: destination.selectionContext;
122+
return i > 0 && selectionContext.containingListDelimiter
123+
? selectionContext.containingListDelimiter + text
120124
: text;
121125
})
122126
.join("");

src/core/inferFullTargets.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ function inferPrimitiveTarget(
9494
previousTargets: PartialTarget[],
9595
actionPreferences: ActionPreferences
9696
): PrimitiveTarget {
97-
const previousTargetsForAttributes = hasContent(target)
98-
? []
99-
: previousTargets;
97+
const doAttributeInference = !hasContent(target) && !target.isImplicit;
98+
99+
const previousTargetsForAttributes = doAttributeInference
100+
? previousTargets
101+
: [];
100102

101103
const maybeSelectionType =
102104
target.selectionType ??
@@ -117,7 +119,7 @@ function inferPrimitiveTarget(
117119

118120
const selectionType =
119121
maybeSelectionType ??
120-
(target.modifier == null ? actionPreferences.selectionType : null) ??
122+
(doAttributeInference ? actionPreferences.selectionType : null) ??
121123
"token";
122124

123125
const insideOutsideType =
@@ -127,7 +129,7 @@ function inferPrimitiveTarget(
127129

128130
const modifier = target.modifier ??
129131
getPreviousAttribute(previousTargetsForAttributes, "modifier") ??
130-
(target.selectionType == null ? actionPreferences.modifier : null) ?? {
132+
(doAttributeInference ? actionPreferences.modifier : null) ?? {
131133
type: "identity",
132134
};
133135

@@ -138,6 +140,7 @@ function inferPrimitiveTarget(
138140
position,
139141
insideOutsideType,
140142
modifier,
143+
isImplicit: target.isImplicit ?? false,
141144
};
142145
}
143146

src/processTargets/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import processMark from "./processMark";
1212
import processModifier from "./modifiers/processModifier";
1313
import processPosition from "./processPosition";
1414
import processSelectionType from "./processSelectionType";
15-
import { isForward as getIsForward } from "../util/selectionUtils";
1615

1716
export default function (
1817
context: ProcessedTargetsContext,
@@ -275,6 +274,13 @@ function processPrimitiveTarget(
275274
({ selection, context: selectionContext }) =>
276275
processSelectionType(context, target, selection, selectionContext)
277276
);
277+
278+
if (target.isImplicit) {
279+
typedSelections.forEach((typedSelection) => {
280+
typedSelection.selectionContext.isRawSelection = true;
281+
});
282+
}
283+
278284
return typedSelections.map((selection) =>
279285
processPosition(context, target, selection)
280286
);

src/processTargets/modifiers/processModifier.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
NodeMatcher,
1111
PrimitiveTarget,
1212
ProcessedTargetsContext,
13+
RawSelectionModifier,
1314
SelectionContext,
1415
SelectionWithEditor,
1516
SubTokenModifier,
@@ -52,6 +53,14 @@ export default function (
5253
case "surroundingPair":
5354
result = processSurroundingPair(context, selection, modifier);
5455
break;
56+
57+
case "toRawSelection":
58+
result = processRawSelectionModifier(context, selection, modifier);
59+
break;
60+
61+
default:
62+
// Make sure we haven't missed any cases
63+
const neverCheck: never = modifier;
5564
}
5665

5766
if (result == null) {
@@ -233,3 +242,16 @@ export function findNearestContainingAncestorNode(
233242

234243
return null;
235244
}
245+
246+
function processRawSelectionModifier(
247+
context: ProcessedTargetsContext,
248+
selection: SelectionWithEditor,
249+
modifier: RawSelectionModifier
250+
): SelectionWithEditorWithContext[] | null {
251+
return [
252+
{
253+
selection,
254+
context: { isRawSelection: true },
255+
},
256+
];
257+
}

src/processTargets/processSelectionType.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,22 @@ function processToken(
6262
selectionType,
6363
position,
6464
insideOutsideType,
65-
selectionContext: getTokenSelectionContext(
66-
selection,
67-
modifier,
68-
position,
69-
insideOutsideType,
70-
selectionContext
71-
),
65+
// NB: This is a hack to work around the fact that it's not currently
66+
// possible to apply a modifier after processing the selection type. We
67+
// would really prefer that the user be able to say "just" and have that be
68+
// processed after we've processed the selection type, which would strip
69+
// away the type information and turn it into a raw target. Until that's
70+
// possible using the new pipelines, we instead just check for it here when
71+
// we're doing the selection type and bail out if it is a raw target.
72+
selectionContext: selectionContext.isRawSelection
73+
? selectionContext
74+
: getTokenSelectionContext(
75+
selection,
76+
modifier,
77+
position,
78+
insideOutsideType,
79+
selectionContext
80+
),
7281
};
7382
}
7483

src/test/suite/fixtures/recorded/actions/bringAirAndBatAndCap.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ command:
1212
mark: {type: decoratedSymbol, symbolColor: default, character: b}
1313
- type: primitive
1414
mark: {type: decoratedSymbol, symbolColor: default, character: c}
15-
- type: primitive
16-
mark: {type: cursor}
17-
selectionType: token
18-
position: contents
19-
modifier: {type: identity}
20-
insideOutsideType: inside
15+
- {type: primitive, isImplicit: true}
2116
initialState:
2217
documentContents: |+
2318
a
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
languageId: typescript
2+
command:
3+
version: 1
4+
spokenForm: bring argue fine and zip
5+
action: replaceWithTarget
6+
targets:
7+
- type: list
8+
elements:
9+
- type: primitive
10+
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}
11+
mark: {type: decoratedSymbol, symbolColor: default, character: f}
12+
- type: primitive
13+
mark: {type: decoratedSymbol, symbolColor: default, character: z}
14+
- {type: primitive, isImplicit: true}
15+
initialState:
16+
documentContents: |-
17+
function helloWorld(foo: string, bar: number, baz: string) {
18+
19+
}
20+
21+
function bongo() {
22+
23+
}
24+
selections:
25+
- anchor: {line: 4, character: 15}
26+
active: {line: 4, character: 15}
27+
marks:
28+
default.f:
29+
start: {line: 0, character: 20}
30+
end: {line: 0, character: 23}
31+
default.z:
32+
start: {line: 0, character: 46}
33+
end: {line: 0, character: 49}
34+
finalState:
35+
documentContents: |-
36+
function helloWorld(foo: string, bar: number, baz: string) {
37+
38+
}
39+
40+
function bongo(foo: string, baz: string) {
41+
42+
}
43+
selections:
44+
- anchor: {line: 4, character: 39}
45+
active: {line: 4, character: 39}
46+
thatMark:
47+
- anchor: {line: 4, character: 15}
48+
active: {line: 4, character: 39}
49+
sourceMark:
50+
- anchor: {line: 0, character: 20}
51+
active: {line: 0, character: 31}
52+
- anchor: {line: 0, character: 46}
53+
active: {line: 0, character: 57}
54+
fullTargets: [{type: list, elements: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: f}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}, isImplicit: false}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: z}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}, isImplicit: false}]}, {type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: identity}, isImplicit: true}]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
languageId: typescript
2+
command:
3+
version: 1
4+
spokenForm: bring argue ox and zip to after just leper
5+
action: replaceWithTarget
6+
targets:
7+
- type: list
8+
elements:
9+
- type: primitive
10+
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}
11+
mark: {type: decoratedSymbol, symbolColor: default, character: o}
12+
- type: primitive
13+
mark: {type: decoratedSymbol, symbolColor: default, character: z}
14+
- type: primitive
15+
position: after
16+
modifier: {type: toRawSelection}
17+
mark: {type: decoratedSymbol, symbolColor: default, character: (}
18+
initialState:
19+
documentContents: |-
20+
function helloWorld(foo: string, bar: number, baz: string) {
21+
22+
}
23+
24+
function bongo() {
25+
26+
}
27+
selections:
28+
- anchor: {line: 3, character: 0}
29+
active: {line: 3, character: 0}
30+
marks:
31+
default.o:
32+
start: {line: 0, character: 20}
33+
end: {line: 0, character: 23}
34+
default.z:
35+
start: {line: 0, character: 46}
36+
end: {line: 0, character: 49}
37+
default.(:
38+
start: {line: 4, character: 14}
39+
end: {line: 4, character: 15}
40+
finalState:
41+
documentContents: |-
42+
function helloWorld(foo: string, bar: number, baz: string) {
43+
44+
}
45+
46+
function bongo(foo: string, baz: string) {
47+
48+
}
49+
selections:
50+
- anchor: {line: 3, character: 0}
51+
active: {line: 3, character: 0}
52+
thatMark:
53+
- anchor: {line: 4, character: 15}
54+
active: {line: 4, character: 39}
55+
sourceMark:
56+
- anchor: {line: 0, character: 20}
57+
active: {line: 0, character: 31}
58+
- anchor: {line: 0, character: 46}
59+
active: {line: 0, character: 57}
60+
fullTargets: [{type: list, elements: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: o}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}, isImplicit: false}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: z}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: false}, isImplicit: false}]}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, selectionType: token, position: after, insideOutsideType: null, modifier: {type: toRawSelection}, isImplicit: false}]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
languageId: plaintext
2+
command:
3+
version: 1
4+
spokenForm: bring line harp and whale
5+
action: replaceWithTarget
6+
targets:
7+
- type: list
8+
elements:
9+
- type: primitive
10+
selectionType: line
11+
mark: {type: decoratedSymbol, symbolColor: default, character: h}
12+
- type: primitive
13+
mark: {type: decoratedSymbol, symbolColor: default, character: w}
14+
- {type: primitive, isImplicit: true}
15+
initialState:
16+
documentContents: |+
17+
hello
18+
there
19+
whatever
20+
21+
selections:
22+
- anchor: {line: 4, character: 0}
23+
active: {line: 4, character: 0}
24+
marks:
25+
default.h:
26+
start: {line: 0, character: 0}
27+
end: {line: 0, character: 5}
28+
default.w:
29+
start: {line: 2, character: 0}
30+
end: {line: 2, character: 8}
31+
finalState:
32+
documentContents: |-
33+
hello
34+
there
35+
whatever
36+
37+
hello
38+
whatever
39+
selections:
40+
- anchor: {line: 5, character: 8}
41+
active: {line: 5, character: 8}
42+
thatMark:
43+
- anchor: {line: 4, character: 0}
44+
active: {line: 5, character: 8}
45+
sourceMark:
46+
- anchor: {line: 0, character: 0}
47+
active: {line: 0, character: 5}
48+
- anchor: {line: 2, character: 0}
49+
active: {line: 2, character: 8}
50+
fullTargets: [{type: list, elements: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, selectionType: line, position: contents, insideOutsideType: null, modifier: {type: identity}, isImplicit: false}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: w}, selectionType: line, position: contents, insideOutsideType: null, modifier: {type: identity}, isImplicit: false}]}, {type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: null, modifier: {type: identity}, isImplicit: true}]

0 commit comments

Comments
 (0)