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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions packages/cursorless-engine/src/actions/BringMoveSwap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { Range, Selection, TextEditor } from "@cursorless/common";
import type {
GeneralizedRange,
Range,
Selection,
TextEditor,
} from "@cursorless/common";
import { FlashStyle, RangeExpansionBehavior } from "@cursorless/common";
import { flatten } from "lodash-es";
import type { RangeUpdater } from "../core/updateSelections/RangeUpdater";
Expand All @@ -8,8 +13,8 @@ import type { EditWithRangeUpdater } from "../typings/Types";
import type { Destination, Target } from "../typings/target.types";
import {
flashTargets,
getContentRange,
runForEachEditor,
toGeneralizedRange,
} from "../util/targetUtils";
import { unifyRemovalTargets } from "../util/unifyRanges";
import type { ActionReturnValue } from "./actions.types";
Expand All @@ -34,7 +39,7 @@ abstract class BringMoveSwap {
protected abstract decoration: {
sourceStyle: FlashStyle;
destinationStyle: FlashStyle;
getSourceRangeCallback: (target: Target) => Range;
getSourceRangeCallback?: (target: Target) => GeneralizedRange;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made this optional. If you don't pass a callback into flashTargets() the content range is used by default.

};

constructor(
Expand Down Expand Up @@ -209,8 +214,12 @@ abstract class BringMoveSwap {
}

protected async decorateThatMark(thatMark: MarkEntry[]) {
const getRange = (target: Target) =>
thatMark.find((t) => t.target === target)!.selection;
const getRange = (target: Target) => {
return toGeneralizedRange(
target,
thatMark.find((t) => t.target === target)!.selection,
);
};
return Promise.all([
flashTargets(
ide(),
Expand Down Expand Up @@ -250,7 +259,6 @@ export class Bring extends BringMoveSwap {
decoration = {
sourceStyle: FlashStyle.referenced,
destinationStyle: FlashStyle.pendingModification0,
getSourceRangeCallback: getContentRange,
Copy link
Member Author

@AndreasArvidsson AndreasArvidsson Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use default content range implementation

};

constructor(rangeUpdater: RangeUpdater) {
Expand Down Expand Up @@ -320,7 +328,6 @@ export class Swap extends BringMoveSwap {
decoration = {
sourceStyle: FlashStyle.pendingModification1,
destinationStyle: FlashStyle.pendingModification0,
getSourceRangeCallback: getContentRange,
};

constructor(rangeUpdater: RangeUpdater) {
Expand Down
7 changes: 1 addition & 6 deletions packages/cursorless-engine/src/actions/CopyToClipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ export class CopyToClipboard implements SimpleAction {
}

if (options.showDecorations) {
await flashTargets(
ide(),
targets,
FlashStyle.referenced,
(target) => target.contentRange,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use default content range implementation

);
await flashTargets(ide(), targets, FlashStyle.referenced);
}

// FIXME: We should really keep track of the number of targets from the
Expand Down
86 changes: 41 additions & 45 deletions packages/cursorless-engine/src/actions/CutToClipboard.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,17 @@
import type { FlashDescriptor } from "@cursorless/common";
import {
FlashStyle,
Range,
toCharacterRange,
toLineRange,
} from "@cursorless/common";
import type { CharacterRange, FlashDescriptor } from "@cursorless/common";
import { FlashStyle, Range, toCharacterRange } from "@cursorless/common";
import { ide } from "../singletons/ide.singleton";
import type { Target } from "../typings/target.types";
import type { Actions } from "./Actions";
import type { SimpleAction, ActionReturnValue } from "./actions.types";
import type { ActionReturnValue, SimpleAction } from "./actions.types";

export class CutToClipboard implements SimpleAction {
constructor(private actions: Actions) {
this.run = this.run.bind(this);
}

async run(targets: Target[]): Promise<ActionReturnValue> {
await ide().flashRanges(
targets.flatMap((target) => {
const { editor, contentRange } = target;
const removalHighlightRange = target.getRemovalHighlightRange();

if (target.isLine) {
return [
{
editor,
range: toCharacterRange(contentRange),
style: FlashStyle.referenced,
},
{
editor,
range: toLineRange(removalHighlightRange),
style: FlashStyle.pendingDelete,
},
];
}

return [
{
editor,
range: toCharacterRange(contentRange),
style: FlashStyle.referenced,
},
...getOutsideOverflow(contentRange, removalHighlightRange).map(
(overflow): FlashDescriptor => ({
editor,
range: toCharacterRange(overflow),
style: FlashStyle.pendingDelete,
}),
),
];
}),
);
await ide().flashRanges(targets.flatMap(getFlashDescriptors));

const options = { showDecorations: false };

Expand All @@ -63,8 +23,44 @@ export class CutToClipboard implements SimpleAction {
}
}

function getFlashDescriptors(target: Target): FlashDescriptor[] {
const { editor, contentRange } = target;
const removalHighlightRange = target.getRemovalHighlightRange();

const flashDescriptors: FlashDescriptor[] = [
{
editor,
range: toCharacterRange(contentRange),
style: FlashStyle.referenced,
},
];

if (removalHighlightRange.type === "line") {
flashDescriptors.push({
editor,
range: removalHighlightRange,
style: FlashStyle.pendingDelete,
});
} else {
flashDescriptors.push(
...getOutsideOverflow(contentRange, removalHighlightRange).map(
(overflow): FlashDescriptor => ({
editor,
range: toCharacterRange(overflow),
style: FlashStyle.pendingDelete,
}),
),
);
}

return flashDescriptors;
}

/** Get the possible leading and trailing overflow ranges of the outside range compared to the inside range */
function getOutsideOverflow(insideRange: Range, outsideRange: Range): Range[] {
function getOutsideOverflow(
insideRange: Range,
outsideRange: CharacterRange,
): Range[] {
const { start: insideStart, end: insideEnd } = insideRange;
const { start: outsideStart, end: outsideEnd } = outsideRange;
const result = [];
Expand Down
4 changes: 3 additions & 1 deletion packages/cursorless-engine/src/actions/Highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export default class Highlight {
ide().setHighlightRanges(
highlightId,
editor,
targets.map(toGeneralizedRange),
targets.map((target) =>
toGeneralizedRange(target, target.contentRange),
),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export default class ToggleBreakpoint implements SimpleAction {
await flashTargets(ide(), thatTargets, FlashStyle.referenced);

await runOnTargetsForEachEditor(targets, async (editor, targets) => {
const generalizedRanges = targets.map(toGeneralizedRange);
const generalizedRanges = targets.map((target) =>
toGeneralizedRange(target, target.contentRange),
);

await ide()
.getEditableTextEditor(editor)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
EnforceUndefined,
GeneralizedRange,
InsertionMode,
Range,
Selection,
Expand All @@ -14,6 +15,7 @@ import type {
JoinAsType,
Target,
} from "../../typings/target.types";
import { toGeneralizedRange } from "../../util/targetUtils";
import { DestinationImpl } from "./DestinationImpl";
import { createContinuousRange } from "./util/createContinuousRange";

Expand Down Expand Up @@ -97,8 +99,8 @@ export abstract class BaseTarget<
};
}

getRemovalHighlightRange(): Range {
return this.getRemovalRange();
getRemovalHighlightRange(): GeneralizedRange {
return toGeneralizedRange(this, this.getRemovalRange());
}

withThatTarget(thatTarget: Target): Target {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { Range } from "@cursorless/common";
import { toLineRange, type Range } from "@cursorless/common";
import type { InteriorTarget, ParagraphTarget } from ".";
import { expandToFullLine } from "../../util/rangeUtils";
import type { MinimumTargetParameters } from "./BaseTarget";
import { BaseTarget } from "./BaseTarget";
import { LineTarget } from "./LineTarget";
import { expandToFullLine } from "../../util/rangeUtils";
import type { InteriorTarget, ParagraphTarget } from ".";

interface BoundedParagraphTargetParameters extends MinimumTargetParameters {
readonly paragraphTarget: ParagraphTarget;
Expand Down Expand Up @@ -86,16 +86,20 @@ export class BoundedParagraphTarget extends BaseTarget<BoundedParagraphTargetPar
}

getRemovalHighlightRange() {
if (this.startLineGap < 1 || this.endLineGap < 1) {
return this.getRemovalRange();
}
const range = (() => {
if (this.startLineGap < 1 || this.endLineGap < 1) {
return this.getRemovalRange();
}

const delimiterTarget =
this.getTrailingDelimiterTarget() ?? this.getLeadingDelimiterTarget();
const delimiterTarget =
this.getTrailingDelimiterTarget() ?? this.getLeadingDelimiterTarget();

return delimiterTarget != null
? this.fullLineContentRange.union(delimiterTarget.contentRange)
: this.fullLineContentRange;
})();

return delimiterTarget != null
? this.fullLineContentRange.union(delimiterTarget.contentRange)
: this.fullLineContentRange;
return toLineRange(range);
}

maybeCreateRichRangeTarget(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { TextEditor } from "@cursorless/common";
import { Position, Range } from "@cursorless/common";
import { Position, Range, toLineRange } from "@cursorless/common";
import { expandToFullLine } from "../../util/rangeUtils";
import { tryConstructTarget } from "../../util/tryConstructTarget";
import type { CommonTargetParameters } from "./BaseTarget";
import { BaseTarget } from "./BaseTarget";
import { expandToFullLine } from "../../util/rangeUtils";
import { tryConstructPlainTarget } from "./PlainTarget";
import { createContinuousLineRange } from "./util/createContinuousRange";
import { tryConstructTarget } from "../../util/tryConstructTarget";

export class LineTarget extends BaseTarget<CommonTargetParameters> {
type = "LineTarget";
Expand Down Expand Up @@ -42,7 +42,9 @@ export class LineTarget extends BaseTarget<CommonTargetParameters> {
: contentRemovalRange.union(delimiterTarget.contentRange);
}

getRemovalHighlightRange = () => this.fullLineContentRange;
getRemovalHighlightRange = () => {
return toLineRange(this.fullLineContentRange);
};

maybeCreateRichRangeTarget(
isReversed: boolean,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import type { TextDocument, TextEditor, TextLine } from "@cursorless/common";
import { Position, Range } from "@cursorless/common";
import type {
GeneralizedRange,
TextDocument,
TextEditor,
TextLine,
} from "@cursorless/common";
import { Position, Range, toLineRange } from "@cursorless/common";
import { expandToFullLine } from "../../util/rangeUtils";
import type { CommonTargetParameters } from "./BaseTarget";
import { BaseTarget } from "./BaseTarget";
import { LineTarget } from "./LineTarget";
import { expandToFullLine } from "../../util/rangeUtils";
import { constructLineTarget } from "./LineTarget";
import { constructLineTarget, LineTarget } from "./LineTarget";
import { createContinuousLineRange } from "./util/createContinuousRange";

export class ParagraphTarget extends BaseTarget<CommonTargetParameters> {
Expand Down Expand Up @@ -59,13 +63,16 @@ export class ParagraphTarget extends BaseTarget<CommonTargetParameters> {
return expandToFullLine(this.editor, this.contentRange);
}

getRemovalHighlightRange() {
getRemovalHighlightRange(): GeneralizedRange {
const delimiterTarget =
this.getTrailingDelimiterTarget() ?? this.getLeadingDelimiterTarget();

return delimiterTarget != null
? this.fullLineContentRange.union(delimiterTarget.contentRange)
: this.fullLineContentRange;
const range =
delimiterTarget != null
? this.fullLineContentRange.union(delimiterTarget.contentRange)
: this.fullLineContentRange;

return toLineRange(range);
}

maybeCreateRichRangeTarget(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { TargetRanges } from "@cursorless/common";
import { toCharacterRange, toLineRange } from "@cursorless/common";
import type { Target } from "../typings/target.types";

export function getTargetRanges(target: Target): TargetRanges {
return {
contentRange: target.contentRange,
removalRange: target.getRemovalRange(),
removalHighlightRange: target.isLine
? toLineRange(target.getRemovalHighlightRange())
: toCharacterRange(target.getRemovalHighlightRange()),
removalHighlightRange: target.getRemovalHighlightRange(),
leadingDelimiter: getOptionalTarget(target.getLeadingDelimiterTarget()),
trailingDelimiter: getOptionalTarget(target.getTrailingDelimiterTarget()),
interior: target.getInterior()?.map(getTargetRanges),
Expand Down
3 changes: 2 additions & 1 deletion packages/cursorless-engine/src/typings/target.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import type { ModifyIfUntypedStage } from "../processTargets/modifiers/ConditionalModifierStages";
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-imports
import type {
GeneralizedRange,
InsertionMode,
Range,
Selection,
Expand Down Expand Up @@ -156,7 +157,7 @@ export interface Target {
* we want to highlight the line that they were on when they said `"chuck
* line"`, as that is logically the line they've deleted.
*/
getRemovalHighlightRange(): Range;
getRemovalHighlightRange(): GeneralizedRange;
withThatTarget(thatTarget: Target): Target;
withContentRange(contentRange: Range): Target;

Expand Down
Loading
Loading