-
-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy pathCopyLines.ts
More file actions
107 lines (94 loc) · 3.16 KB
/
CopyLines.ts
File metadata and controls
107 lines (94 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {
Action,
ActionPreferences,
ActionReturnValue,
Graph,
TypedSelection,
} from "../typings/Types";
import { Range, Selection, TextEditor } from "vscode";
import { performEditsAndUpdateSelections } from "../util/updateSelections";
import { displayPendingEditDecorationsForSelection } from "../util/editDisplayUtils";
import { runOnTargetsForEachEditor } from "../util/targetUtils";
import { flatten } from "lodash";
import unifyRanges from "../util/unifyRanges";
import expandToContainingLine from "../util/expandToContainingLine";
class CopyLines implements Action {
getTargetPreferences: () => ActionPreferences[] = () => [{ insideOutsideType: "inside" }];
constructor(private graph: Graph, private isUp: boolean) {
this.run = this.run.bind(this);
}
private getRanges(editor: TextEditor, targets: TypedSelection[]) {
const paragraphTargets = targets.filter(
(target) => target.selectionType === "paragraph"
);
const ranges = targets.map((target) =>
expandToContainingLine(editor, target.selection.selection)
);
const unifiedRanges = unifyRanges(ranges);
return unifiedRanges.map((range) => ({
range,
isParagraph:
paragraphTargets.find((target) =>
target.selection.selection.isEqual(range)
) != null,
}));
}
private getEdits(
editor: TextEditor,
ranges: { range: Range; isParagraph: boolean }[]
) {
return ranges.map(({ range, isParagraph }) => {
const delimiter = isParagraph ? "\n\n" : "\n";
let text = editor.document.getText(range);
text = this.isUp ? `${text}${delimiter}` : `${delimiter}${text}`;
const newRange = this.isUp
? new Range(range.start, range.start)
: new Range(range.end, range.end);
return {
editor,
range: newRange,
text,
};
});
}
async run([targets]: [TypedSelection[]]): Promise<ActionReturnValue> {
const results = flatten(
await runOnTargetsForEachEditor(targets, async (editor, targets) => {
const ranges = this.getRanges(editor, targets);
const edits = this.getEdits(editor, ranges);
const [updatedSelections, copySelections] =
await performEditsAndUpdateSelections(editor, edits, [
targets.map((target) => target.selection.selection),
ranges.map(({ range }) => new Selection(range.start, range.end)),
]);
editor.revealRange(updatedSelections[0]);
return {
thatMark: updatedSelections.map((selection) => ({
editor,
selection,
})),
copySelections: copySelections.map((selection) => ({
editor,
selection,
})),
};
})
);
await displayPendingEditDecorationsForSelection(
results.flatMap((result) => result.copySelections),
this.graph.editStyles.justAdded.token
);
const thatMark = results.flatMap((result) => result.thatMark);
return { thatMark };
}
}
export class CopyLinesUp extends CopyLines {
constructor(graph: Graph) {
super(graph, false);
}
}
export class CopyLinesDown extends CopyLines {
constructor(graph: Graph) {
super(graph, true);
}
}