mirror of
https://github.com/cursorless-dev/cursorless.git
synced 2024-10-05 05:17:38 +03:00
Fixed selection bug and added source mark to copy lines (#384)
* Fix so clone up moves selection * Added source mark to copy lines * Added tests for clone linesg * Updated tests
This commit is contained in:
parent
0712ee8fa9
commit
9df55b699c
@ -46,14 +46,20 @@ class CopyLines implements Action {
|
||||
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 length = text.length;
|
||||
text = this.isUp ? `${delimiter}${text}` : `${text}${delimiter}`;
|
||||
const newRange = this.isUp
|
||||
? new Range(range.start, range.start)
|
||||
: new Range(range.end, range.end);
|
||||
? new Range(range.end, range.end)
|
||||
: new Range(range.start, range.start);
|
||||
return {
|
||||
editor,
|
||||
range: newRange,
|
||||
text,
|
||||
edit: {
|
||||
editor,
|
||||
range: newRange,
|
||||
text,
|
||||
isReplace: this.isUp,
|
||||
},
|
||||
offset: delimiter.length,
|
||||
length,
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -62,27 +68,44 @@ class CopyLines implements Action {
|
||||
const results = flatten(
|
||||
await runOnTargetsForEachEditor(targets, async (editor, targets) => {
|
||||
const ranges = this.getRanges(editor, targets);
|
||||
const edits = this.getEdits(editor, ranges);
|
||||
const editWrappers = this.getEdits(editor, ranges);
|
||||
const rangeSelections = ranges.map(
|
||||
({ range }) => new Selection(range.start, range.end)
|
||||
);
|
||||
|
||||
const [updatedSelections, copySelections] =
|
||||
const [editorSelections, copySelections] =
|
||||
await performEditsAndUpdateSelections(
|
||||
this.graph.rangeUpdater,
|
||||
editor,
|
||||
edits,
|
||||
[
|
||||
targets.map((target) => target.selection.selection),
|
||||
ranges.map(({ range }) => new Selection(range.start, range.end)),
|
||||
]
|
||||
editWrappers.map((wrapper) => wrapper.edit),
|
||||
[editor.selections, rangeSelections]
|
||||
);
|
||||
|
||||
editor.revealRange(updatedSelections[0]);
|
||||
editor.selections = editorSelections;
|
||||
editor.revealRange(copySelections[0]);
|
||||
|
||||
let sourceSelections;
|
||||
if (this.isUp) {
|
||||
sourceSelections = editWrappers.map((wrapper) => {
|
||||
const startIndex =
|
||||
editor.document.offsetAt(wrapper.edit.range.start) +
|
||||
wrapper.offset;
|
||||
const endIndex = startIndex + wrapper.length;
|
||||
return new Selection(
|
||||
editor.document.positionAt(startIndex),
|
||||
editor.document.positionAt(endIndex)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
sourceSelections = rangeSelections;
|
||||
}
|
||||
|
||||
return {
|
||||
thatMark: updatedSelections.map((selection) => ({
|
||||
sourceMark: sourceSelections.map((selection) => ({
|
||||
editor,
|
||||
selection,
|
||||
})),
|
||||
copySelections: copySelections.map((selection) => ({
|
||||
thatMark: copySelections.map((selection) => ({
|
||||
editor,
|
||||
selection,
|
||||
})),
|
||||
@ -91,24 +114,25 @@ class CopyLines implements Action {
|
||||
);
|
||||
|
||||
await displayPendingEditDecorationsForSelection(
|
||||
results.flatMap((result) => result.copySelections),
|
||||
results.flatMap((result) => result.thatMark),
|
||||
this.graph.editStyles.justAdded.token
|
||||
);
|
||||
|
||||
const sourceMark = results.flatMap((result) => result.sourceMark);
|
||||
const thatMark = results.flatMap((result) => result.thatMark);
|
||||
|
||||
return { thatMark };
|
||||
return { sourceMark, thatMark };
|
||||
}
|
||||
}
|
||||
|
||||
export class CopyLinesUp extends CopyLines {
|
||||
constructor(graph: Graph) {
|
||||
super(graph, false);
|
||||
super(graph, true);
|
||||
}
|
||||
}
|
||||
|
||||
export class CopyLinesDown extends CopyLines {
|
||||
constructor(graph: Graph) {
|
||||
super(graph, true);
|
||||
super(graph, false);
|
||||
}
|
||||
}
|
||||
|
31
src/test/suite/fixtures/recorded/actions/cloneHarp.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneHarp.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone harp
|
||||
action: insertCopyAfter
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: h}
|
||||
initialState:
|
||||
documentContents: hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 5}
|
||||
active: {line: 0, character: 5}
|
||||
marks:
|
||||
default.h:
|
||||
start: {line: 0, character: 0}
|
||||
end: {line: 0, character: 5}
|
||||
finalState:
|
||||
documentContents: |-
|
||||
hello
|
||||
hello
|
||||
selections:
|
||||
- anchor: {line: 1, character: 5}
|
||||
active: {line: 1, character: 5}
|
||||
thatMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 5}
|
||||
sourceMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 5}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
31
src/test/suite/fixtures/recorded/actions/cloneHarp2.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneHarp2.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone harp
|
||||
action: insertCopyAfter
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: h}
|
||||
initialState:
|
||||
documentContents: hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 0}
|
||||
marks:
|
||||
default.h:
|
||||
start: {line: 0, character: 0}
|
||||
end: {line: 0, character: 5}
|
||||
finalState:
|
||||
documentContents: |-
|
||||
hello
|
||||
hello
|
||||
selections:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 0}
|
||||
thatMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 5}
|
||||
sourceMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 5}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
31
src/test/suite/fixtures/recorded/actions/cloneUpHarp.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneUpHarp.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone up harp
|
||||
action: insertCopyBefore
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: h}
|
||||
initialState:
|
||||
documentContents: hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 5}
|
||||
active: {line: 0, character: 5}
|
||||
marks:
|
||||
default.h:
|
||||
start: {line: 0, character: 0}
|
||||
end: {line: 0, character: 5}
|
||||
finalState:
|
||||
documentContents: |-
|
||||
hello
|
||||
hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 5}
|
||||
active: {line: 0, character: 5}
|
||||
thatMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 5}
|
||||
sourceMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 5}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
31
src/test/suite/fixtures/recorded/actions/cloneUpHarp2.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneUpHarp2.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone up harp
|
||||
action: insertCopyBefore
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: h}
|
||||
initialState:
|
||||
documentContents: hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 0}
|
||||
marks:
|
||||
default.h:
|
||||
start: {line: 0, character: 0}
|
||||
end: {line: 0, character: 5}
|
||||
finalState:
|
||||
documentContents: |-
|
||||
hello
|
||||
hello
|
||||
selections:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 0}
|
||||
thatMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 5}
|
||||
sourceMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 5}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: h}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
31
src/test/suite/fixtures/recorded/actions/cloneUpVest.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneUpVest.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone up vest
|
||||
action: insertCopyBefore
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: v}
|
||||
initialState:
|
||||
documentContents: " const value = \"Hello world\";"
|
||||
selections:
|
||||
- anchor: {line: 0, character: 15}
|
||||
active: {line: 0, character: 15}
|
||||
marks:
|
||||
default.v:
|
||||
start: {line: 0, character: 10}
|
||||
end: {line: 0, character: 15}
|
||||
finalState:
|
||||
documentContents: |2-
|
||||
const value = "Hello world";
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 0, character: 15}
|
||||
active: {line: 0, character: 15}
|
||||
thatMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 32}
|
||||
sourceMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 32}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
31
src/test/suite/fixtures/recorded/actions/cloneVest.yml
Normal file
31
src/test/suite/fixtures/recorded/actions/cloneVest.yml
Normal file
@ -0,0 +1,31 @@
|
||||
languageId: plaintext
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: clone vest
|
||||
action: insertCopyAfter
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: v}
|
||||
initialState:
|
||||
documentContents: " const value = \"Hello world\";"
|
||||
selections:
|
||||
- anchor: {line: 0, character: 15}
|
||||
active: {line: 0, character: 15}
|
||||
marks:
|
||||
default.v:
|
||||
start: {line: 0, character: 10}
|
||||
end: {line: 0, character: 15}
|
||||
finalState:
|
||||
documentContents: |2-
|
||||
const value = "Hello world";
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 1, character: 15}
|
||||
active: {line: 1, character: 15}
|
||||
thatMark:
|
||||
- anchor: {line: 1, character: 0}
|
||||
active: {line: 1, character: 32}
|
||||
sourceMark:
|
||||
- anchor: {line: 0, character: 0}
|
||||
active: {line: 0, character: 32}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: identity}}]
|
@ -1,31 +0,0 @@
|
||||
languageId: typescript
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: dupe up vest
|
||||
action: insertCopyBefore
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: v}
|
||||
initialState:
|
||||
documentContents: |
|
||||
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 1, character: 11}
|
||||
active: {line: 1, character: 11}
|
||||
marks:
|
||||
default.v:
|
||||
start: {line: 1, character: 6}
|
||||
end: {line: 1, character: 11}
|
||||
finalState:
|
||||
documentContents: |
|
||||
|
||||
const value = "Hello world";
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 1, character: 11}
|
||||
active: {line: 1, character: 11}
|
||||
thatMark:
|
||||
- anchor: {line: 1, character: 6}
|
||||
active: {line: 1, character: 11}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}]
|
@ -1,31 +0,0 @@
|
||||
languageId: typescript
|
||||
command:
|
||||
version: 1
|
||||
spokenForm: dupe vest
|
||||
action: insertCopyAfter
|
||||
targets:
|
||||
- type: primitive
|
||||
mark: {type: decoratedSymbol, symbolColor: default, character: v}
|
||||
initialState:
|
||||
documentContents: |
|
||||
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 1, character: 11}
|
||||
active: {line: 1, character: 11}
|
||||
marks:
|
||||
default.v:
|
||||
start: {line: 1, character: 6}
|
||||
end: {line: 1, character: 11}
|
||||
finalState:
|
||||
documentContents: |
|
||||
|
||||
const value = "Hello world";
|
||||
const value = "Hello world";
|
||||
selections:
|
||||
- anchor: {line: 2, character: 11}
|
||||
active: {line: 2, character: 11}
|
||||
thatMark:
|
||||
- anchor: {line: 2, character: 6}
|
||||
active: {line: 2, character: 11}
|
||||
fullTargets: [{type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}]
|
Loading…
Reference in New Issue
Block a user