From 13244c11c03a1769c95bf7969e38da0a5294e3ae Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Sun, 19 Jun 2022 13:42:40 +0100 Subject: [PATCH 01/12] Fix positional inference --- src/core/commandRunner/CommandRunner.ts | 3 +- src/core/inferFullTargets.ts | 115 +++++++++++++++--------- src/test/suite/runTestSubset.ts | 2 +- 3 files changed, 77 insertions(+), 43 deletions(-) diff --git a/src/core/commandRunner/CommandRunner.ts b/src/core/commandRunner/CommandRunner.ts index 7f0bc0e9bf..ff4e901cdf 100644 --- a/src/core/commandRunner/CommandRunner.ts +++ b/src/core/commandRunner/CommandRunner.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import { ActionType } from "../../actions/actions.types"; import { OutdatedExtensionError } from "../../errors"; import processTargets from "../../processTargets"; +import isTesting from "../../testUtil/isTesting"; import { Graph, ProcessedTargetsContext } from "../../typings/Types"; import { isString } from "../../util/type"; import { canonicalizeAndValidateCommand } from "../commandVersionUpgrades/canonicalizeAndValidateCommand"; @@ -146,7 +147,7 @@ export default class CommandRunner { const err = e as Error; if (err instanceof OutdatedExtensionError) { this.showUpdateExtensionErrorMessage(err); - } else { + } else if (!isTesting()) { vscode.window.showErrorMessage(err.message); } console.error(err.message); diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 270177095f..0b129cfa45 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -94,36 +94,27 @@ function inferPrimitiveTarget( }; } - const hasPosition = !!target.modifiers?.find( - (modifier) => modifier.type === "position" - ); + const ownPositionalModifier = getPosition(target); + const ownNonPositionalModifiers = getNonPositionalModifiers(target); // Position without a mark can be something like "take air past end of line" const mark = target.mark ?? - (hasPosition ? getPreviousMark(previousTargets) : null) ?? { + (!!ownPositionalModifier ? getPreviousMark(previousTargets) : null) ?? { type: "cursor", }; - const previousModifiers = getPreviousModifiers(previousTargets); + const nonPositionalModifiers = + ownNonPositionalModifiers ?? + getPreviousNonPositionalModifiers(previousTargets) ?? + []; - const modifiers = target.modifiers ?? previousModifiers ?? []; + const positionalModifier = + ownPositionalModifier ?? getPreviousPosition(previousTargets); - // "bring line to after this" needs to infer line on second target - const modifierTypes = [ - ...new Set(modifiers.map((modifier) => modifier.type)), + const modifiers = [ + ...(positionalModifier == null ? [] : [positionalModifier]), + ...nonPositionalModifiers, ]; - if ( - previousModifiers != null && - modifierTypes.length === 1 && - modifierTypes[0] === "position" - ) { - const containingScopeModifier = previousModifiers.find( - (modifier) => modifier.type === "containingScope" - ); - if (containingScopeModifier != null) { - modifiers.push(containingScopeModifier); - } - } return { type: target.type, @@ -132,45 +123,87 @@ function inferPrimitiveTarget( }; } +function getPosition(target: PartialPrimitiveTargetDescriptor) { + if (target.modifiers == null) { + return undefined; + } + + const positionModifierIndex = target.modifiers.findIndex( + (modifier) => modifier.type === "position" + ); + + if (positionModifierIndex > 0) { + throw Error("Position modifiers must be at the start of a modifier chain"); + } + + return positionModifierIndex === -1 ? undefined : target.modifiers[0]; +} + +function getNonPositionalModifiers(target: PartialPrimitiveTargetDescriptor) { + const nonPositionalModifiers = target.modifiers?.filter( + (modifier) => modifier.type !== "position" + ); + return nonPositionalModifiers == null || nonPositionalModifiers.length === 0 + ? undefined + : nonPositionalModifiers; +} + function getPreviousMark(previousTargets: PartialTargetDescriptor[]) { - return getPreviousTarget( + return getPreviousTargetAttribute( previousTargets, - (target: PartialPrimitiveTargetDescriptor) => target.mark != null - )?.mark; + (target: PartialPrimitiveTargetDescriptor) => target.mark + ); } -function getPreviousModifiers(previousTargets: PartialTargetDescriptor[]) { - return getPreviousTarget( +function getPreviousNonPositionalModifiers( + previousTargets: PartialTargetDescriptor[] +) { + return getPreviousTargetAttribute( previousTargets, - (target: PartialPrimitiveTargetDescriptor) => target.modifiers != null - )?.modifiers; + (target: PartialPrimitiveTargetDescriptor) => + getNonPositionalModifiers(target) + ); +} + +function getPreviousPosition(previousTargets: PartialTargetDescriptor[]) { + return getPreviousTargetAttribute( + previousTargets, + (target: PartialPrimitiveTargetDescriptor) => getPosition(target) + ); } -function getPreviousTarget( +function getPreviousTargetAttribute( previousTargets: PartialTargetDescriptor[], - useTarget: (target: PartialPrimitiveTargetDescriptor) => boolean -): PartialPrimitiveTargetDescriptor | null { + getAttribute: (target: PartialPrimitiveTargetDescriptor) => T | undefined +): T | undefined { // Search from back(last) to front(first) for (let i = previousTargets.length - 1; i > -1; --i) { const target = previousTargets[i]; switch (target.type) { - case "primitive": - if (useTarget(target)) { - return target; + case "primitive": { + const attributeValue = getAttribute(target); + if (attributeValue != null) { + return attributeValue; } break; - case "range": - if (useTarget(target.anchor)) { - return target.anchor; + } + case "range": { + const attributeValue = getAttribute(target.anchor); + if (attributeValue != null) { + return attributeValue; } break; + } case "list": - const result = getPreviousTarget(target.elements, useTarget); - if (result != null) { - return result; + const attributeValue = getPreviousTargetAttribute( + target.elements, + getAttribute + ); + if (attributeValue != null) { + return attributeValue; } break; } } - return null; + return undefined; } diff --git a/src/test/suite/runTestSubset.ts b/src/test/suite/runTestSubset.ts index c3c37bf1d4..d4f36e6350 100644 --- a/src/test/suite/runTestSubset.ts +++ b/src/test/suite/runTestSubset.ts @@ -4,7 +4,7 @@ * configuration. * See https://mochajs.org/#-grep-regexp-g-regexp for supported syntax */ -export const TEST_SUBSET_GREP_STRING = "actions/insertEmptyLines"; +export const TEST_SUBSET_GREP_STRING = "bringLineAirAndBatAndCapToBeforeDrum"; /** * Determine whether we should run just the subset of the tests specified by From 2e811b8928e5461b0b0d666b97d8732a45c4b627 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 14:46:43 +0100 Subject: [PATCH 02/12] Attempt to fix ci --- ...OfSecondCarWhaleAndEndOfWhaleTakeWhale.yml | 22 +++++++----- ...SecondCarWhaleAndStartOfWhaleTakeWhale.yml | 22 +++++++----- ...OfSecondCarWhaleAndEndOfWhaleTakeWhale.yml | 22 +++++++----- ...SecondCarWhaleAndStartOfWhaleTakeWhale.yml | 22 +++++++----- ...astSecondCarWhaleToEndOfWhaleTakeWhale.yml | 36 ++++++++++++------- 5 files changed, 80 insertions(+), 44 deletions(-) diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml index 2f1eb9460b..11f9c1a3f1 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml @@ -1,8 +1,7 @@ languageId: plaintext command: - version: 1 spokenForm: bring point and harp to end of second car whale and end of whale take whale - action: replaceWithTarget + version: 2 targets: - type: list elements: @@ -13,15 +12,22 @@ command: - type: list elements: - type: primitive - position: after - insideOutsideType: inside - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 1, active: 1, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: end} + - type: ordinalRange + scopeType: {type: character} + anchor: 1 + active: 1 + excludeAnchor: false + excludeActive: false - type: primitive - position: after - insideOutsideType: inside mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: end} + - {type: toRawSelection} + usePrePhraseSnapshot: false + action: {name: replaceWithTarget} marksToCheck: [default.w] initialState: documentContents: hello. world diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml index c800f11648..214e2a73c7 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml @@ -1,10 +1,9 @@ languageId: plaintext command: - version: 1 spokenForm: >- bring point and harp to start of second car whale and start of whale take whale - action: replaceWithTarget + version: 2 targets: - type: list elements: @@ -15,15 +14,22 @@ command: - type: list elements: - type: primitive - position: before - insideOutsideType: inside - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 1, active: 1, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: start} + - type: ordinalRange + scopeType: {type: character} + anchor: 1 + active: 1 + excludeAnchor: false + excludeActive: false - type: primitive - position: before - insideOutsideType: inside mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: start} + - {type: toRawSelection} + usePrePhraseSnapshot: false + action: {name: replaceWithTarget} marksToCheck: [default.w] initialState: documentContents: hello. world diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml index 6202f6bb19..5ce3a3ec92 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml @@ -1,8 +1,7 @@ languageId: plaintext command: - version: 1 spokenForm: bring point and point to end of second car whale and end of whale take whale - action: replaceWithTarget + version: 2 targets: - type: list elements: @@ -13,15 +12,22 @@ command: - type: list elements: - type: primitive - position: after - insideOutsideType: inside - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 1, active: 1, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: end} + - type: ordinalRange + scopeType: {type: character} + anchor: 1 + active: 1 + excludeAnchor: false + excludeActive: false - type: primitive - position: after - insideOutsideType: inside mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: end} + - {type: toRawSelection} + usePrePhraseSnapshot: false + action: {name: replaceWithTarget} marksToCheck: [default.w] initialState: documentContents: hello. world diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml index 9e6aa159a5..28728023f6 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml @@ -1,10 +1,9 @@ languageId: plaintext command: - version: 1 spokenForm: >- bring point and point to start of second car whale and start of whale take whale - action: replaceWithTarget + version: 2 targets: - type: list elements: @@ -15,15 +14,22 @@ command: - type: list elements: - type: primitive - position: before - insideOutsideType: inside - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 1, active: 1, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: start} + - type: ordinalRange + scopeType: {type: character} + anchor: 1 + active: 1 + excludeAnchor: false + excludeActive: false - type: primitive - position: before - insideOutsideType: inside mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: start} + - {type: toRawSelection} + usePrePhraseSnapshot: false + action: {name: replaceWithTarget} marksToCheck: [default.w] initialState: documentContents: hello. world diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml index 213464506d..aaeb7145f4 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml @@ -1,26 +1,38 @@ languageId: plaintext command: - version: 1 spokenForm: move fourth car harp past second car whale to end of whale take whale - action: moveToTarget + version: 2 targets: - type: range - start: + anchor: type: primitive - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 3, active: 3, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: h} - end: + modifiers: + - type: ordinalRange + scopeType: {type: character} + anchor: 3 + active: 3 + excludeAnchor: false + excludeActive: false + active: type: primitive - selectionType: token - modifier: {type: subpiece, pieceType: character, anchor: 1, active: 1, excludeAnchor: false, excludeActive: false} mark: {type: decoratedSymbol, symbolColor: default, character: w} - excludeStart: false - excludeEnd: false + modifiers: + - type: ordinalRange + scopeType: {type: character} + anchor: 1 + active: 1 + excludeAnchor: false + excludeActive: false + excludeAnchor: false + excludeActive: false - type: primitive - position: after - insideOutsideType: inside mark: {type: decoratedSymbol, symbolColor: default, character: w} + modifiers: + - {type: position, position: end} + - {type: toRawSelection} + usePrePhraseSnapshot: false + action: {name: moveToTarget} marksToCheck: [default.w] initialState: documentContents: hello world whatever From 40f3cb2e74c2a7df71b4891c71c782088ecbecdb Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 14:49:06 +0100 Subject: [PATCH 03/12] Update spoken forms --- ...tAndHarpToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml} | 2 +- ...HarpToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml} | 2 +- ...AndPointToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml} | 2 +- ...ointToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml} | 2 +- ...ourthCarHarpPastSecondCarWhaleToEndOfJustWhaleTakeWhale.yml} | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename src/test/suite/fixtures/recorded/hatTokenMap/{bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml => bringPointAndHarpToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml} (99%) rename src/test/suite/fixtures/recorded/hatTokenMap/{bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml => bringPointAndHarpToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml} (99%) rename src/test/suite/fixtures/recorded/hatTokenMap/{bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml => bringPointAndPointToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml} (98%) rename src/test/suite/fixtures/recorded/hatTokenMap/{bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml => bringPointAndPointToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml} (99%) rename src/test/suite/fixtures/recorded/hatTokenMap/{moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml => moveFourthCarHarpPastSecondCarWhaleToEndOfJustWhaleTakeWhale.yml} (99%) diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml similarity index 99% rename from src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml rename to src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml index 11f9c1a3f1..a71f9edab7 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml @@ -1,6 +1,6 @@ languageId: plaintext command: - spokenForm: bring point and harp to end of second car whale and end of whale take whale + spokenForm: bring point and harp to end of second car whale and end of just whale take whale version: 2 targets: - type: list diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml similarity index 99% rename from src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml rename to src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml index 214e2a73c7..98685ec465 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndHarpToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml @@ -1,7 +1,7 @@ languageId: plaintext command: spokenForm: >- - bring point and harp to start of second car whale and start of whale take + bring point and harp to start of second car whale and start of just whale take whale version: 2 targets: diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml similarity index 98% rename from src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml rename to src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml index 5ce3a3ec92..5533531e76 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToEndOfSecondCarWhaleAndEndOfJustWhaleTakeWhale.yml @@ -1,6 +1,6 @@ languageId: plaintext command: - spokenForm: bring point and point to end of second car whale and end of whale take whale + spokenForm: bring point and point to end of second car whale and end of just whale take whale version: 2 targets: - type: list diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml similarity index 99% rename from src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml rename to src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml index 28728023f6..bc88db91a8 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/bringPointAndPointToStartOfSecondCarWhaleAndStartOfJustWhaleTakeWhale.yml @@ -1,7 +1,7 @@ languageId: plaintext command: spokenForm: >- - bring point and point to start of second car whale and start of whale take + bring point and point to start of second car whale and start of just whale take whale version: 2 targets: diff --git a/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml b/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfJustWhaleTakeWhale.yml similarity index 99% rename from src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml rename to src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfJustWhaleTakeWhale.yml index aaeb7145f4..c31575a50a 100644 --- a/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfWhaleTakeWhale.yml +++ b/src/test/suite/fixtures/recorded/hatTokenMap/moveFourthCarHarpPastSecondCarWhaleToEndOfJustWhaleTakeWhale.yml @@ -1,6 +1,6 @@ languageId: plaintext command: - spokenForm: move fourth car harp past second car whale to end of whale take whale + spokenForm: move fourth car harp past second car whale to end of just whale take whale version: 2 targets: - type: range From 15f318e41d3d546ecb753994716ab4c7fee838f8 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 14:55:35 +0100 Subject: [PATCH 04/12] Cleanup --- src/core/inferFullTargets.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 0b129cfa45..4e33ef67f2 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -94,12 +94,15 @@ function inferPrimitiveTarget( }; } - const ownPositionalModifier = getPosition(target); + const ownPositionalModifier = getPositionalModifier(target); const ownNonPositionalModifiers = getNonPositionalModifiers(target); // Position without a mark can be something like "take air past end of line" + // We will move this case when we implement #736 const mark = target.mark ?? - (!!ownPositionalModifier ? getPreviousMark(previousTargets) : null) ?? { + (ownPositionalModifier == null + ? null + : getPreviousMark(previousTargets)) ?? { type: "cursor", }; @@ -109,7 +112,7 @@ function inferPrimitiveTarget( []; const positionalModifier = - ownPositionalModifier ?? getPreviousPosition(previousTargets); + ownPositionalModifier ?? getPreviousPositionalModifier(previousTargets); const modifiers = [ ...(positionalModifier == null ? [] : [positionalModifier]), @@ -123,7 +126,7 @@ function inferPrimitiveTarget( }; } -function getPosition(target: PartialPrimitiveTargetDescriptor) { +function getPositionalModifier(target: PartialPrimitiveTargetDescriptor) { if (target.modifiers == null) { return undefined; } @@ -165,10 +168,12 @@ function getPreviousNonPositionalModifiers( ); } -function getPreviousPosition(previousTargets: PartialTargetDescriptor[]) { +function getPreviousPositionalModifier( + previousTargets: PartialTargetDescriptor[] +) { return getPreviousTargetAttribute( previousTargets, - (target: PartialPrimitiveTargetDescriptor) => getPosition(target) + (target: PartialPrimitiveTargetDescriptor) => getPositionalModifier(target) ); } From 97f66a2ebeaa012516c7accaa10585a0bf6ac522 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 14:56:04 +0100 Subject: [PATCH 05/12] More stuff --- src/core/inferFullTargets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 4e33ef67f2..002868d17a 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -98,7 +98,7 @@ function inferPrimitiveTarget( const ownNonPositionalModifiers = getNonPositionalModifiers(target); // Position without a mark can be something like "take air past end of line" - // We will move this case when we implement #736 + // We will remove this case when we implement #736 const mark = target.mark ?? (ownPositionalModifier == null ? null From 08e8ba1de1215c8c5374e4c4c5d94b2ce5b5f6f1 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:03:48 +0100 Subject: [PATCH 06/12] Add return types --- src/core/inferFullTargets.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 002868d17a..311edf24cf 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -1,8 +1,11 @@ import { + Mark, + Modifier, PartialListTargetDescriptor, PartialPrimitiveTargetDescriptor, PartialRangeTargetDescriptor, PartialTargetDescriptor, + PositionModifier, PrimitiveTargetDescriptor, RangeTargetDescriptor, TargetDescriptor, @@ -126,7 +129,9 @@ function inferPrimitiveTarget( }; } -function getPositionalModifier(target: PartialPrimitiveTargetDescriptor) { +function getPositionalModifier( + target: PartialPrimitiveTargetDescriptor +): PositionModifier | undefined { if (target.modifiers == null) { return undefined; } @@ -139,10 +144,14 @@ function getPositionalModifier(target: PartialPrimitiveTargetDescriptor) { throw Error("Position modifiers must be at the start of a modifier chain"); } - return positionModifierIndex === -1 ? undefined : target.modifiers[0]; + return positionModifierIndex === -1 + ? undefined + : (target.modifiers[0] as PositionModifier); } -function getNonPositionalModifiers(target: PartialPrimitiveTargetDescriptor) { +function getNonPositionalModifiers( + target: PartialPrimitiveTargetDescriptor +): Modifier[] | undefined { const nonPositionalModifiers = target.modifiers?.filter( (modifier) => modifier.type !== "position" ); @@ -151,7 +160,9 @@ function getNonPositionalModifiers(target: PartialPrimitiveTargetDescriptor) { : nonPositionalModifiers; } -function getPreviousMark(previousTargets: PartialTargetDescriptor[]) { +function getPreviousMark( + previousTargets: PartialTargetDescriptor[] +): Mark | undefined { return getPreviousTargetAttribute( previousTargets, (target: PartialPrimitiveTargetDescriptor) => target.mark @@ -160,7 +171,7 @@ function getPreviousMark(previousTargets: PartialTargetDescriptor[]) { function getPreviousNonPositionalModifiers( previousTargets: PartialTargetDescriptor[] -) { +): Modifier[] | undefined { return getPreviousTargetAttribute( previousTargets, (target: PartialPrimitiveTargetDescriptor) => @@ -170,7 +181,7 @@ function getPreviousNonPositionalModifiers( function getPreviousPositionalModifier( previousTargets: PartialTargetDescriptor[] -) { +): PositionModifier | undefined { return getPreviousTargetAttribute( previousTargets, (target: PartialPrimitiveTargetDescriptor) => getPositionalModifier(target) From 92bd3bc7a54d3e1aacf2a841d270ba1d306a0557 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:04:43 +0100 Subject: [PATCH 07/12] Cleanup --- src/core/inferFullTargets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 311edf24cf..dd5ea2f883 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -146,7 +146,7 @@ function getPositionalModifier( return positionModifierIndex === -1 ? undefined - : (target.modifiers[0] as PositionModifier); + : (target.modifiers[positionModifierIndex] as PositionModifier); } function getNonPositionalModifiers( From 506d099308b13f9fba5461b5d4084dd8da7620b8 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:07:06 +0100 Subject: [PATCH 08/12] Doc string --- src/core/inferFullTargets.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index dd5ea2f883..1d299d6263 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -149,6 +149,13 @@ function getPositionalModifier( : (target.modifiers[positionModifierIndex] as PositionModifier); } +/** + * Return a list of non-positional modifiers on the given target. We return + * undefined if there are none. Note that we will never return an empty list; we + * will always return `undefined` if there are no non-positional modifiers. + * @param target The target from which to get the non-positional modifiers + * @returns A list of non-positional modifiers or `undefined` if there are none + */ function getNonPositionalModifiers( target: PartialPrimitiveTargetDescriptor ): Modifier[] | undefined { From 7f441209ec1d4285c0bcbbadeacdefac44376249 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:08:52 +0100 Subject: [PATCH 09/12] More cleanup --- src/core/inferFullTargets.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index 1d299d6263..aeb81fdd9f 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -179,20 +179,13 @@ function getPreviousMark( function getPreviousNonPositionalModifiers( previousTargets: PartialTargetDescriptor[] ): Modifier[] | undefined { - return getPreviousTargetAttribute( - previousTargets, - (target: PartialPrimitiveTargetDescriptor) => - getNonPositionalModifiers(target) - ); + return getPreviousTargetAttribute(previousTargets, getNonPositionalModifiers); } function getPreviousPositionalModifier( previousTargets: PartialTargetDescriptor[] ): PositionModifier | undefined { - return getPreviousTargetAttribute( - previousTargets, - (target: PartialPrimitiveTargetDescriptor) => getPositionalModifier(target) - ); + return getPreviousTargetAttribute(previousTargets, getPositionalModifier); } function getPreviousTargetAttribute( From d1566012ca1bb340a5bcf0811024decf79f6e533 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:14:08 +0100 Subject: [PATCH 10/12] Doc string --- src/core/inferFullTargets.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/inferFullTargets.ts b/src/core/inferFullTargets.ts index aeb81fdd9f..8def1fb35c 100644 --- a/src/core/inferFullTargets.ts +++ b/src/core/inferFullTargets.ts @@ -188,6 +188,16 @@ function getPreviousPositionalModifier( return getPreviousTargetAttribute(previousTargets, getPositionalModifier); } +/** + * Walks backward through the given targets and their descendants trying to find + * the first target for which the given attribute extractor returns a + * non-nullish value. Returns `undefined` if none could be found + * @param previousTargets The targets that precede the target we are trying to + * infer. We look in these targets and their descendants for the given attribute + * @param getAttribute The function used to extract the attribute from a + * primitive target + * @returns The extracted attribute or undefined if one could not be found + */ function getPreviousTargetAttribute( previousTargets: PartialTargetDescriptor[], getAttribute: (target: PartialPrimitiveTargetDescriptor) => T | undefined From 3f898a3e22ae2705ec6274ef84b38344a967606a Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:15:47 +0100 Subject: [PATCH 11/12] Revert test subset --- src/test/suite/runTestSubset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/suite/runTestSubset.ts b/src/test/suite/runTestSubset.ts index d4f36e6350..c3c37bf1d4 100644 --- a/src/test/suite/runTestSubset.ts +++ b/src/test/suite/runTestSubset.ts @@ -4,7 +4,7 @@ * configuration. * See https://mochajs.org/#-grep-regexp-g-regexp for supported syntax */ -export const TEST_SUBSET_GREP_STRING = "bringLineAirAndBatAndCapToBeforeDrum"; +export const TEST_SUBSET_GREP_STRING = "actions/insertEmptyLines"; /** * Determine whether we should run just the subset of the tests specified by From 31cbb37932393cbeb79f1d661c6d3ba171b57852 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Tue, 21 Jun 2022 15:17:28 +0100 Subject: [PATCH 12/12] Add test case for the thing we were trying to fix --- .../bringHarpAfterLineTrapAndBlockSpun.yml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/test/suite/fixtures/recorded/inference/bringHarpAfterLineTrapAndBlockSpun.yml diff --git a/src/test/suite/fixtures/recorded/inference/bringHarpAfterLineTrapAndBlockSpun.yml b/src/test/suite/fixtures/recorded/inference/bringHarpAfterLineTrapAndBlockSpun.yml new file mode 100644 index 0000000000..2cae3a03aa --- /dev/null +++ b/src/test/suite/fixtures/recorded/inference/bringHarpAfterLineTrapAndBlockSpun.yml @@ -0,0 +1,62 @@ +languageId: plaintext +command: + spokenForm: bring harp after line trap and block spun + version: 2 + targets: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: h} + - type: list + elements: + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: t} + modifiers: + - {type: position, position: after} + - type: containingScope + scopeType: {type: line} + - type: primitive + mark: {type: decoratedSymbol, symbolColor: default, character: s} + modifiers: + - type: containingScope + scopeType: {type: paragraph} + usePrePhraseSnapshot: true + action: {name: replaceWithTarget} +initialState: + documentContents: |- + hello + there + + testing + selections: + - anchor: {line: 3, character: 7} + active: {line: 3, character: 7} + marks: + default.h: + start: {line: 0, character: 0} + end: {line: 0, character: 5} + default.t: + start: {line: 1, character: 0} + end: {line: 1, character: 5} + default.s: + start: {line: 3, character: 0} + end: {line: 3, character: 7} +finalState: + documentContents: |- + hello + there + hello + + testing + + hello + selections: + - anchor: {line: 4, character: 7} + active: {line: 4, character: 7} + thatMark: + - anchor: {line: 2, character: 0} + active: {line: 2, character: 5} + - anchor: {line: 6, character: 0} + active: {line: 6, character: 5} + sourceMark: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 5} +fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, modifiers: []}, {type: list, elements: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: t}, modifiers: [{type: position, position: after}, {type: containingScope, scopeType: {type: line}}]}, {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: s}, modifiers: [{type: position, position: after}, {type: containingScope, scopeType: {type: paragraph}}]}]}]