diff --git a/cursorless-talon/src/modifiers/containing_scope.py b/cursorless-talon/src/modifiers/containing_scope.py index c9ce567c4d..62905178ff 100644 --- a/cursorless-talon/src/modifiers/containing_scope.py +++ b/cursorless-talon/src/modifiers/containing_scope.py @@ -53,6 +53,7 @@ "file": "document", "line": "line", "paint": "nonWhitespaceSequence", + "short paint": "boundedNonWhitespaceSequence", "link": "url", "token": "token", } diff --git a/src/processTargets/getModifierStage.ts b/src/processTargets/getModifierStage.ts index e4f8eb7876..ff7af44716 100644 --- a/src/processTargets/getModifierStage.ts +++ b/src/processTargets/getModifierStage.ts @@ -31,6 +31,9 @@ import { UrlStage, } from "./modifiers/scopeTypeStages/RegexStage"; import TokenStage from "./modifiers/scopeTypeStages/TokenStage"; +import BoundedNonWhitespaceSequenceStage, { + BoundedNonWhitespaceSequenceModifier, +} from "./modifiers/BoundedNonWhitespaceStage"; import SurroundingPairStage from "./modifiers/SurroundingPairStage"; import { ModifierStage } from "./PipelineStages.types"; @@ -89,6 +92,10 @@ const getContainingScopeStage = ( return new NonWhitespaceSequenceStage( modifier as NonWhitespaceSequenceModifier ); + case "boundedNonWhitespaceSequence": + return new BoundedNonWhitespaceSequenceStage( + modifier as BoundedNonWhitespaceSequenceModifier + ); case "url": return new UrlStage(modifier as UrlModifier); case "surroundingPair": diff --git a/src/processTargets/modifiers/BoundedNonWhitespaceStage.ts b/src/processTargets/modifiers/BoundedNonWhitespaceStage.ts new file mode 100644 index 0000000000..7259c5acbc --- /dev/null +++ b/src/processTargets/modifiers/BoundedNonWhitespaceStage.ts @@ -0,0 +1,77 @@ +import { Target } from "../../typings/target.types"; +import { + ContainingScopeModifier, + EveryScopeModifier, +} from "../../typings/targetDescriptor.types"; +import { ProcessedTargetsContext } from "../../typings/Types"; +import { ModifierStage } from "../PipelineStages.types"; +import { TokenTarget } from "../targets"; +import getModifierStage from "../getModifierStage"; +import { processSurroundingPair } from "./surroundingPair"; +import { NoContainingScopeError } from "../../errors"; + +export type BoundedNonWhitespaceSequenceModifier = ( + | ContainingScopeModifier + | EveryScopeModifier +) & { + scopeType: { type: "boundedNonWhitespaceSequence" }; +}; + +/** + * Intersection of NonWhitespaceSequenceStage and a surrounding pair + * Expand the target until reaching a white space or surrounding pair. + * If there is no surrounding pair defaults to the non white space sequence + */ +export default class BoundedNonWhitespaceSequenceStage + implements ModifierStage +{ + constructor(private modifier: BoundedNonWhitespaceSequenceModifier) {} + + run(context: ProcessedTargetsContext, target: Target): Target[] { + const paintStage = getModifierStage({ + type: this.modifier.type, + scopeType: { type: "nonWhitespaceSequence" }, + }); + + const paintTargets = paintStage.run(context, target); + + const pairInfo = processSurroundingPair( + context, + target.editor, + target.contentRange, + { + type: "surroundingPair", + delimiter: "any", + requireStrongContainment: true, + } + ); + + if (pairInfo == null) { + return paintTargets; + } + + const targets = paintTargets.flatMap((paintTarget) => { + const contentRange = paintTarget.contentRange.intersection( + pairInfo.interiorRange + ); + + if (contentRange == null || contentRange.isEmpty) { + return []; + } + + return [ + new TokenTarget({ + editor: target.editor, + isReversed: target.isReversed, + contentRange, + }), + ]; + }); + + if (targets.length === 0) { + throw new NoContainingScopeError(this.modifier.scopeType.type); + } + + return targets; + } +} diff --git a/src/processTargets/modifiers/scopeTypeStages/RegexStage.ts b/src/processTargets/modifiers/scopeTypeStages/RegexStage.ts index 301c45c927..4ceb041469 100644 --- a/src/processTargets/modifiers/scopeTypeStages/RegexStage.ts +++ b/src/processTargets/modifiers/scopeTypeStages/RegexStage.ts @@ -38,7 +38,10 @@ class RegexStage implements ModifierStage { for (let i = start.line; i <= end.line; ++i) { this.getMatchesForLine(editor, i).forEach((range) => { // Regex match and selection intersects - if (range.end.isAfterOrEqual(start) && range.end.isBeforeOrEqual(end)) { + if ( + range.end.isAfterOrEqual(start) && + range.start.isBeforeOrEqual(end) + ) { targets.push(this.getTargetFromRange(target, range)); } }); diff --git a/src/processTargets/modifiers/surroundingPair/findDelimiterPairAdjacentToSelection.ts b/src/processTargets/modifiers/surroundingPair/findDelimiterPairAdjacentToSelection.ts index 42ad36b765..64f8e3f246 100644 --- a/src/processTargets/modifiers/surroundingPair/findDelimiterPairAdjacentToSelection.ts +++ b/src/processTargets/modifiers/surroundingPair/findDelimiterPairAdjacentToSelection.ts @@ -1,11 +1,13 @@ +import { SurroundingPairScopeType } from "../../../typings/targetDescriptor.types"; +import { findOppositeDelimiter } from "./findOppositeDelimiter"; import { getSurroundingPairOffsets } from "./getSurroundingPairOffsets"; import { - SurroundingPairOffsets, + DelimiterOccurrence, Offsets, PossibleDelimiterOccurrence, - DelimiterOccurrence, + SurroundingPairOffsets, } from "./types"; -import { findOppositeDelimiter } from "./findOppositeDelimiter"; +import { weaklyContains } from "./weaklyContains"; /** * Looks for a surrounding pair where one of its delimiters contains the entire selection. @@ -28,7 +30,7 @@ export function findDelimiterPairAdjacentToSelection( initialIndex: number, delimiterOccurrences: PossibleDelimiterOccurrence[], selectionOffsets: Offsets, - forceDirection: "left" | "right" | undefined, + scopeType: SurroundingPairScopeType, bailOnUnmatchedAdjacent: boolean = false ): SurroundingPairOffsets | null { const indicesToTry = [initialIndex + 1, initialIndex]; @@ -38,8 +40,7 @@ export function findDelimiterPairAdjacentToSelection( if ( delimiterOccurrence != null && - delimiterOccurrence.offsets.start <= selectionOffsets.start && - delimiterOccurrence.offsets.end >= selectionOffsets.end + weaklyContains(delimiterOccurrence.offsets, selectionOffsets) ) { const { delimiterInfo } = delimiterOccurrence; @@ -48,14 +49,23 @@ export function findDelimiterPairAdjacentToSelection( delimiterOccurrences, index, delimiterInfo, - forceDirection + scopeType.forceDirection ); if (possibleMatch != null) { - return getSurroundingPairOffsets( + const surroundingPairOffsets = getSurroundingPairOffsets( delimiterOccurrence as DelimiterOccurrence, possibleMatch ); + + if ( + !scopeType.requireStrongContainment || + (surroundingPairOffsets.leftDelimiter.start < + selectionOffsets.start && + surroundingPairOffsets.rightDelimiter.end > selectionOffsets.end) + ) { + return surroundingPairOffsets; + } } else if (bailOnUnmatchedAdjacent) { return null; } diff --git a/src/processTargets/modifiers/surroundingPair/findSurroundingPairCore.ts b/src/processTargets/modifiers/surroundingPair/findSurroundingPairCore.ts index d0485053b6..6a0708aa4b 100644 --- a/src/processTargets/modifiers/surroundingPair/findSurroundingPairCore.ts +++ b/src/processTargets/modifiers/surroundingPair/findSurroundingPairCore.ts @@ -1,5 +1,8 @@ import { sortedIndexBy } from "lodash"; -import { SimpleSurroundingPairName } from "../../../typings/targetDescriptor.types"; +import { + SimpleSurroundingPairName, + SurroundingPairScopeType, +} from "../../../typings/targetDescriptor.types"; import { findDelimiterPairAdjacentToSelection } from "./findDelimiterPairAdjacentToSelection"; import { findDelimiterPairContainingSelection } from "./findDelimiterPairContainingSelection"; import { @@ -30,7 +33,7 @@ import { * @returns */ export function findSurroundingPairCore( - forceDirection: "left" | "right" | undefined, + scopeType: SurroundingPairScopeType, delimiterOccurrences: PossibleDelimiterOccurrence[], acceptableDelimiters: SimpleSurroundingPairName[], selectionOffsets: Offsets, @@ -57,7 +60,7 @@ export function findSurroundingPairCore( initialIndex, delimiterOccurrences, selectionOffsets, - forceDirection, + scopeType, bailOnUnmatchedAdjacent ); diff --git a/src/processTargets/modifiers/surroundingPair/findSurroundingPairParseTreeBased.ts b/src/processTargets/modifiers/surroundingPair/findSurroundingPairParseTreeBased.ts index 374f1772e2..8968e5dc41 100644 --- a/src/processTargets/modifiers/surroundingPair/findSurroundingPairParseTreeBased.ts +++ b/src/processTargets/modifiers/surroundingPair/findSurroundingPairParseTreeBased.ts @@ -2,7 +2,7 @@ import { Range, TextDocument, TextEditor } from "vscode"; import { SyntaxNode } from "web-tree-sitter"; import { SimpleSurroundingPairName, - SurroundingPairDirection, + SurroundingPairScopeType, } from "../../../typings/targetDescriptor.types"; import { getNodeRange } from "../../../util/nodeSelectors"; import { isContainedInErrorNode } from "../../../util/treeSitterUtils"; @@ -62,7 +62,7 @@ export function findSurroundingPairParseTreeBased( selection: Range, node: SyntaxNode, delimiters: SimpleSurroundingPairName[], - forceDirection: "left" | "right" | undefined + scopeType: SurroundingPairScopeType ) { const document: TextDocument = editor.document; @@ -88,7 +88,7 @@ export function findSurroundingPairParseTreeBased( individualDelimiters, delimiters, selectionOffsets, - forceDirection, + scopeType, }; // Walk up the parse tree from parent to parent until we find a node whose @@ -149,7 +149,7 @@ interface Context { */ selectionOffsets: Offsets; - forceDirection: SurroundingPairDirection | undefined; + scopeType: SurroundingPairScopeType; } /** @@ -170,7 +170,7 @@ function findSurroundingPairContainedInNode( individualDelimiters, delimiters, selectionOffsets, - forceDirection, + scopeType, } = context; /** @@ -213,7 +213,7 @@ function findSurroundingPairContainedInNode( // approach might not always work, but seems to work in the // languages we've tried. let side = - delimiterInfo.side === "unknown" && forceDirection == null + delimiterInfo.side === "unknown" && scopeType.forceDirection == null ? inferDelimiterSide(delimiterNode) : delimiterInfo.side; @@ -227,7 +227,7 @@ function findSurroundingPairContainedInNode( // Just run core algorithm once we have our list of delimiters. return findSurroundingPairCore( - forceDirection, + scopeType, delimiterOccurrences, delimiters, selectionOffsets, diff --git a/src/processTargets/modifiers/surroundingPair/findSurroundingPairTextBased.ts b/src/processTargets/modifiers/surroundingPair/findSurroundingPairTextBased.ts index 7caf64353c..f395354898 100644 --- a/src/processTargets/modifiers/surroundingPair/findSurroundingPairTextBased.ts +++ b/src/processTargets/modifiers/surroundingPair/findSurroundingPairTextBased.ts @@ -2,8 +2,8 @@ import { escapeRegExp, findLast, uniq } from "lodash"; import { Range, TextDocument, TextEditor } from "vscode"; import { SimpleSurroundingPairName, - SurroundingPairDirection, SurroundingPairName, + SurroundingPairScopeType, } from "../../../typings/targetDescriptor.types"; import { getDocumentRange } from "../../../util/range"; import { matchAll } from "../../../util/regex"; @@ -70,7 +70,7 @@ export function findSurroundingPairTextBased( range: Range, allowableRange: Range | null, delimiters: SimpleSurroundingPairName[], - forceDirection: "left" | "right" | undefined + scopeType: SurroundingPairScopeType ) { const document: TextDocument = editor.document; const fullRange = allowableRange ?? getDocumentRange(document); @@ -106,7 +106,7 @@ export function findSurroundingPairTextBased( * Context to pass to nested call */ const context: Context = { - forceDirection, + scopeType, delimiterRegex, delimiters, delimiterTextToDelimiterInfoMap, @@ -196,7 +196,7 @@ function getDelimiterRegex(individualDelimiters: IndividualDelimiter[]) { * Context to pass to nested call */ interface Context { - forceDirection: SurroundingPairDirection | undefined; + scopeType: SurroundingPairScopeType; delimiterTextToDelimiterInfoMap: { [k: string]: IndividualDelimiter; }; @@ -229,11 +229,12 @@ function getDelimiterPairOffsets( isAtEndOfFullRange: boolean ): SurroundingPairOffsets | null { const { - forceDirection, + scopeType, delimiterTextToDelimiterInfoMap, delimiterRegex, delimiters, } = context; + const { forceDirection } = scopeType; // XXX: The below is a bit wasteful when there are multiple targets, because // this whole function gets run once per target, so we're re-running this @@ -290,7 +291,7 @@ function getDelimiterPairOffsets( // Then just run core algorithm const surroundingPair = findSurroundingPairCore( - forceDirection, + scopeType, delimiterOccurrences, delimiters, selectionOffsets, diff --git a/src/processTargets/modifiers/surroundingPair/index.ts b/src/processTargets/modifiers/surroundingPair/index.ts index b86b154785..93a66ad986 100644 --- a/src/processTargets/modifiers/surroundingPair/index.ts +++ b/src/processTargets/modifiers/surroundingPair/index.ts @@ -21,8 +21,9 @@ import { findSurroundingPairTextBased } from "./findSurroundingPairTextBased"; * smallest pair of delimiters which contains the selection. * * @param context Context to be leveraged by modifier - * @param selection The selection to process - * @param modifier The surrounding pair modifier information + * @param editor The editor containing the range + * @param range The range to process + * @param scopeType The surrounding pair modifier information * @returns The new selection expanded to the containing surrounding pair or * `null` if none was found */ @@ -30,12 +31,12 @@ export function processSurroundingPair( context: ProcessedTargetsContext, editor: TextEditor, range: Range, - modifier: SurroundingPairScopeType + scopeType: SurroundingPairScopeType ): SurroundingPairInfo | null { const document = editor.document; const delimiters = complexDelimiterMap[ - modifier.delimiter as ComplexSurroundingPairName - ] ?? [modifier.delimiter]; + scopeType.delimiter as ComplexSurroundingPairName + ] ?? [scopeType.delimiter]; let node: SyntaxNode | null; let textFragmentExtractor: TextFragmentExtractor; @@ -53,7 +54,7 @@ export function processSurroundingPair( range, null, delimiters, - modifier.forceDirection + scopeType ); } else { throw err; @@ -73,7 +74,7 @@ export function processSurroundingPair( range, textFragmentRange, delimiters, - modifier.forceDirection + scopeType ); if (surroundingRange != null) { @@ -89,6 +90,6 @@ export function processSurroundingPair( range, node, delimiters, - modifier.forceDirection + scopeType ); } diff --git a/src/processTargets/modifiers/surroundingPair/weaklyContains.ts b/src/processTargets/modifiers/surroundingPair/weaklyContains.ts new file mode 100644 index 0000000000..bf727be34e --- /dev/null +++ b/src/processTargets/modifiers/surroundingPair/weaklyContains.ts @@ -0,0 +1,13 @@ +import { Offsets } from "./types"; + +/** + * Determines whether {@link offsets1} weakly contains {@link offsets2}, which + * defined as the boundaries of {@link offsets1} being inside or equal to the + * boundaries of {@link offsets2}. + * @param offsets1 The first set of offsets + * @param offsets2 The second set of offsets + * @returns `true` if {@link offsets1} weakly contains {@link offsets2} + */ +export function weaklyContains(offsets1: Offsets, offsets2: Offsets) { + return offsets1.start <= offsets2.start && offsets1.end >= offsets2.end; +} diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint.yml new file mode 100644 index 0000000000..5e8b6aa69d --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: change every paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: nonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: aa|aa-().c_d bb|bb-().'' + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +finalState: + documentContents: " " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: nonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint2.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint2.yml new file mode 100644 index 0000000000..85f1b270e0 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint2.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: change every paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: nonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: " " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: nonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint3.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint3.yml new file mode 100644 index 0000000000..967a73b36d --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaint3.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: change every paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: nonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 28} + marks: {} +finalState: + documentContents: " " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: nonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintInsideParen2.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintInsideParen2.yml new file mode 100644 index 0000000000..8fcf113409 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintInsideParen2.yml @@ -0,0 +1,35 @@ +languageId: plaintext +command: + spokenForm: change every paint inside paren + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: everyScope + scopeType: {type: nonWhitespaceSequence} + - {type: interiorOnly} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') { return 1; } + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.(: + start: {line: 0, character: 3} + end: {line: 0, character: 4} +finalState: + documentContents: " { return 1; }" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: everyScope, scopeType: {type: nonWhitespaceSequence}}, {type: interiorOnly}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintPairParen2.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintPairParen2.yml new file mode 100644 index 0000000000..84282a72d3 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryPaintPairParen2.yml @@ -0,0 +1,36 @@ +languageId: plaintext +command: + spokenForm: change every paint pair paren + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: everyScope + scopeType: {type: nonWhitespaceSequence} + - type: containingScope + scopeType: {type: surroundingPair, delimiter: any} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') { return 1; } + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: + default.(: + start: {line: 0, character: 3} + end: {line: 0, character: 4} +finalState: + documentContents: " { return 1; }" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: everyScope, scopeType: {type: nonWhitespaceSequence}}, {type: containingScope, scopeType: {type: surroundingPair, delimiter: any}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint.yml new file mode 100644 index 0000000000..ed2b53a37e --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint.yml @@ -0,0 +1,34 @@ +languageId: python +command: + spokenForm: change every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: several different words + selections: + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + marks: {} +finalState: + documentContents: " " + 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} + thatMark: + - 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} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint2.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint2.yml new file mode 100644 index 0000000000..faa8421edf --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint2.yml @@ -0,0 +1,34 @@ +languageId: plaintext +command: + spokenForm: change every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: some.text.here some-other-text word()[] + selections: + - anchor: {line: 0, character: 20} + active: {line: 0, character: 20} + marks: {} +finalState: + documentContents: " " + 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} + thatMark: + - 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} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint3.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint3.yml new file mode 100644 index 0000000000..bb8ccce55e --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint3.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: change every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "\"aa|aa-().c_d\" (bb|bb-().'')" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: " " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint4.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint4.yml new file mode 100644 index 0000000000..4300e6de62 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaint4.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: change every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: " " + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintInsideParen.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintInsideParen.yml new file mode 100644 index 0000000000..e78802c920 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintInsideParen.yml @@ -0,0 +1,35 @@ +languageId: plaintext +command: + spokenForm: change every short paint inside paren + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + - {type: interiorOnly} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: + default.(: + start: {line: 0, character: 3} + end: {line: 0, character: 4} +finalState: + documentContents: foo( ) + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + thatMark: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}, {type: interiorOnly}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintPairParen.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintPairParen.yml new file mode 100644 index 0000000000..55757a1a5e --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeEveryShortPaintPairParen.yml @@ -0,0 +1,36 @@ +languageId: plaintext +command: + spokenForm: change every short paint pair paren + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + - type: containingScope + scopeType: {type: surroundingPair, delimiter: any} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-().c_d bb|bb-().'') + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.(: + start: {line: 0, character: 3} + end: {line: 0, character: 4} +finalState: + documentContents: foo( ) + selections: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} + thatMark: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}, {type: containingScope, scopeType: {type: surroundingPair, delimiter: any}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/changeShortPaintParen.yml b/src/test/suite/fixtures/recorded/selectionTypes/changeShortPaintParen.yml new file mode 100644 index 0000000000..a29af962ed --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/changeShortPaintParen.yml @@ -0,0 +1,30 @@ + +command: + spokenForm: change short paint paren + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: foo(aa|aa-.c_d bb|bb-.'') + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: + default.(: + start: {line: 0, character: 3} + end: {line: 0, character: 4} +finalState: + documentContents: " bb|bb-.'')" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckEveryShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckEveryShortPaint.yml new file mode 100644 index 0000000000..09ac3a401e --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckEveryShortPaint.yml @@ -0,0 +1,26 @@ +languageId: plaintext +command: + spokenForm: chuck every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: some.text.here some-other-text word()[] + selections: + - anchor: {line: 0, character: 20} + active: {line: 0, character: 20} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintAir.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintAir.yml new file mode 100644 index 0000000000..e1ab65cad6 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintAir.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: chuck small paint air + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: a} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: some amount of text + selections: + - anchor: {line: 0, character: 19} + active: {line: 0, character: 19} + marks: + default.a: + start: {line: 0, character: 5} + end: {line: 0, character: 11} +finalState: + documentContents: some of text + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + thatMark: + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: a}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine.yml new file mode 100644 index 0000000000..f8a94c0e96 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: chuck small paint fine + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: f} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: "[foo[0], bar]" + selections: + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + marks: + default.f: + start: {line: 0, character: 1} + end: {line: 0, character: 4} +finalState: + documentContents: "[ bar]" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: f}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine2.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine2.yml new file mode 100644 index 0000000000..fbadb5e786 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintFine2.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: chuck small paint fine + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: f} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: "[baz, foo[0], bar]" + selections: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + marks: + default.f: + start: {line: 0, character: 6} + end: {line: 0, character: 9} +finalState: + documentContents: "[baz, bar]" + selections: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + thatMark: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: f}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintSoap2.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintSoap2.yml new file mode 100644 index 0000000000..57d75cb077 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintSoap2.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: chuck small paint soap + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: s} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: f.o(some() text) + selections: + - anchor: {line: 0, character: 16} + active: {line: 0, character: 16} + marks: + default.s: + start: {line: 0, character: 4} + end: {line: 0, character: 8} +finalState: + documentContents: f.o( text) + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} + thatMark: + - anchor: {line: 0, character: 4} + active: {line: 0, character: 4} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: s}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintZero.yml b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintZero.yml new file mode 100644 index 0000000000..0418df6f3f --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/chuckSmallPaintZero.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: chuck small paint zero + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: '0'} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: remove} +initialState: + documentContents: "[foo[0], bar]" + selections: + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + marks: + default.0: + start: {line: 0, character: 5} + end: {line: 0, character: 6} +finalState: + documentContents: "[foo[], bar]" + selections: + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + thatMark: + - anchor: {line: 0, character: 5} + active: {line: 0, character: 5} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: '0'}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint.yml new file mode 100644 index 0000000000..0607d56613 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: clear every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 11} + active: {line: 0, character: 11} + marks: {} +finalState: + documentContents: "{foo.bar( )} test-this" + selections: + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} + thatMark: + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint2.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint2.yml new file mode 100644 index 0000000000..95016a55b7 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearEveryShortPaint2.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: clear every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "{ } test-this" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint.yml new file mode 100644 index 0000000000..447a2c3d6d --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint.yml @@ -0,0 +1,26 @@ +languageId: plaintext +command: + spokenForm: clear short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} + marks: {} +finalState: + documentContents: "{foo.bar( whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} + thatMark: + - anchor: {line: 0, character: 9} + active: {line: 0, character: 9} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint2.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint2.yml new file mode 100644 index 0000000000..c5f499d1cc --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint2.yml @@ -0,0 +1,26 @@ +languageId: plaintext +command: + spokenForm: clear short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "{ whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint3.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint3.yml new file mode 100644 index 0000000000..0efbd7feb4 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaint3.yml @@ -0,0 +1,26 @@ +languageId: plaintext +command: + spokenForm: clear short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 11} + marks: {} +finalState: + documentContents: "{ whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaintLeper.yml b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaintLeper.yml new file mode 100644 index 0000000000..3934237e28 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/clearShortPaintLeper.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: clear short paint leper + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: (} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: clearAndSetSelection} +initialState: + documentContents: "{foo.bar(hello-world, whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 14} + active: {line: 0, character: 14} + marks: + default.(: + start: {line: 0, character: 8} + end: {line: 0, character: 9} +finalState: + documentContents: "{ whatever-now)} test-this" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: (}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint.yml new file mode 100644 index 0000000000..cf3022349e --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint.yml @@ -0,0 +1,34 @@ +languageId: plaintext +command: + spokenForm: take every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 33} + active: {line: 0, character: 33} + marks: {} +finalState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 32} + - anchor: {line: 0, character: 33} + active: {line: 0, character: 44} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 32} + - anchor: {line: 0, character: 33} + active: {line: 0, character: 44} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint2.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint2.yml new file mode 100644 index 0000000000..58b2b0ec1c --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint2.yml @@ -0,0 +1,30 @@ +languageId: plaintext +command: + spokenForm: take every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 29} + active: {line: 0, character: 29} + marks: {} +finalState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 7} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 31} + thatMark: + - anchor: {line: 0, character: 7} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 31} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint3.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint3.yml new file mode 100644 index 0000000000..49a2528d02 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeEveryShortPaint3.yml @@ -0,0 +1,34 @@ +languageId: plaintext +command: + spokenForm: take every short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: everyScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 32} + - anchor: {line: 0, character: 33} + active: {line: 0, character: 44} + thatMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 16} + - anchor: {line: 0, character: 17} + active: {line: 0, character: 32} + - anchor: {line: 0, character: 33} + active: {line: 0, character: 44} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: everyScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeShortPaint.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeShortPaint.yml new file mode 100644 index 0000000000..c2271b9588 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeShortPaint.yml @@ -0,0 +1,26 @@ +languageId: plaintext +command: + spokenForm: take short paint + version: 2 + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 7} + active: {line: 0, character: 7} + marks: {} +finalState: + documentContents: foo[0](bar.test, baz-other-test) something[] + selections: + - anchor: {line: 0, character: 7} + active: {line: 0, character: 16} + thatMark: + - anchor: {line: 0, character: 7} + active: {line: 0, character: 16} +fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintAir.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintAir.yml new file mode 100644 index 0000000000..1ae942953f --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintAir.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: take small paint air + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: a} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: some amount of text + selections: + - anchor: {line: 0, character: 19} + active: {line: 0, character: 19} + marks: + default.a: + start: {line: 0, character: 5} + end: {line: 0, character: 11} +finalState: + documentContents: some amount of text + selections: + - anchor: {line: 0, character: 5} + active: {line: 0, character: 11} + thatMark: + - anchor: {line: 0, character: 5} + active: {line: 0, character: 11} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: a}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine.yml new file mode 100644 index 0000000000..e1088696f9 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: take small paint fine + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: f} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: "[foo[0], bar]" + selections: + - anchor: {line: 0, character: 3} + active: {line: 0, character: 3} + marks: + default.f: + start: {line: 0, character: 1} + end: {line: 0, character: 4} +finalState: + documentContents: "[foo[0], bar]" + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 8} + thatMark: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 8} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: f}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine2.yml b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine2.yml new file mode 100644 index 0000000000..72c58c32c6 --- /dev/null +++ b/src/test/suite/fixtures/recorded/selectionTypes/takeSmallPaintFine2.yml @@ -0,0 +1,30 @@ +languageId: python +command: + spokenForm: take small paint fine + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: f} + modifiers: + - type: containingScope + scopeType: {type: boundedNonWhitespaceSequence} + usePrePhraseSnapshot: true + action: {name: setSelection} +initialState: + documentContents: "[baz, foo[0], bar]" + selections: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 6} + marks: + default.f: + start: {line: 0, character: 6} + end: {line: 0, character: 9} +finalState: + documentContents: "[baz, foo[0], bar]" + selections: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 13} + thatMark: + - anchor: {line: 0, character: 6} + active: {line: 0, character: 13} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: f}, modifiers: [{type: containingScope, scopeType: {type: boundedNonWhitespaceSequence}}]}] diff --git a/src/typings/targetDescriptor.types.ts b/src/typings/targetDescriptor.types.ts index 5590fc3750..cc95e9ab3f 100644 --- a/src/typings/targetDescriptor.types.ts +++ b/src/typings/targetDescriptor.types.ts @@ -109,6 +109,7 @@ export type SimpleScopeTypeType = | "character" | "word" | "nonWhitespaceSequence" + | "boundedNonWhitespaceSequence" | "url"; export interface SimpleScopeType { @@ -120,6 +121,12 @@ export interface SurroundingPairScopeType { type: "surroundingPair"; delimiter: SurroundingPairName; forceDirection?: SurroundingPairDirection; + + /** + * If `true`, then only accept pairs where the pair completely contains the + * selection, ie without the edges touching. + */ + requireStrongContainment?: boolean; } export type ScopeType = SimpleScopeType | SurroundingPairScopeType;