diff --git a/cursorless-talon/src/modifiers/scopes.py b/cursorless-talon/src/modifiers/scopes.py index 61308cff95..a6a741d2fa 100644 --- a/cursorless-talon/src/modifiers/scopes.py +++ b/cursorless-talon/src/modifiers/scopes.py @@ -29,6 +29,7 @@ "funk name": "functionName", "funk": "namedFunction", "if state": "ifStatement", + "instance": "instance", "item": "collectionItem", "key": "collectionKey", "lambda": "anonymousFunction", diff --git a/docs/user/README.md b/docs/user/README.md index e235dc7bb7..6adfdd0247 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -311,6 +311,26 @@ foo.bar baz|bongo Saying `"every paint"` would select `foo.bar` and `baz|bongo`. +##### `"instance"` + +The `"instance"` modifier searches for occurrences of the text of the target. For example: + +- `"take every instance air"`: selects all instances of the token with a hat over the letter `a` in the whole document +- `"take two instances air"`: selects the first two instances of the token with a hat over the letter `a`, starting from that token itself +- `"take next instance air"`: selects the next instance of the token with a hat over the letter `a`, starting from that token itself +- `"chuck every instance two tokens air"`: deletes all occurrences of the two tokens beginning from the token with a hat over the letter `a`. For example if there were a hat over the `a` in `aaa.bbb`, it would delete every occurrence of `aaa.` in the file. +- `"take every instance air past bat"`: if there were hats over the `a` and `b` in `aaa ccc bbb ddd`, it would selects all occurrences of `aaa ccc bbb` (which is the text corresponding to the range `"air past bat"`) + +Note in the final example how the `"instance"` modifier constructs the instance based on the range `"air past bat"`, rather than the individual tokens `"air"` and `"bat"`, as you might expect given the way other modifiers behave. Effectively `"instance"` applies to everything after the `"instance"` modifier, rather than just the next modifier. + +Note also that `"instance"` considers the type of target used to construct the instance. So for example, `"take every instance air"` will only select tokens that +are identical to the token with a hat over the letter `a`, skipping over bigger tokens that contain the token with a hat over the letter `a` as a substring. For example, if there were a hat over the `a` in `aaa`, it would select every occurrence of `aaa` in the file, but not `aaaaa`. If you want to avoid this behaviour, you can +use the `"just"` modifier, eg `"take every instance just air"`. + +If your cursor is touching a token, you can say `"take every instance air"` to select all instances of the given token. + +Pro tip: if you say eg `"take five instances air"`, and it turns out you need more, you can say eg `"take that and next two instances that"` to select the next two instances after the last instance you selected. + ##### Surrounding pair Cursorless has support for expanding the selection to the nearest containing paired delimiter, eg the surrounding parentheses, curly brackets, etc. @@ -351,7 +371,7 @@ For example: If your cursor / mark is between two delimiters (not adjacent to one), then saying either "left" or "right" will cause cursorless to just expand to the nearest delimiters on either side, without trying to determine whether they are opening or closing delimiters. -#### `"its"` +##### `"its"` The the modifier `"its"` is intended to be used as part of a compound target, and will tell Cursorless to use the previously mentioned mark in the compound target. diff --git a/packages/common/src/types/command/PartialTargetDescriptor.types.ts b/packages/common/src/types/command/PartialTargetDescriptor.types.ts index 849077a3a5..c95b25cd01 100644 --- a/packages/common/src/types/command/PartialTargetDescriptor.types.ts +++ b/packages/common/src/types/command/PartialTargetDescriptor.types.ts @@ -86,6 +86,7 @@ export type SimpleScopeTypeType = | "functionCallee" | "functionName" | "ifStatement" + | "instance" | "list" | "map" | "name" diff --git a/packages/cursorless-engine/src/core/handleHoistedModifiers.ts b/packages/cursorless-engine/src/core/handleHoistedModifiers.ts index 8fbbb3e35f..635d25132c 100644 --- a/packages/cursorless-engine/src/core/handleHoistedModifiers.ts +++ b/packages/cursorless-engine/src/core/handleHoistedModifiers.ts @@ -146,7 +146,8 @@ const hoistedModifierTypes: HoistedModifierType[] = [ // "every" ranges, eg "every line air past bat" { accept(modifier: Modifier) { - return modifier.type === "everyScope" + return modifier.type === "everyScope" && + modifier.scopeType.type !== "instance" ? { accepted: true, transformTarget(target: RangeTargetDescriptor) { @@ -159,4 +160,19 @@ const hoistedModifierTypes: HoistedModifierType[] = [ : { accepted: false }; }, }, + + // "instance" modifiers treat the range as the instance to search for, eg + // "every instance air past bat" searches for instances of the text of the + // range "air past bat". + { + accept(modifier: Modifier) { + return { + accepted: + (modifier.type === "everyScope" || + modifier.type === "relativeScope" || + modifier.type === "ordinalScope") && + modifier.scopeType.type === "instance", + }; + }, + }, ]; diff --git a/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts b/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts index b84bc6c80e..5dfeca7ad2 100644 --- a/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts +++ b/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts @@ -16,6 +16,7 @@ import { KeepEmptyFilterStage, } from "./modifiers/FilterStages"; import { HeadStage, TailStage } from "./modifiers/HeadTailStage"; +import InstanceStage from "./modifiers/InstanceStage"; import { ExcludeInteriorStage, InteriorOnlyStage, @@ -75,10 +76,22 @@ export class ModifierStageFactoryImpl implements ModifierStageFactory { modifier, ); case "everyScope": + if (modifier.scopeType.type === "instance") { + return new InstanceStage(this, modifier); + } + return new EveryScopeStage(this, this.scopeHandlerFactory, modifier); case "ordinalScope": + if (modifier.scopeType.type === "instance") { + return new InstanceStage(this, modifier); + } + return new OrdinalScopeStage(this, modifier); case "relativeScope": + if (modifier.scopeType.type === "instance") { + return new InstanceStage(this, modifier); + } + return new RelativeScopeStage(this, this.scopeHandlerFactory, modifier); case "keepContentFilter": return new KeepContentFilterStage(modifier); diff --git a/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts new file mode 100644 index 0000000000..2950efd44f --- /dev/null +++ b/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts @@ -0,0 +1,205 @@ +import { + Direction, + Modifier, + OrdinalScopeModifier, + Range, + RelativeScopeModifier, + ScopeType, + TextEditor, +} from "@cursorless/common"; +import { ifilter, imap, itake } from "itertools"; +import { escapeRegExp } from "lodash"; +import type { Target } from "../../typings/target.types"; +import { generateMatchesInRange } from "../../util/getMatchesInRange"; +import { ModifierStageFactory } from "../ModifierStageFactory"; +import type { ModifierStage } from "../PipelineStages.types"; +import { PlainTarget } from "../targets"; +import { ContainingTokenIfUntypedEmptyStage } from "./ConditionalModifierStages"; +import { OutOfRangeError } from "./targetSequenceUtils"; + +export default class InstanceStage implements ModifierStage { + constructor( + private modifierStageFactory: ModifierStageFactory, + private modifier: Modifier, + ) {} + + run(inputTarget: Target): Target[] { + // If the target is untyped and empty, we want to target the containing + // token. This handles the case where they just say "instance" with an empty + // selection, eg "take every instance". + const target = new ContainingTokenIfUntypedEmptyStage( + this.modifierStageFactory, + ).run(inputTarget)[0]; + + switch (this.modifier.type) { + case "everyScope": + return this.handleEveryScope(target); + case "ordinalScope": + return this.handleOrdinalScope(target, this.modifier); + case "relativeScope": + return this.handleRelativeScope(target, this.modifier); + default: + throw Error(`${this.modifier.type} instance scope not supported`); + } + } + + private handleEveryScope(target: Target): Target[] { + const { editor } = target; + + return Array.from( + this.getTargetIterable( + target, + editor, + this.getEveryRange(editor), + "forward", + ), + ); + } + + private handleOrdinalScope( + target: Target, + { start, length }: OrdinalScopeModifier, + ): Target[] { + const { editor } = target; + + return takeFromOffset( + this.getTargetIterable( + target, + editor, + this.getEveryRange(editor), + start >= 0 ? "forward" : "backward", + ), + start >= 0 ? start : -(length + start), + length, + ); + } + + private handleRelativeScope( + target: Target, + { direction, offset, length }: RelativeScopeModifier, + ): Target[] { + const { editor } = target; + + const iterationRange = + direction === "forward" + ? new Range(target.contentRange.start, editor.document.range.end) + : new Range(editor.document.range.start, target.contentRange.end); + + return takeFromOffset( + this.getTargetIterable(target, editor, iterationRange, direction), + offset, + length, + ); + } + + private getEveryRange(editor: TextEditor): Range { + return editor.document.range; + } + + private getTargetIterable( + target: Target, + editor: TextEditor, + searchRange: Range, + direction: Direction, + ): Iterable { + const iterable = imap( + generateMatchesInRange( + new RegExp(escapeRegExp(target.contentText), "g"), + editor, + searchRange, + direction, + ), + (range) => + new PlainTarget({ + contentRange: range, + editor, + isReversed: false, + isToken: false, + }), + ); + + const filterScopeType = getFilterScopeType(target); + + if (filterScopeType != null) { + // If the target is a line, token or word, we want to filter out any + // instances of the text that are not also a line, token or word. For + // those that are, we want to return the target as a line, token or word + // target. For example, if the user says "take every instance air", we + // won't return matches where we find the text of the "air" token as part + // of a larger token. + const containingScopeModifier = this.modifierStageFactory.create({ + type: "containingScope", + scopeType: filterScopeType, + }); + + return ifilter( + imap(iterable, (target) => { + try { + // Just try to expand to the containing scope. If it fails or is not + // equal to the target, we know the match is not a line, token or + // word. + const containingScope = containingScopeModifier.run(target); + + if ( + containingScope.length === 1 && + containingScope[0].contentRange.isRangeEqual(target.contentRange) + ) { + return containingScope[0]; + } + + return null; + } catch (err) { + return null; + } + }), + (target): target is Target => target != null, + ) as Iterable; + } + + return iterable; + } +} + +function getFilterScopeType(target: Target): ScopeType | null { + if (target.isLine) { + return { type: "line" }; + } + + if (target.isToken) { + return { type: "token" }; + } + + if (target.isWord) { + return { type: "word" }; + } + + return null; +} + +/** + * Take `length` items from `iterable` starting at `offset`, throwing an error + * if there are not enough items. + * + * @param iterable The iterable to take from + * @param offset How many items to skip + * @param count How many items to take + * @returns An array of length `length` containing the items from `iterable` + * starting at `offset` + */ +function takeFromOffset( + iterable: Iterable, + offset: number, + count: number, +): T[] { + // Skip the first `offset` targets + Array.from(itake(offset, iterable)); + + // Take the next `length` targets + const items = Array.from(itake(count, iterable)); + + if (items.length < count) { + throw new OutOfRangeError(); + } + + return items; +} diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts index 998a096fb6..ad0413ceaf 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts @@ -58,6 +58,9 @@ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory { return new ParagraphScopeHandler(scopeType, languageId); case "custom": return scopeType.scopeHandler; + case "instance": + // Handle instance pseudoscope with its own special modifier + throw Error("Unexpected scope type 'instance'"); default: return this.languageDefinitions .get(languageId) diff --git a/packages/cursorless-engine/src/processTargets/targets/BaseTarget.ts b/packages/cursorless-engine/src/processTargets/targets/BaseTarget.ts index aea3a789af..3f22cfca11 100644 --- a/packages/cursorless-engine/src/processTargets/targets/BaseTarget.ts +++ b/packages/cursorless-engine/src/processTargets/targets/BaseTarget.ts @@ -37,6 +37,7 @@ export default abstract class BaseTarget implements Target { isRaw = false; isImplicit = false; isNotebookCell = false; + isWord = false; constructor(parameters: CommonTargetParameters) { this.state = { diff --git a/packages/cursorless-engine/src/processTargets/targets/SubTokenWordTarget.ts b/packages/cursorless-engine/src/processTargets/targets/SubTokenWordTarget.ts index e190f057ca..e9b040dba2 100644 --- a/packages/cursorless-engine/src/processTargets/targets/SubTokenWordTarget.ts +++ b/packages/cursorless-engine/src/processTargets/targets/SubTokenWordTarget.ts @@ -14,6 +14,7 @@ export default class SubTokenWordTarget extends BaseTarget { private trailingDelimiterRange_?: Range; insertionDelimiter: string; isToken = false; + isWord = true; constructor(parameters: SubTokenTargetParameters) { super(parameters); diff --git a/packages/cursorless-engine/src/typings/target.types.ts b/packages/cursorless-engine/src/typings/target.types.ts index 7e97b74da6..5ec834289d 100644 --- a/packages/cursorless-engine/src/typings/target.types.ts +++ b/packages/cursorless-engine/src/typings/target.types.ts @@ -47,6 +47,9 @@ export interface Target { /** If true this target should be treated as a token */ readonly isToken: boolean; + /** If true this target should be treated as a word */ + readonly isWord: boolean; + /** * If `true`, then this target has an explicit scope type, and so should never * be automatically expanded to a containing scope. diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/instants/clearSecondLastInstanceAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/instants/clearSecondLastInstanceAir.yml new file mode 100644 index 0000000000..6944233218 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/instants/clearSecondLastInstanceAir.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear second last instance air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: instance} + start: -2 + length: 1 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa eee + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 20} + end: {line: 0, character: 23} +finalState: + documentContents: | + aaa bbb ccc ddd aaa eee + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/bringDrumAfterTwoInstancesAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/bringDrumAfterTwoInstancesAir.yml new file mode 100644 index 0000000000..e55884936d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/bringDrumAfterTwoInstancesAir.yml @@ -0,0 +1,37 @@ +languageId: plaintext +command: + version: 5 + spokenForm: bring drum after two instances air + action: {name: replaceWithTarget} + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: d} + - type: primitive + modifiers: + - {type: position, position: after} + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc ddd aaa + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.d: + start: {line: 0, character: 12} + end: {line: 0, character: 15} + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa ddd bbb ccc ddd aaa ddd + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/chuckTwoInstancesLineAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/chuckTwoInstancesLineAir.yml new file mode 100644 index 0000000000..7478fffceb --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/chuckTwoInstancesLineAir.yml @@ -0,0 +1,37 @@ +languageId: plaintext +command: + version: 5 + spokenForm: chuck two instances line air + action: {name: remove} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - type: containingScope + scopeType: {type: line} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb + aaa bbb ccc + aaa bbb + ddd + selections: + - anchor: {line: 4, character: 0} + active: {line: 4, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa bbb ccc + ddd + selections: + - anchor: {line: 2, character: 0} + active: {line: 2, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAir.yml new file mode 100644 index 0000000000..455143f686 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAir.yml @@ -0,0 +1,36 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear every instance air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + eee aaa fff + selections: + - anchor: {line: 2, character: 0} + active: {line: 2, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: |2 + bbb ccc ddd + eee fff + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAirPastBat.yml new file mode 100644 index 0000000000..a081e85eb3 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceAirPastBat.yml @@ -0,0 +1,40 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear every instance air past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: |2 + ccc + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceEveryTokenAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceEveryTokenAirPastBat.yml new file mode 100644 index 0000000000..c91f28f989 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceEveryTokenAirPastBat.yml @@ -0,0 +1,46 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear every instance every token air past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + - type: everyScope + scopeType: {type: token} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: |2 + ccc + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + - anchor: {line: 0, character: 7} + active: {line: 0, character: 7} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstancePastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstancePastBat.yml new file mode 100644 index 0000000000..7b487b5d14 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstancePastBat.yml @@ -0,0 +1,34 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear every instance past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: aaa bbb ccc aaa bbb + selections: + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: aa ccc aa + selections: + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceThisPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceThisPastBat.yml new file mode 100644 index 0000000000..5ecc92fb8d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearEveryInstanceThisPastBat.yml @@ -0,0 +1,35 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear every instance this past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + mark: {type: cursor} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: aaa bbb ccc aaa bbb + selections: + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: " ccc " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstInstanceAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstInstanceAir.yml new file mode 100644 index 0000000000..dd81543d27 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstInstanceAir.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear first instance air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: instance} + start: 0 + length: 1 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 20} + end: {line: 0, character: 23} +finalState: + documentContents: |2 + bbb ccc aaa ddd aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstTwoInstancesAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstTwoInstancesAir.yml new file mode 100644 index 0000000000..b1ef8317ee --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearFirstTwoInstancesAir.yml @@ -0,0 +1,32 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear first two instances air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: instance} + start: 0 + length: 2 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa eee + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: |2 + bbb ccc ddd aaa eee + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearLastTwoInstancesAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearLastTwoInstancesAir.yml new file mode 100644 index 0000000000..10756b96b3 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearLastTwoInstancesAir.yml @@ -0,0 +1,32 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear last two instances air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: instance} + start: -2 + length: 2 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa eee + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa bbb ccc ddd eee + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAir.yml new file mode 100644 index 0000000000..3b5faa3630 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAir.yml @@ -0,0 +1,31 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear next instance air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 1 + length: 1 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa bbb ccc ddd aaa + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAirPastBat.yml new file mode 100644 index 0000000000..0f31a11367 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextInstanceAirPastBat.yml @@ -0,0 +1,41 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear next instance air past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 1 + length: 1 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa bbb ccc + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextTwoInstancesAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextTwoInstancesAir.yml new file mode 100644 index 0000000000..bdc373fcd6 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearNextTwoInstancesAir.yml @@ -0,0 +1,33 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear next two instances air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 1 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa bbb ccc ddd + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPastNextInstance.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPastNextInstance.yml new file mode 100644 index 0000000000..cb10386d79 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPastNextInstance.yml @@ -0,0 +1,38 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear past next instance + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: {type: implicit} + active: + type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 1 + length: 1 + direction: forward + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb aaa fff + ddd eee ddd ggg + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: {} +finalState: + documentContents: |2 + fff + ggg + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPreviousTwoInstancesAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPreviousTwoInstancesAir.yml new file mode 100644 index 0000000000..d43dcaf7c8 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearPreviousTwoInstancesAir.yml @@ -0,0 +1,33 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear previous two instances air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 1 + length: 2 + direction: backward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 20} + end: {line: 0, character: 23} +finalState: + documentContents: |2 + bbb ccc ddd aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearThreeInstances.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearThreeInstances.yml new file mode 100644 index 0000000000..152ad5e8e1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearThreeInstances.yml @@ -0,0 +1,21 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear three instances + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 3 + direction: forward + usePrePhraseSnapshot: true +initialState: + documentContents: aaa bbb aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +thrownError: {name: OutOfRangeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances.yml new file mode 100644 index 0000000000..a431db15a4 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances.yml @@ -0,0 +1,29 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa ddd aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: |2 + bbb ccc ddd aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances2.yml new file mode 100644 index 0000000000..48b2b4db73 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstances2.yml @@ -0,0 +1,27 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + usePrePhraseSnapshot: true +initialState: + documentContents: aaa bbb aaaa bbb aaa + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 3} + marks: {} +finalState: + documentContents: " bbb a bbb aaa" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesAirAndBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesAirAndBat.yml new file mode 100644 index 0000000000..a50466e8bc --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesAirAndBat.yml @@ -0,0 +1,44 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances air and bat + action: {name: clearAndSetSelection} + targets: + - type: list + elements: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: |2 + ccc + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + - anchor: {line: 0, character: 7} + active: {line: 0, character: 7} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBackward.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBackward.yml new file mode 100644 index 0000000000..d6eda0d5cd --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBackward.yml @@ -0,0 +1,27 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances backward + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: backward + usePrePhraseSnapshot: true +initialState: + documentContents: bbb aaa bbb aaa bbb + selections: + - anchor: {line: 0, character: 19} + active: {line: 0, character: 19} + marks: {} +finalState: + documentContents: "bbb aaa aaa " + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat.yml new file mode 100644 index 0000000000..dcefef0309 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat.yml @@ -0,0 +1,33 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances bat + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: b} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa ccc aaa aaa bbb + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat2.yml new file mode 100644 index 0000000000..3a9d9c1b51 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBat2.yml @@ -0,0 +1,33 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances bat + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: b} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbbb aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa ccc aaa bbbb aaa + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 22} + active: {line: 0, character: 22} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBlueAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBlueAirPastBat.yml new file mode 100644 index 0000000000..e6281906c7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesBlueAirPastBat.yml @@ -0,0 +1,43 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances blue air past bat + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: blue, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbbb aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + blue.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: |2 + ccc aaa bbbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesEveryTokenBatPastDrum.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesEveryTokenBatPastDrum.yml new file mode 100644 index 0000000000..a9454f1122 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesEveryTokenBatPastDrum.yml @@ -0,0 +1,63 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances every token bat past drum + action: {name: clearAndSetSelection} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - type: everyScope + scopeType: {type: token} + mark: {type: decoratedSymbol, symbolColor: default, character: b} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: d} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc ddd eee + aaa + bbb + ccc + ddd + eee + selections: + - anchor: {line: 6, character: 0} + active: {line: 6, character: 0} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} + default.d: + start: {line: 0, character: 12} + end: {line: 0, character: 15} +finalState: + documentContents: | + aaa eee + aaa + + + + eee + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + - anchor: {line: 2, character: 0} + active: {line: 2, character: 0} + - anchor: {line: 3, character: 0} + active: {line: 3, character: 0} + - anchor: {line: 4, character: 0} + active: {line: 4, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesJustBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesJustBat.yml new file mode 100644 index 0000000000..39d4c1f0a2 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesJustBat.yml @@ -0,0 +1,34 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances just bat + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - {type: toRawSelection} + mark: {type: decoratedSymbol, symbolColor: default, character: b} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbbb aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa ccc aaa b aaa bbb + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLastWordAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLastWordAir.yml new file mode 100644 index 0000000000..414ab6c509 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLastWordAir.yml @@ -0,0 +1,35 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances last word air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - type: ordinalScope + scopeType: {type: word} + start: -1 + length: 1 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: aaaBbb cccBbbb dddBbb + selections: + - anchor: {line: 0, character: 21} + active: {line: 0, character: 21} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 6} +finalState: + documentContents: aaa cccBbbb ddd + selections: + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + - anchor: {line: 0, character: 15} + active: {line: 0, character: 15} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLineAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLineAir.yml new file mode 100644 index 0000000000..01fc8ee06c --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesLineAir.yml @@ -0,0 +1,39 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances line air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - type: containingScope + scopeType: {type: line} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb + aaa bbb ccc + aaa bbb + selections: + - anchor: {line: 3, character: 0} + active: {line: 3, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: |+ + + aaa bbb ccc + + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 2, character: 0} + active: {line: 2, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesTwoClicksAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesTwoClicksAir.yml new file mode 100644 index 0000000000..5224309236 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/clearTwoInstancesTwoClicksAir.yml @@ -0,0 +1,38 @@ +languageId: plaintext +command: + version: 5 + spokenForm: clear two instances two clicks air + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: relativeScope + scopeType: {type: instance} + offset: 0 + length: 2 + direction: forward + - type: relativeScope + scopeType: {type: token} + offset: 0 + length: 2 + direction: forward + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbbb aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: |2 + ccc aaa bbbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryCarEveryInstanceAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryCarEveryInstanceAirPastBat.yml new file mode 100644 index 0000000000..baae4837c8 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryCarEveryInstanceAirPastBat.yml @@ -0,0 +1,66 @@ +languageId: plaintext +command: + version: 5 + spokenForm: pre every car every instance air past bat + action: {name: setSelectionBefore} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: character} + - type: everyScope + scopeType: {type: instance} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} + - anchor: {line: 0, character: 15} + active: {line: 0, character: 15} + - anchor: {line: 0, character: 16} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} + - anchor: {line: 0, character: 18} + active: {line: 0, character: 18} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceEveryCarAirPastBat.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceEveryCarAirPastBat.yml new file mode 100644 index 0000000000..1341b609cb --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceEveryCarAirPastBat.yml @@ -0,0 +1,70 @@ +languageId: plaintext +command: + version: 5 + spokenForm: pre every instance every car air past bat + action: {name: setSelectionBefore} + targets: + - type: range + anchor: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + - type: everyScope + scopeType: {type: character} + mark: {type: decoratedSymbol, symbolColor: default, character: a} + active: + type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: b} + excludeAnchor: false + excludeActive: false + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + default.b: + start: {line: 0, character: 4} + end: {line: 0, character: 7} +finalState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + - anchor: {line: 0, character: 7} + active: {line: 0, character: 7} + - anchor: {line: 0, character: 11} + active: {line: 0, character: 11} + - anchor: {line: 0, character: 15} + active: {line: 0, character: 15} + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + - anchor: {line: 0, character: 16} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} + - anchor: {line: 0, character: 18} + active: {line: 0, character: 18} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceFirstCarAir.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceFirstCarAir.yml new file mode 100644 index 0000000000..ce84324bb7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/modifiers/instance/preEveryInstanceFirstCarAir.yml @@ -0,0 +1,42 @@ +languageId: plaintext +command: + version: 5 + spokenForm: pre every instance first car air + action: {name: setSelectionBefore} + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: instance} + - type: ordinalScope + scopeType: {type: character} + start: 0 + length: 1 + mark: {type: decoratedSymbol, symbolColor: default, character: a} + usePrePhraseSnapshot: true +initialState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} + marks: + default.a: + start: {line: 0, character: 0} + end: {line: 0, character: 3} +finalState: + documentContents: | + aaa bbb ccc aaa bbb + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14}