Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cursorless-talon-dev/src/cursorless_test.talon
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ test api extract decorated marks <user.cursorless_target>:
test api alternate highlight nothing:
user.private_cursorless_test_alternate_highlight_nothing()

test api parsed: user.cursorless_x_custom_command("chuck block")
test api parsed chuck block: user.cursorless_x_custom_command("chuck block")
test api parsed take next token: user.cursorless_x_custom_command("take next token")
test api parsed change next instance: user.cursorless_x_custom_command("change next instance")
test api parsed <user.cursorless_target>:
user.cursorless_x_custom_command("chuck block <target>", cursorless_target)
test api parsed <user.cursorless_target> plus <user.cursorless_target>:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function id(d: any[]): any { return d[0]; }
declare var simpleActionName: any;
declare var bringMove: any;
declare var insertionMode: any;
declare var direction: any;
declare var simpleScopeTypeType: any;
declare var pairedDelimiter: any;
declare var simpleMarkType: any;
Expand All @@ -16,9 +17,10 @@ import { lexer } from "../lexer";
import {
bringMoveActionDescriptor,
containingScopeModifier,
partialPrimitiveTargetDescriptor,
createPlaceholderTarget,
partialPrimitiveTargetDescriptor,
primitiveDestinationDescriptor,
relativeScopeModifier,
simpleActionDescriptor,
simplePartialMark,
simpleScopeType,
Expand Down Expand Up @@ -80,12 +82,12 @@ const grammar: Grammar = {
{"name": "primitiveTarget", "symbols": ["primitiveTarget$ebnf$2", "mark"], "postprocess":
([modifiers, mark]) => partialPrimitiveTargetDescriptor(modifiers, mark)
},
{"name": "modifier", "symbols": ["containingScopeModifier"], "postprocess":
([containingScopeModifier]) => containingScopeModifier
},
{"name": "containingScopeModifier", "symbols": ["scopeType"], "postprocess":
{"name": "modifier", "symbols": ["scopeType"], "postprocess":
([scopeType]) => containingScopeModifier(scopeType)
},
{"name": "modifier", "symbols": [(lexer.has("direction") ? {type: "direction"} : direction), "scopeType"], "postprocess":
([direction, scopeType]) => relativeScopeModifier(scopeType, direction)
},
{"name": "scopeType", "symbols": [(lexer.has("simpleScopeTypeType") ? {type: "simpleScopeTypeType"} : simpleScopeTypeType)], "postprocess":
([simpleScopeTypeType]) => simpleScopeType(simpleScopeTypeType)
},
Expand Down
11 changes: 6 additions & 5 deletions packages/cursorless-engine/src/customCommandGrammar/grammar.ne
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { lexer } from "../lexer";
import {
bringMoveActionDescriptor,
containingScopeModifier,
partialPrimitiveTargetDescriptor,
createPlaceholderTarget,
partialPrimitiveTargetDescriptor,
primitiveDestinationDescriptor,
relativeScopeModifier,
simpleActionDescriptor,
simplePartialMark,
simpleScopeType,
Expand Down Expand Up @@ -54,12 +55,12 @@ primitiveTarget -> modifier:+ mark {%

# --------------------------- Modifiers ---------------------------

modifier -> containingScopeModifier {%
([containingScopeModifier]) => containingScopeModifier
modifier -> scopeType {%
([scopeType]) => containingScopeModifier(scopeType)
%}

containingScopeModifier -> scopeType {%
([scopeType]) => containingScopeModifier(scopeType)
modifier -> %direction scopeType {%
([direction, scopeType]) => relativeScopeModifier(scopeType, direction)
%}

# --------------------------- Scope types ---------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type {
BringMoveActionDescriptor,
DestinationDescriptor,
Direction,
InsertionMode,
PartialListTargetDescriptor,
PartialRangeTargetDescriptor,
PartialTargetMark,
PrimitiveDestinationDescriptor,
RelativeScopeModifier,
} from "@cursorless/common";
import {
type ContainingScopeModifier,
Expand Down Expand Up @@ -75,6 +77,19 @@ export function containingScopeModifier(
};
}

export function relativeScopeModifier(
scopeType: ScopeType,
direction: Direction,
): RelativeScopeModifier {
return {
type: "relativeScope",
scopeType,
offset: 1,
length: 1,
direction,
};
}

export function simpleScopeType(type: SimpleScopeTypeType): SimpleScopeType {
return { type };
}
Expand Down
16 changes: 16 additions & 0 deletions packages/cursorless-engine/src/customCommandGrammar/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ for (const [mark, spokenForm] of Object.entries(marks)) {
}
}

defaultSpokenFormMap.modifierExtra.next.spokenForms.forEach((spokenForm) => {
tokens[spokenForm] = {
type: "direction",
value: "forward",
};
});

defaultSpokenFormMap.modifierExtra.previous.spokenForms.forEach(
(spokenForm) => {
tokens[spokenForm] = {
type: "direction",
value: "backward",
};
},
);

export const lexer = new CommandLexer({
ws: /[ \t]+/,
placeholderTarget: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ function getTextAction(options: GetTextActionOptions): ActionDescriptor {
};
}

const parsedActionNoTargets: ActionDescriptor = {
name: "parsed",
content: "chuck block",
arguments: [],
};
function parsedAction(content: string): ActionDescriptor {
return {
name: "parsed",
content,
arguments: [],
};
}

const parsedActionAir: ActionDescriptor = {
name: "parsed",
content: "chuck block <target>",
Expand Down Expand Up @@ -221,7 +224,15 @@ export const talonApiFixture = [
"test api alternate highlight nothing",
alternateHighlightNothingAction,
),
spokenFormTest("test api parsed", parsedActionNoTargets),
spokenFormTest("test api parsed chuck block", parsedAction("chuck block")),
spokenFormTest(
"test api parsed take next token",
parsedAction("take next token"),
),
spokenFormTest(
"test api parsed change next instance",
parsedAction("change next instance"),
),
spokenFormTest("test api parsed air and bat", parsedActionAir),
spokenFormTest("test api parsed air plus bat", parsedActionAirPlusBat),
];
Expand Down
9 changes: 5 additions & 4 deletions packages/cursorless-engine/src/testUtil/TalonRepl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as os from "node:os";
import { isWindows } from "@cursorless/node-common";
import * as childProcess from "node:child_process";
import * as os from "node:os";

const MAX_OUTPUT_TO_EAT = 20;

Expand All @@ -16,7 +17,7 @@ export class TalonRepl {
start(): Promise<void> {
return new Promise<void>((resolve, reject) => {
const path = getReplPath();
this.child = childProcess.spawn(path);
this.child = childProcess.spawn(path, { shell: true });

if (!this.child.stdin) {
reject("stdin is null");
Expand Down Expand Up @@ -86,7 +87,7 @@ export class TalonRepl {
}

function getReplPath() {
return os.platform() === "win32"
? `${os.homedir()}\\AppData\\Roaming\\talon\\venv\\3.11\\Scripts\\repl.bat`
return isWindows()
? `${os.homedir()}\\AppData\\Roaming\\talon\\venv\\3.13\\Scripts\\repl.bat`
: `${os.homedir()}/.talon/.venv/bin/repl`;
}
Loading