Skip to content

Commit

Permalink
Merge branch 'main' into java_scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasArvidsson committed Nov 25, 2023
2 parents 7701042 + 08cd7a1 commit 16dfc13
Show file tree
Hide file tree
Showing 32 changed files with 280 additions and 61 deletions.
6 changes: 6 additions & 0 deletions changelog/2023-11-modalKeyboardVscodeCommands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
tags: [enhancement, keyboard]
pullRequest: 2026
---

- Add support for running VSCode commands from the experimental modal keyboard interface. See the [keyboard modal docs](https://www.cursorless.org/docs/user/experimental/keyboard/modal/) for more info.
5 changes: 4 additions & 1 deletion cursorless-talon/src/spoken_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ def handle_new_values(csv_name: str, values: list[SpokenFormEntry]):
handle_csv(
"modifier_scope_types.csv",
pluralize_lists=["scope_type"],
extra_allowed_values=["private.fieldAccess"],
extra_allowed_values=[
"private.fieldAccess",
"private.switchStatementSubject",
],
default_list_name="scope_type",
),
handle_csv(
Expand Down
18 changes: 18 additions & 0 deletions docs/user/experimental/keyboard/modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ To bind keys that do not have modifiers (eg just pressing `a`), add entries like
"z": "bolt",
"w": "crosshairs"
},
"cursorless.experimental.keyboard.modal.keybindings.vscodeCommands": {
// For simple commands, just use the command name
// "aa": "workbench.action.editor.changeLanguageMode",

// For commands with args, use the following format
// "am": {
// "commandId": "some.command.id",
// "args": ["foo", 0]
// }

// If you'd like to run the command on the active target, use the following format
"am": {
"commandId": "editor.action.joinLines",
"executeAtTarget": true,
// "keepChangedSelection": true,
// "exitCursorlessMode": true,
}
}
```

Any supported scopes, actions, or colors can be added to these sections, using the same identifiers that appear in the second column of your customisation csvs. Feel free to add / tweak / remove the keyboard shortcuts above as you see fit.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const simpleScopeTypeTypes = [
"sectionLevelFive",
"sectionLevelSix",
"selector",
"switchStatementSubject",
"private.switchStatementSubject",
"unit",
"xmlBothTags",
"xmlElement",
Expand Down
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/cpp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const nodeMatchers: Partial<
"function_definition[declarator][declarator][namespace]", // void ClassName::method() {}
],
ifStatement: "if_statement",
switchStatementSubject: "switch_statement[condition][value]",
["private.switchStatementSubject"]: "switch_statement[condition][value]",
string: "string_literal",
comment: "comment",
anonymousFunction: "lambda_expression",
Expand Down
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/csharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ const nodeMatchers: Partial<
conditionMatcher("*[condition]"),
patternMatcher("while_statement[0]"),
),
switchStatementSubject: [
["private.switchStatementSubject"]: [
"switch_statement.tuple_expression!",
"switch_statement[value]",
],
Expand Down
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const nodeMatchers: Partial<
]),
ternaryBranchMatcher("conditional_expression", [0, 2]),
),
switchStatementSubject: "match_statement[subject]",
["private.switchStatementSubject"]: "match_statement[subject]",
};

export default createPatternMatchers(nodeMatchers);
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/rust.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ const nodeMatchers: Partial<
matcher(patternFinder("else_clause"), elseExtractor("if_expression")),
matcher(patternFinder("if_expression"), elseIfExtractor()),
),
switchStatementSubject: "match_expression[value]",
["private.switchStatementSubject"]: "match_expression[value]",
};

export default createPatternMatchers(nodeMatchers);
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/scala.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const nodeMatchers: Partial<
}),
),

switchStatementSubject: "match_expression[value]",
["private.switchStatementSubject"]: "match_expression[value]",
name: ["*[name]", "*[pattern]"],
functionName: "function_definition[name]",

Expand Down
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/languages/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const nodeMatchers: Partial<
"do_statement[condition]",
),
),
switchStatementSubject: matcher(
["private.switchStatementSubject"]: matcher(
patternFinder("switch_statement[value]"),
unwrapSelectionExtractor,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ function isLanguageSpecific(scopeType: ScopeType): boolean {
case "sectionLevelFive":
case "sectionLevelSix":
case "selector":
case "switchStatementSubject":
case "private.switchStatementSubject":
case "unit":
case "xmlBothTags":
case "xmlElement":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {

export function scopeTypeToString(scopeType: ScopeType): string {
if (isSimpleScopeType(scopeType)) {
return camelCaseToAllDown(scopeType.type);
return camelCaseToAllDown(scopeType.type).replace(".", " ");
}

if (scopeType.type === "surroundingPair") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const defaultSpokenFormMapCore: DefaultSpokenFormMapDefinition = {

["private.fieldAccess"]: isPrivate("access"),
string: isPrivate("parse tree string"),
switchStatementSubject: isPrivate("subject"),
["private.switchStatementSubject"]: isPrivate("subject"),
},

surroundingPairForceDirection: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
int main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: false
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
int main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |-
switch (aaa) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: false
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |-
switch (aaa + 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
class Aaa {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
class Aaa {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
match 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
match user {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |
def matchTest(x: Int): String = x match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |-
switch(aaa) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ command:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: switchStatementSubject}
scopeType: {type: private.switchStatementSubject}
usePrePhraseSnapshot: true
spokenFormError: >-
simple scope type type with id switchStatementSubject; this is a private
spoken form currently only for internal experimentation
simple scope type type with id private.switchStatementSubject; this is a
private spoken form currently only for internal experimentation
initialState:
documentContents: |-
switch(aaa + 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ suite("Basic keyboard test", async function () {

test("Don't take keyboard control on startup", () => checkKeyboardStartup());
test("Basic keyboard test", () => basic());
test("Run vscode command", () => vscodeCommand());
test("Check that entering and leaving mode is no-op", () =>
enterAndLeaveIsNoOp());
});
Expand Down Expand Up @@ -56,6 +57,37 @@ async function basic() {
assert.equal(editor.document.getText().trim(), "a");
}

async function vscodeCommand() {
const { hatTokenMap } = (await getCursorlessApi()).testHelpers!;

const editor = await openNewEditor("aaa;\nbbb;\nccc;\n", {
languageId: "typescript",
});
await hatTokenMap.allocateHats();

editor.selection = new vscode.Selection(0, 0, 0, 0);

await vscode.commands.executeCommand("cursorless.keyboard.modal.modeOn");

// Target default b
await typeText("db");

// Comment line containing *selection*
await typeText("c");
assert.equal(editor.document.getText(), "// aaa;\nbbb;\nccc;\n");

// Comment line containing *target*
await typeText("mc");
assert.equal(editor.document.getText(), "// aaa;\n// bbb;\nccc;\n");

// Comment line containing *target*, keeping changed selection and exiting
// cursorless mode
await typeText("dcmma");
assert.equal(editor.document.getText(), "// aaa;\n// bbb;\n// a;\n");

await vscode.commands.executeCommand("cursorless.keyboard.modal.modeOff");
}

async function enterAndLeaveIsNoOp() {
const editor = await openNewEditor("hello");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const spokenFormJsonContents = {
},
{
type: "simpleScopeTypeType",
id: "switchStatementSubject",
id: "private.switchStatementSubject",
spokenForms: ["custom subject"],
},
{
Expand All @@ -96,22 +96,22 @@ const spokenFormJsonContents = {
};

const subjectStandard: ScopeTypeInfo = {
humanReadableName: "switch statement subject",
humanReadableName: "private switch statement subject",
isLanguageSpecific: true,
scopeType: { type: "switchStatementSubject" },
scopeType: { type: "private.switchStatementSubject" },
spokenForm: {
isPrivate: true,
reason:
"simple scope type type with id switchStatementSubject; this is a private spoken form currently only for internal experimentation",
"simple scope type type with id private.switchStatementSubject; this is a private spoken form currently only for internal experimentation",
requiresTalonUpdate: false,
type: "error",
},
};

const subjectCustom: ScopeTypeInfo = {
humanReadableName: "switch statement subject",
humanReadableName: "private switch statement subject",
isLanguageSpecific: true,
scopeType: { type: "switchStatementSubject" },
scopeType: { type: "private.switchStatementSubject" },
spokenForm: {
spokenForms: ["custom subject"],
type: "success",
Expand Down
Loading

0 comments on commit 16dfc13

Please sign in to comment.