Skip to content

Commit 023cdf7

Browse files
Merged with fully compositional modifiers pr
2 parents 4456705 + 4e78c28 commit 023cdf7

File tree

115 files changed

+1694
-1034
lines changed

Some content is hidden

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

115 files changed

+1694
-1034
lines changed

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,27 @@
4141
"!**/node_modules/**"
4242
]
4343
},
44+
{
45+
"name": "Run Single Extension Test",
46+
"type": "extensionHost",
47+
"request": "launch",
48+
"env": {
49+
"CURSORLESS_TEST": "true",
50+
"CURSORLESS_RUN_SINGLE_TEST": "true"
51+
},
52+
"args": [
53+
"--extensions-dir=${workspaceFolder}/.vscode-sandbox/extensions",
54+
"--extensionDevelopmentPath=${workspaceFolder}",
55+
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
56+
],
57+
"outFiles": ["${workspaceFolder}/out/test/**/*.js"],
58+
"preLaunchTask": "${defaultBuildTask}",
59+
"resolveSourceMapLocations": [
60+
"${workspaceFolder}/**",
61+
"!${workspaceFolder}/.vscode-sandbox/**",
62+
"!**/node_modules/**"
63+
]
64+
},
4465
{
4566
"name": "Update fixtures",
4667
"type": "extensionHost",

cursorless-talon/src/actions/actions_makeshift.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class MakeshiftAction:
3939
"editor.action.rename",
4040
restore_selection=True,
4141
await_command=False,
42-
post_command_sleep_ms=150,
42+
post_command_sleep_ms=200,
4343
),
4444
]
4545

cursorless-talon/src/csv_overrides.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ def update_dicts(
159159
key = obj["key"]
160160
if not is_removed(key):
161161
for k in key.split("|"):
162+
if value == "pasteFromClipboard" and k.endswith(" to"):
163+
# FIXME: This is a hack to work around the fact that the
164+
# spoken form of the `pasteFromClipboard` action used to be
165+
# "paste to", but now the spoken form is just "paste" and
166+
# the "to" is part of the positional target. Users who had
167+
# cursorless before this change would have "paste to" as
168+
# their spoken form and so would need to say "paste to to".
169+
k = k[:-3]
162170
results[obj["list"]][k.strip()] = value
163171

164172
# Assign result to talon context list

cursorless-talon/src/positional_target.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@
77

88
mod.list(
99
"cursorless_positional_connective",
10-
desc="The connective used to separate source and destination targets",
10+
desc='Connectives used to separate source and destination targets that indicate position, eg "before" or "after"',
1111
)
1212

1313
positional_connectives = {
1414
**POSITION_BEFORE,
1515
**POSITION_AFTER,
1616
}
1717

18-
print(positional_connectives)
1918
ctx.lists["self.cursorless_positional_connective"] = positional_connectives.keys()
2019

2120

docs/contributing/CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ locally, you need to run the extension in debug mode. To do so you need to run
3434
the `workbench.action.debug.selectandstart` command in VSCode and then select either "Run
3535
Extension" or "Extension Tests".
3636

37+
### Running a single test
38+
39+
The entire test suite takes a little while to run (1-2 mins), so if you'd like to repeat a single test, you can edit [`runSingleRecordedTest`](../../src/test/suite/runSingleRecordedTest.ts) to refer to the desired test and use the "Run Single Extension Test" launch config instead of the usual "Extension Tests".
40+
3741
## Code formatting
3842

3943
We use [`pre-commit`](https://pre-commit.com/) to automate autoformatting.

docs/contributing/parse-tree-patterns.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ We have a small domain-specific language that we use to define patterns to look
66

77
`GRAND_PARENT_TYPE.*.CHILD_TYPE[FIELD]!?`
88

9-
| Syntax | Description |
10-
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
11-
| TYPE | Match node type<br/>`node.type` |
12-
| Dot operator(`.`) | Type hierarchy between parent and child |
13-
| Wildcard op(`*`) | Match any type |
14-
| Negation op(`~`) | Match any type other than what is specified after `~` |
15-
| Important op(`!`) | Use this node as result instead of parent.<br/>By default the leftmost/top node is used |
16-
| Optional op(`?`) | Node is optional. Will match if available. |
17-
| Field op(`[field]`) | Get child field node for resulting node.<br/>Only evaluated on the resulting node at the end.<br/>`node.childForFieldName(field)` |
9+
| Syntax | Description |
10+
| ------------------- | --------------------------------------------------------------------------------------- |
11+
| TYPE | Match node type<br/>`node.type` |
12+
| Dot operator(`.`) | Type hierarchy between parent and child |
13+
| Wildcard op(`*`) | Match any type |
14+
| Negation op(`~`) | Match any type other than what is specified after `~` |
15+
| Important op(`!`) | Use this node as result instead of parent.<br/>By default the leftmost/top node is used |
16+
| Optional op(`?`) | Node is optional. Will match if available. |
17+
| Field op(`[field]`) | Return child node at given field.<br/>`node.childForFieldName(field)` |
18+
| Index op(`[n]`) | Return nth named child node. |
1819

1920
## Multiple patterns
2021

docs/user/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ The following colors are supported. Note that to target the default (gray) hat y
6464
| `"navy"` | navy | `userColor1` ||
6565
| `"apricot"` | apricot | `userColor2` ||
6666

67-
You can enable or disable colors in your VSCode settings, by searching for `cursorless.hatEnablement.colors` and checking the box next to the internal ID for the given shape as listed above.
67+
You can enable or disable colors in your VSCode settings, by searching for `cursorless.hatEnablement.colors` and checking the box next to the internal ID for the given shape as listed above. To navigate to your VSCode settings, either say "show settings", or go to File --> Preferences --> Settings.
6868

6969
You can also tweak the visible colors for any of these colors in your VSCode settings, by searching for `cursorless.colors` and changing the hex color code next to the internal ID for the given shape as listed above. Note that you can configure different colors for dark and light themes.
7070

@@ -93,7 +93,7 @@ The following shapes are supported. Note that to target the default (dot) shape
9393
| `"cross"` | ![Crosshairs](../../images/hats/crosshairs.svg) | `crosshairs` ||
9494
| `"bolt"` | ![Bolt](../../images/hats/bolt.svg) | `bolt` ||
9595

96-
You can enable or disable shapes in your VSCode settings, by searching for `cursorless.hatEnablement.shapes` and checking the box next to the internal ID for the given shape as listed above.
96+
You can enable or disable shapes in your VSCode settings, by searching for `cursorless.hatEnablement.shapes` and checking the box next to the internal ID for the given shape as listed above. To navigate to your VSCode settings, either say "show settings", or go to File --> Preferences --> Settings.
9797

9898
If you find these shape names unintuitive / tough to remember, their
9999
spoken forms can be [customized](customization.md) like any other spoken form

src/actions/BringMoveSwap.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ class BringMoveSwap implements Action {
9999
text = sources
100100
.map((source, i) => {
101101
const text = source.contentText;
102-
const delimiter = destination.delimiter ?? source.delimiter;
102+
const delimiter =
103+
(destination.isRaw ? null : destination.insertionDelimiter) ??
104+
(source.isRaw ? null : source.insertionDelimiter);
103105
return i > 0 && delimiter != null ? delimiter + text : text;
104106
})
105107
.join("");

src/actions/Clear.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { toRawTarget } from "../processTargets/modifiers/RawSelectionStage";
1+
import PlainTarget from "../processTargets/targets/PlainTarget";
22
import { Target } from "../typings/target.types";
33
import { Graph } from "../typings/Types";
44
import { setSelectionsAndFocusEditor } from "../util/setSelectionsAndFocusEditor";
@@ -12,9 +12,16 @@ export default class Clear implements Action {
1212

1313
async run([targets]: [Target[]]): Promise<ActionReturnValue> {
1414
const editor = ensureSingleEditor(targets);
15-
const rawTargets = targets.map(toRawTarget);
15+
const plainTargets = targets.map(
16+
(target) =>
17+
new PlainTarget({
18+
editor: target.editor,
19+
isReversed: target.isReversed,
20+
contentRange: target.contentRange,
21+
})
22+
);
1623

17-
const { thatMark } = await this.graph.actions.remove.run([rawTargets]);
24+
const { thatMark } = await this.graph.actions.remove.run([plainTargets]);
1825

1926
if (thatMark != null) {
2027
await setSelectionsAndFocusEditor(

src/actions/CutCopyPaste.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import RawSelectionTarget from "../processTargets/targets/RawSelectionTarget";
1+
import PlainTarget from "../processTargets/targets/PlainTarget";
22
import { Target } from "../typings/target.types";
33
import { Graph } from "../typings/Types";
44
import { getOutsideOverflow } from "../util/targetUtils";
@@ -19,10 +19,10 @@ export class Cut implements Action {
1919
return getOutsideOverflow(target.editor, target.contentRange, range).map(
2020
(overflow): Target =>
2121
// TODO Instead of creating a new target display decorations by range
22-
new RawSelectionTarget({
22+
new PlainTarget({
2323
editor: target.editor,
2424
contentRange: overflow,
25-
isReversed: false,
25+
isReversed: target.isReversed,
2626
})
2727
);
2828
});

src/actions/EditNew.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class EditNew implements Action {
3333
const context = target.getEditNewContext(this.isBefore);
3434
const common = {
3535
target,
36-
// targetRange: target.thatTarget.contentRange,
3736
cursorRange: target.contentRange,
3837
};
3938
switch (context.type) {
@@ -146,7 +145,7 @@ class EditNew implements Action {
146145
() => commands.executeCommand(command),
147146
editor.document,
148147
[
149-
targets.map(({ target }) => target.contentRange),
148+
targets.map(({ target }) => target.thatTarget.contentRange),
150149
targets.map(({ cursorRange }) => cursorRange),
151150
]
152151
);

src/actions/InsertEmptyLines.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ class InsertEmptyLines implements Action {
2424
const edits: EditWithRangeUpdater[] = [];
2525
if (this.insertAbove) {
2626
edits.push(
27-
toPositionTarget(lineTarget, "before").constructChangeEdit("")
27+
toPositionTarget(lineTarget, "before").constructEmptyChangeEdit()
2828
);
2929
}
3030
if (this.insertBelow) {
3131
edits.push(
32-
toPositionTarget(lineTarget, "after").constructChangeEdit("")
32+
toPositionTarget(lineTarget, "after").constructEmptyChangeEdit()
3333
);
3434
}
3535
return edits;

src/languages/csharp.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
matcher,
88
trailingMatcher,
99
typeMatcher,
10+
conditionMatcher,
11+
patternMatcher,
1012
} from "../util/nodeMatchers";
1113
import { NodeMatcherAlternative } from "../typings/Types";
1214
import { SimpleScopeTypeType } from "../typings/target.types";
@@ -221,6 +223,10 @@ const nodeMatchers: Partial<
221223
ifStatement: "if_statement",
222224
class: "class_declaration",
223225
className: "class_declaration[name]",
226+
condition: cascadingMatcher(
227+
conditionMatcher("*[condition]"),
228+
patternMatcher("while_statement[0]")
229+
),
224230
statement: STATEMENT_TYPES,
225231
anonymousFunction: "lambda_expression",
226232
functionCall: "invocation_expression",
Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,25 @@
1-
import { Range } from "vscode";
21
import { DelimiterRangeModifier, Target } from "../../typings/target.types";
32
import { ProcessedTargetsContext } from "../../typings/Types";
43
import { ModifierStage } from "../PipelineStages.types";
5-
import DelimiterRangeTarget from "../targets/DelimiterRangeTarget";
64

75
export default class DelimiterRangeStage implements ModifierStage {
86
constructor(private modifier: DelimiterRangeModifier) {}
97

108
run(context: ProcessedTargetsContext, target: Target): Target[] {
11-
let contentRange: Range;
12-
139
switch (this.modifier.direction) {
1410
case "leading":
15-
const leading = target.getLeadingDelimiterRange(true);
11+
const leading = target.getLeadingDelimiterTarget();
1612
if (leading == null) {
1713
throw Error("No available leading range");
1814
}
19-
contentRange = leading;
20-
break;
15+
return [leading];
2116

2217
case "trailing":
23-
const trailing = target.getTrailingDelimiterRange(true);
18+
const trailing = target.getTrailingDelimiterTarget();
2419
if (trailing == null) {
2520
throw Error("No available trailing range");
2621
}
27-
contentRange = trailing;
22+
return [trailing];
2823
}
29-
30-
return [
31-
new DelimiterRangeTarget({
32-
editor: target.editor,
33-
isReversed: target.isReversed,
34-
contentRange,
35-
isLine: target.is("paragraph"),
36-
}),
37-
];
3824
}
3925
}

src/processTargets/modifiers/ModifyIfWeakStage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default class ModifyIfWeakStage implements ModifierStage {
1818

1919
run(context: ProcessedTargetsContext, target: Target): Target[] {
2020
/** If true this target is of weak type and should use inference/upgrade when needed. See {@link WeakTarget} for more info */
21-
if (target.type === "weak") {
21+
if (target.isWeak) {
2222
return this.nestedStage
2323
.run(context, target)
2424
.map((newTarget) => newTarget.withThatTarget(target));

0 commit comments

Comments
 (0)