Skip to content

Commit 9dcf9c0

Browse files
Added action replace (#135)
1 parent 563ed19 commit 9dcf9c0

23 files changed

+261
-193
lines changed

src/CommandAction.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ export default class CommandAction implements Action {
6363
]): Promise<ActionReturnValue> {
6464
await displayPendingEditDecorations(
6565
targets,
66-
this.graph.editStyles.referenced,
67-
this.graph.editStyles.referencedLine
66+
this.graph.editStyles.referenced
6867
);
6968

7069
const originalEditor = window.activeTextEditor;

src/Types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { SyntaxNode } from "web-tree-sitter";
22
import * as vscode from "vscode";
33
import { Location } from "vscode";
44
import { SymbolColor } from "./constants";
5-
import EditStyles from "./editStyles";
5+
import { EditStyles } from "./editStyles";
66
import NavigationMap from "./NavigationMap";
77

88
/**
@@ -256,6 +256,7 @@ export type ActionType =
256256
| "move"
257257
| "outdentLines"
258258
| "paste"
259+
| "replaceWithText"
259260
| "scrollToBottom"
260261
| "scrollToCenter"
261262
| "scrollToTop"

src/actions/BringMoveSwap.ts

Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,11 @@ import {
99
import { runForEachEditor } from "../targetUtils";
1010
import update from "immutability-helper";
1111
import displayPendingEditDecorations from "../editDisplayUtils";
12-
import { performInsideOutsideAdjustment } from "../performInsideOutsideAdjustment";
12+
import { performOutsideAdjustment } from "../performInsideOutsideAdjustment";
1313
import { flatten, zip } from "lodash";
14-
import { Selection, TextEditorDecorationType, TextEditor, Range } from "vscode";
14+
import { Selection, TextEditor, Range } from "vscode";
1515
import { performEditsAndUpdateSelections } from "../updateSelections";
16-
17-
interface DecorationTypes {
18-
sourceStyle: TextEditorDecorationType;
19-
sourceLineStyle: TextEditorDecorationType;
20-
destinationStyle: TextEditorDecorationType;
21-
destinationLineStyle: TextEditorDecorationType;
22-
}
16+
import { getTextWithPossibleDelimiter } from "../getTextWithPossibleDelimiter";
2317

2418
interface ExtendedEdit extends Edit {
2519
editor: TextEditor;
@@ -37,7 +31,7 @@ interface ThatMarkEntry {
3731
class BringMoveSwap implements Action {
3832
targetPreferences: ActionPreferences[] = [
3933
{ insideOutsideType: null },
40-
{ insideOutsideType: "inside" },
34+
{ insideOutsideType: null },
4135
];
4236

4337
constructor(private graph: Graph, private type: string) {
@@ -56,25 +50,20 @@ class BringMoveSwap implements Action {
5650
return sources;
5751
}
5852

59-
private getDecorationStyles(): DecorationTypes {
60-
let sourceStyle, sourceLineStyle;
53+
private getDecorationStyles() {
54+
let sourceStyle;
6155
if (this.type === "bring") {
6256
sourceStyle = this.graph.editStyles.referenced;
63-
sourceLineStyle = this.graph.editStyles.referencedLine;
64-
} else if (this.type === "swap") {
65-
sourceStyle = this.graph.editStyles.pendingModification1;
66-
sourceLineStyle = this.graph.editStyles.pendingLineModification1;
6757
} else if (this.type === "move") {
6858
sourceStyle = this.graph.editStyles.pendingDelete;
69-
sourceLineStyle = this.graph.editStyles.pendingLineDelete;
70-
} else {
71-
throw Error(`Unknown type "${this.type}"`);
59+
}
60+
// NB this.type === "swap"
61+
else {
62+
sourceStyle = this.graph.editStyles.pendingModification1;
7263
}
7364
return {
7465
sourceStyle,
75-
sourceLineStyle,
7666
destinationStyle: this.graph.editStyles.pendingModification0,
77-
destinationLineStyle: this.graph.editStyles.pendingLineModification0,
7867
};
7968
}
8069

@@ -84,15 +73,10 @@ class BringMoveSwap implements Action {
8473
) {
8574
const decorationTypes = this.getDecorationStyles();
8675
await Promise.all([
87-
displayPendingEditDecorations(
88-
sources,
89-
decorationTypes.sourceStyle,
90-
decorationTypes.sourceLineStyle
91-
),
76+
displayPendingEditDecorations(sources, decorationTypes.sourceStyle),
9277
displayPendingEditDecorations(
9378
destinations,
94-
decorationTypes.destinationStyle,
95-
decorationTypes.destinationLineStyle
79+
decorationTypes.destinationStyle
9680
),
9781
]);
9882
}
@@ -107,54 +91,45 @@ class BringMoveSwap implements Action {
10791
throw new Error("Targets must have same number of args");
10892
}
10993

110-
const sourceText = source.selection.editor.document.getText(
111-
source.selection.selection
112-
);
113-
114-
const { containingListDelimiter } = destination.selectionContext;
115-
const newText =
116-
containingListDelimiter == null || destination.position === "contents"
117-
? sourceText
118-
: destination.position === "after"
119-
? containingListDelimiter + sourceText
120-
: sourceText + containingListDelimiter;
94+
// Get text adjusting for destination position
95+
const text = getTextWithPossibleDelimiter(source, destination);
12196

12297
// Add destination edit
12398
const result = [
12499
{
125-
isSource: false,
100+
range: destination.selection.selection as Range,
101+
text,
126102
editor: destination.selection.editor,
127103
originalSelection: destination,
128-
range: destination.selection.selection as Range,
129-
text: newText,
104+
isSource: false,
130105
},
131106
];
132107

133108
// Add source edit for move and swap
134109
// Prevent multiple instances of the same expanded source.
135110
if (this.type !== "bring" && !usedSources.includes(source)) {
136-
let newText: string;
111+
let text: string;
137112
let range: Range;
138113

139114
if (this.type === "swap") {
140-
newText = destination.selection.editor.document.getText(
115+
text = destination.selection.editor.document.getText(
141116
destination.selection.selection
142117
);
143118
range = source.selection.selection;
144-
} else {
145-
// NB: this.type === "move"
146-
newText = "";
147-
range = performInsideOutsideAdjustment(source, "outside").selection
148-
.selection;
119+
}
120+
// NB: this.type === "move"
121+
else {
122+
text = "";
123+
range = performOutsideAdjustment(source).selection.selection;
149124
}
150125

151126
usedSources.push(source);
152127
result.push({
153-
isSource: true,
128+
range,
129+
text,
154130
editor: source.selection.editor,
155131
originalSelection: source,
156-
range,
157-
text: newText,
132+
isSource: true,
158133
});
159134
}
160135

@@ -206,15 +181,13 @@ class BringMoveSwap implements Action {
206181
thatMark
207182
.filter(({ isSource }) => isSource)
208183
.map(({ typedSelection }) => typedSelection),
209-
decorationTypes.sourceStyle,
210-
decorationTypes.sourceLineStyle
184+
decorationTypes.sourceStyle
211185
),
212186
displayPendingEditDecorations(
213187
thatMark
214188
.filter(({ isSource }) => !isSource)
215189
.map(({ typedSelection }) => typedSelection),
216-
decorationTypes.destinationStyle,
217-
decorationTypes.destinationLineStyle
190+
decorationTypes.destinationStyle
218191
),
219192
]);
220193
}

src/actions/CopyLines.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ class CopyLines implements Action {
4646
async run([targets]: [TypedSelection[]]): Promise<ActionReturnValue> {
4747
await displayPendingEditDecorations(
4848
targets,
49-
this.graph.editStyles.referenced,
50-
this.graph.editStyles.referencedLine
49+
this.graph.editStyles.referenced
5150
);
5251

5352
const thatMark = flatten(

src/actions/Find.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ export class FindInFiles implements Action {
1818
async run([targets]: [TypedSelection[]]): Promise<ActionReturnValue> {
1919
ensureSingleTarget(targets);
2020

21-
const { returnValue: query, thatMark } =
22-
await this.graph.actions.getText.run([targets]);
21+
const {
22+
returnValue: [query],
23+
thatMark,
24+
} = await this.graph.actions.getText.run([targets]);
2325

24-
await commands.executeCommand("workbench.action.findInFiles", { query });
26+
await commands.executeCommand("workbench.action.findInFiles", {
27+
query,
28+
});
2529

2630
return { returnValue: null, thatMark };
2731
}

src/actions/GetText.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,21 @@ export default class GetText implements Action {
1616

1717
async run(
1818
[targets]: [TypedSelection[]],
19-
showDecorations = true
19+
{ showDecorations = true } = {}
2020
): Promise<ActionReturnValue> {
2121
if (showDecorations) {
2222
await displayPendingEditDecorations(
2323
targets,
24-
this.graph.editStyles.referenced,
25-
this.graph.editStyles.referencedLine
24+
this.graph.editStyles.referenced
2625
);
2726
}
2827

29-
const text = targets
30-
.map((target) =>
31-
target.selection.editor.document.getText(target.selection.selection)
32-
)
33-
.join("\n");
28+
const returnValue = targets.map((target) =>
29+
target.selection.editor.document.getText(target.selection.selection)
30+
);
3431

3532
return {
36-
returnValue: text,
33+
returnValue,
3734
thatMark: targets.map((target) => target.selection),
3835
};
3936
}

src/actions/InsertEmptyLines.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class InsertEmptyLines implements Action {
2424
displayPendingEditDecorations(
2525
targets,
2626
this.graph.editStyles.referenced,
27-
this.graph.editStyles.referencedLine
2827
);
2928

3029
const edits = await runForEachEditor(

src/actions/Paste.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export default class Paste implements Action {
2323
await displayPendingEditDecorations(
2424
targets,
2525
this.graph.editStyles.pendingModification0,
26-
this.graph.editStyles.pendingLineModification0
2726
);
2827

2928
const text = await env.clipboard.readText();
@@ -78,7 +77,6 @@ export default class Paste implements Action {
7877
await displayPendingEditDecorations(
7978
thatMark.map(({ typedSelection }) => typedSelection),
8079
this.graph.editStyles.pendingModification0,
81-
this.graph.editStyles.pendingLineModification0
8280
);
8381

8482
return { returnValue: null, thatMark };

src/actions/ReplaceWithText.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import {
2+
Action,
3+
ActionPreferences,
4+
ActionReturnValue,
5+
Graph,
6+
TypedSelection,
7+
} from "../Types";
8+
import displayPendingEditDecorations from "../editDisplayUtils";
9+
import { runForEachEditor } from "../targetUtils";
10+
import { flatten, zip } from "lodash";
11+
import { maybeAddDelimiter } from "../getTextWithPossibleDelimiter";
12+
import { performEditsAndUpdateSelections } from "../updateSelections";
13+
14+
export default class 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(
22+
[targets]: [TypedSelection[]],
23+
texts: string[]
24+
): Promise<ActionReturnValue> {
25+
await displayPendingEditDecorations(
26+
targets,
27+
this.graph.editStyles.pendingModification0
28+
);
29+
30+
// Broadcast single text for each target
31+
if (texts.length === 1) {
32+
texts = Array(targets.length).fill(texts[0]);
33+
}
34+
35+
if (targets.length !== texts.length) {
36+
throw new Error("Targets and texts must have same length");
37+
}
38+
39+
const edits = zip(targets, texts).map(([target, text]) => ({
40+
editor: target!.selection.editor,
41+
range: target!.selection.selection,
42+
text: maybeAddDelimiter(text!, target!),
43+
}));
44+
45+
const thatMark = flatten(
46+
await runForEachEditor(
47+
edits,
48+
(edit) => edit.editor,
49+
async (editor, edits) => {
50+
const [updatedSelections] = await performEditsAndUpdateSelections(
51+
editor,
52+
edits,
53+
[targets.map((target) => target.selection.selection)]
54+
);
55+
56+
return updatedSelections.map((selection) => ({
57+
editor,
58+
selection,
59+
}));
60+
}
61+
)
62+
);
63+
64+
return { returnValue: null, thatMark };
65+
}
66+
}

src/actions/Scroll.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Scroll implements Action {
5656

5757
await displayDecorationsWhileRunningFunc(
5858
targets.map((target) => target.selection),
59-
this.graph.editStyles.referencedLine,
59+
this.graph.editStyles.referenced.line,
6060
scrollCallback,
6161
showAdditionalHighlightBeforeScroll
6262
);

src/actions/SetBreakpoint.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export default class SetBreakpoint implements Action {
4141
]): Promise<ActionReturnValue> {
4242
await displayPendingEditDecorations(
4343
targets,
44-
this.graph.editStyles.referenced,
45-
this.graph.editStyles.referencedLine
44+
this.graph.editStyles.referenced
4645
);
4746

4847
const lines = targets.flatMap((target) => {

src/actions/copy.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ export default class Copy implements Action {
1818
const { returnValue, thatMark } = await this.graph.actions.getText.run([
1919
targets,
2020
]);
21+
const text = returnValue.join("\n");
2122

22-
await env.clipboard.writeText(returnValue);
23+
await env.clipboard.writeText(text);
2324

2425
return { returnValue: null, thatMark };
2526
}

0 commit comments

Comments
 (0)