diff --git a/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts index a72424fc7d..26fc8b4c4b 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts @@ -55,10 +55,11 @@ export class InstanceStage implements ModifierStage { private handleOrdinalScope( target: Target, - { start, length }: OrdinalScopeModifier, + { start, length, scopeType }: OrdinalScopeModifier, ): Target[] { return this.getEveryRanges(target).flatMap(([editor, searchRange]) => takeFromOffset( + scopeType, this.getTargetIterable( target, editor, @@ -73,7 +74,7 @@ export class InstanceStage implements ModifierStage { private handleRelativeScope( target: Target, - { direction, offset, length }: RelativeScopeModifier, + { direction, offset, length, scopeType }: RelativeScopeModifier, ): Target[] { const referenceTargets = this.storedTargets.get("instanceReference") ?? [ target, @@ -97,6 +98,7 @@ export class InstanceStage implements ModifierStage { ); return takeFromOffset( + scopeType, this.getTargetIterable(target, editor, iterationRange, direction), offset === 0 ? 0 : offset - 1, length, @@ -206,6 +208,7 @@ function getFilterScopeType(target: Target): ScopeType | null { * starting at `offset` */ function takeFromOffset( + scopeType: ScopeType, iterable: Iterable, offset: number, count: number, @@ -217,7 +220,7 @@ function takeFromOffset( const items = Array.from(itake(count, iterable)); if (items.length < count) { - throw new OutOfRangeError(); + throw new OutOfRangeError(scopeType, offset + count - 1); } return items; diff --git a/packages/cursorless-engine/src/processTargets/modifiers/OrdinalScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/OrdinalScopeStage.ts index c1396ef5b4..1e9e30d8a7 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/OrdinalScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/OrdinalScopeStage.ts @@ -2,11 +2,11 @@ import type { OrdinalScopeModifier } from "@cursorless/common"; import type { Target } from "../../typings/target.types"; import type { ModifierStageFactory } from "../ModifierStageFactory"; import type { ModifierStage } from "../PipelineStages.types"; +import { sliceStrict } from "./listUtils"; import { createRangeTargetFromIndices, getEveryScopeTargets, } from "./targetSequenceUtils"; -import { sliceStrict } from "./listUtils"; export class OrdinalScopeStage implements ModifierStage { constructor( @@ -26,11 +26,17 @@ export class OrdinalScopeStage implements ModifierStage { const endIndex = startIndex + this.modifier.length - 1; if (this.modifier.isEvery) { - return sliceStrict(targets, startIndex, endIndex); + return sliceStrict( + this.modifier.scopeType, + targets, + startIndex, + endIndex, + ); } return [ createRangeTargetFromIndices( + this.modifier.scopeType, target.isReversed, targets, startIndex, diff --git a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts index 3d91160e12..709304a361 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts @@ -47,7 +47,10 @@ export class RelativeScopeStage implements ModifierStage { ); if (scopes.length < this.modifier.length) { - throw new OutOfRangeError(); + throw new OutOfRangeError( + this.modifier.scopeType, + this.modifier.offset + this.modifier.length - 1, + ); } const { isReversed } = target; diff --git a/packages/cursorless-engine/src/processTargets/modifiers/listUtils.ts b/packages/cursorless-engine/src/processTargets/modifiers/listUtils.ts index 1b28e296d8..8a243f652f 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/listUtils.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/listUtils.ts @@ -1,27 +1,35 @@ +import type { ScopeType } from "@cursorless/common"; + export class OutOfRangeError extends Error { - constructor() { - super("Scope index out of range"); + constructor(scopeType: ScopeType, index?: number) { + const numberStr = index != null ? ` #${index + 1}` : ""; + super(`Scope '${scopeType.type}'${numberStr} is out of range`); this.name = "OutOfRangeError"; } } /** Slice list of by given indices */ export function sliceStrict( + scopeType: ScopeType, targets: T[], startIndex: number, endIndex: number, ): T[] { - assertIndices(targets, startIndex, endIndex); + assertIndices(scopeType, targets, startIndex, endIndex); return targets.slice(startIndex, endIndex + 1); } export function assertIndices( + scopeType: ScopeType, targets: T[], startIndex: number, endIndex: number, ): void { - if (startIndex < 0 || endIndex >= targets.length) { - throw new OutOfRangeError(); + if (startIndex < 0 || startIndex >= targets.length) { + throw new OutOfRangeError(scopeType, startIndex); + } + if (endIndex < 0 || endIndex >= targets.length) { + throw new OutOfRangeError(scopeType, endIndex); } } diff --git a/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts b/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts index 4cc146a65f..f757d88dbd 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts @@ -72,6 +72,7 @@ function calculateIndicesAndCreateTarget( return [ createRangeTargetFromIndices( + modifier.scopeType, target.isReversed, targets, startIndex, @@ -108,7 +109,7 @@ function computeProximalIndex( ); if (adjacentTargetIndex === -1) { - throw new OutOfRangeError(); + throw new OutOfRangeError(modifier.scopeType); } // For convenience, if they ask to include intersecting indices, we just diff --git a/packages/cursorless-engine/src/processTargets/modifiers/targetSequenceUtils.ts b/packages/cursorless-engine/src/processTargets/modifiers/targetSequenceUtils.ts index f91dcf602d..b2c528ad4c 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/targetSequenceUtils.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/targetSequenceUtils.ts @@ -14,12 +14,13 @@ import { assertIndices } from "./listUtils"; * end of the range */ export function createRangeTargetFromIndices( + scopeType: ScopeType, isReversed: boolean, targets: Target[], startIndex: number, endIndex: number, ): Target { - assertIndices(targets, startIndex, endIndex); + assertIndices(scopeType, targets, startIndex, endIndex); if (startIndex === endIndex) { return targets[startIndex];