Skip to content

Commit 8462eba

Browse files
AndreasArvidssonpokey
authored andcommitted
Use built in action for copy and paste (#141)
* use built in action for copy and paste * eshure single editotar * Merge decorations for cut
1 parent c0008e7 commit 8462eba

File tree

8 files changed

+149
-161
lines changed

8 files changed

+149
-161
lines changed

src/CommandAction.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ import { runOnTargetsForEachEditor } from "./targetUtils";
1212
import { focusEditor } from "./setSelectionsAndFocusEditor";
1313
import { flatten } from "lodash";
1414
import { callFunctionAndUpdateSelections } from "./updateSelections";
15+
import { ensureSingleEditor } from "./targetUtils";
1516

1617
export default class CommandAction implements Action {
1718
targetPreferences: ActionPreferences[] = [{ insideOutsideType: "inside" }];
19+
private ensureSingleEditor: boolean;
1820

19-
constructor(private graph: Graph, private command: string) {
21+
constructor(
22+
private graph: Graph,
23+
private command: string,
24+
{ ensureSingleEditor = false } = {}
25+
) {
2026
this.run = this.run.bind(this);
27+
this.ensureSingleEditor = ensureSingleEditor;
2128
}
2229

2330
private async runCommandAndUpdateSelections(targets: TypedSelection[]) {
@@ -57,14 +64,20 @@ export default class CommandAction implements Action {
5764
);
5865
}
5966

60-
async run([targets]: [
61-
TypedSelection[],
62-
TypedSelection[]
63-
]): Promise<ActionReturnValue> {
64-
await displayPendingEditDecorations(
65-
targets,
66-
this.graph.editStyles.referenced
67-
);
67+
async run(
68+
[targets]: [TypedSelection[]],
69+
{ showDecorations = true } = {}
70+
): Promise<ActionReturnValue> {
71+
if (showDecorations) {
72+
await displayPendingEditDecorations(
73+
targets,
74+
this.graph.editStyles.referenced
75+
);
76+
}
77+
78+
if (this.ensureSingleEditor) {
79+
ensureSingleEditor(targets);
80+
}
6881

6982
const originalEditor = window.activeTextEditor;
7083

src/actions/CutCopyPaste.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {
2+
Action,
3+
ActionPreferences,
4+
ActionReturnValue,
5+
Graph,
6+
TypedSelection,
7+
} from "../Types";
8+
import { performInsideOutsideAdjustment } from "../performInsideOutsideAdjustment";
9+
import CommandAction from "../CommandAction";
10+
import displayPendingEditDecorations from "../editDisplayUtils";
11+
import { getOutsideOverflow } from "../targetUtils";
12+
import { zip } from "lodash";
13+
14+
export class Cut implements Action {
15+
targetPreferences: ActionPreferences[] = [{ insideOutsideType: null }];
16+
17+
constructor(private graph: Graph) {
18+
this.run = this.run.bind(this);
19+
}
20+
21+
async run([targets]: [TypedSelection[]]): Promise<ActionReturnValue> {
22+
const insideTargets = targets.map((target) =>
23+
performInsideOutsideAdjustment(target, "inside")
24+
);
25+
const outsideTargets = targets.map((target) =>
26+
performInsideOutsideAdjustment(target, "outside")
27+
);
28+
const outsideTargetDecorations = zip(insideTargets, outsideTargets).flatMap(
29+
([inside, outside]) => getOutsideOverflow(inside!, outside!)
30+
);
31+
const options = { showDecorations: false };
32+
33+
await Promise.all([
34+
displayPendingEditDecorations(
35+
insideTargets,
36+
this.graph.editStyles.referenced
37+
),
38+
displayPendingEditDecorations(
39+
outsideTargetDecorations,
40+
this.graph.editStyles.pendingDelete
41+
),
42+
]);
43+
44+
await this.graph.actions.copy.run([insideTargets], options);
45+
46+
const { thatMark } = await this.graph.actions.delete.run(
47+
[outsideTargets],
48+
options
49+
);
50+
51+
return {
52+
returnValue: null,
53+
thatMark,
54+
};
55+
}
56+
}
57+
58+
const OPTIONS = { ensureSingleEditor: true };
59+
60+
export class Copy extends CommandAction {
61+
constructor(graph: Graph) {
62+
super(graph, "editor.action.clipboardCopyAction", OPTIONS);
63+
}
64+
}
65+
66+
export class Paste extends CommandAction {
67+
constructor(graph: Graph) {
68+
super(graph, "editor.action.clipboardPasteAction", OPTIONS);
69+
}
70+
}

src/actions/Paste.ts

Lines changed: 0 additions & 84 deletions
This file was deleted.

src/actions/copy.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/actions/cut.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/actions/delete.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ export default class Delete implements Action {
1717
this.run = this.run.bind(this);
1818
}
1919

20-
async run([targets]: [TypedSelection[]]): Promise<ActionReturnValue> {
21-
await displayPendingEditDecorations(
22-
targets,
23-
this.graph.editStyles.pendingDelete,
24-
);
20+
async run(
21+
[targets]: [TypedSelection[]],
22+
{ showDecorations = true } = {}
23+
): Promise<ActionReturnValue> {
24+
if (showDecorations) {
25+
await displayPendingEditDecorations(
26+
targets,
27+
this.graph.editStyles.pendingDelete
28+
);
29+
}
2530

2631
const thatMark = flatten(
2732
await runOnTargetsForEachEditor(targets, async (editor, targets) => {

src/actions/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { ActionRecord, Graph } from "../Types";
22
import Clear from "./clear";
3-
import Copy from "./copy";
4-
import Cut from "./cut";
3+
import { Cut, Copy, Paste } from "./CutCopyPaste";
54
import Delete from "./delete";
65
import ExtractVariable from "./extractVariable";
76
import { Fold, Unfold } from "./fold";
@@ -15,7 +14,6 @@ import Wrap from "./wrap";
1514
import { ScrollToTop, ScrollToCenter, ScrollToBottom } from "./Scroll";
1615
import { IndentLines, OutdentLines } from "./Indent";
1716
import { CommentLines } from "./Comment";
18-
import Paste from "./Paste";
1917
import { Bring, Move, Swap } from "./BringMoveSwap";
2018
import {
2119
InsertEmptyLineAbove,

src/targetUtils.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { TextEditor } from "vscode";
1+
import { TextEditor, Selection, Position } from "vscode";
22
import { groupBy } from "./itertools";
33
import { TypedSelection } from "./Types";
4+
import update from "immutability-helper";
45

56
export function ensureSingleEditor(targets: TypedSelection[]) {
67
if (targets.length === 0) {
@@ -42,3 +43,47 @@ export async function runOnTargetsForEachEditor<T>(
4243
): Promise<T[]> {
4344
return runForEachEditor(targets, (target) => target.selection.editor, func);
4445
}
46+
47+
/** Get the possible leading and trailing overflow ranges of the outside target compared to the inside target */
48+
export function getOutsideOverflow(
49+
insideTarget: TypedSelection,
50+
outsideTarget: TypedSelection
51+
): TypedSelection[] {
52+
const { start: insideStart, end: insideEnd } =
53+
insideTarget.selection.selection;
54+
const { start: outsideStart, end: outsideEnd } =
55+
outsideTarget.selection.selection;
56+
const result = [];
57+
if (outsideStart.isBefore(insideStart)) {
58+
result.push(
59+
createTypeSelection(
60+
insideTarget.selection.editor,
61+
outsideStart,
62+
insideStart
63+
)
64+
);
65+
}
66+
if (outsideEnd.isAfter(insideEnd)) {
67+
result.push(
68+
createTypeSelection(insideTarget.selection.editor, insideEnd, outsideEnd)
69+
);
70+
}
71+
return result;
72+
}
73+
74+
function createTypeSelection(
75+
editor: TextEditor,
76+
start: Position,
77+
end: Position
78+
): TypedSelection {
79+
return {
80+
selection: {
81+
editor,
82+
selection: new Selection(start, end),
83+
},
84+
selectionType: "token",
85+
selectionContext: {},
86+
insideOutsideType: "inside",
87+
position: "contents",
88+
};
89+
}

0 commit comments

Comments
 (0)