mirror of
https://github.com/Silverquark/dance.git
synced 2024-09-11 10:45:43 +03:00
parent
e6dd3dda50
commit
80b8258da5
@ -1691,6 +1691,29 @@ export namespace Selections {
|
||||
*/
|
||||
export const from = fromAnchorActive;
|
||||
|
||||
/**
|
||||
* Sorts selections in the given direction. If `Forward`, selections will be
|
||||
* sorted from top to bottom. Otherwise, they will be sorted from bottom to
|
||||
* top.
|
||||
*/
|
||||
export function sort(direction: Direction, selections: vscode.Selection[] = current.slice()) {
|
||||
return selections.sort(direction === Direction.Forward ? sortTopToBottom : sortBottomToTop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts selections from top to bottom.
|
||||
*/
|
||||
export function topToBottom(selections: vscode.Selection[] = current.slice()) {
|
||||
return selections.sort(sortTopToBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts selections from bottom to top.
|
||||
*/
|
||||
export function bottomToTop(selections: vscode.Selection[] = current.slice()) {
|
||||
return selections.sort(sortBottomToTop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts empty selections by one character to the left.
|
||||
*/
|
||||
@ -1932,3 +1955,11 @@ export namespace Selections {
|
||||
return caretModeSelections;
|
||||
}
|
||||
}
|
||||
|
||||
function sortTopToBottom(a: vscode.Selection, b: vscode.Selection) {
|
||||
return a.start.compareTo(b.start);
|
||||
}
|
||||
|
||||
function sortBottomToTop(a: vscode.Selection, b: vscode.Selection) {
|
||||
return b.start.compareTo(a.start);
|
||||
}
|
||||
|
35
src/commands/README.md
generated
35
src/commands/README.md
generated
@ -173,17 +173,17 @@
|
||||
<tr><td><a href="#selectionsselect"><code>selections.select</code></a></td><td>Select within selections</td><td><code>S</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L301"><code>selections.clear.main</code></a></td><td>Clear main selections</td><td><code>Alt+Space</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L300"><code>selections.clear.secondary</code></a></td><td>Clear secondary selections</td><td><code>Space</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L658"><code>selections.copy.above</code></a></td><td>Copy selections above</td><td><code>Shift+Alt+C</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L622"><code>selections.faceBackward</code></a></td><td>Backward selections</td><td></td></tr>
|
||||
<tr><td><a href="./selections.ts#L621"><code>selections.faceForward</code></a></td><td>Forward selections</td><td><code>Shift+Alt+;</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L662"><code>selections.copy.above</code></a></td><td>Copy selections above</td><td><code>Shift+Alt+C</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L626"><code>selections.faceBackward</code></a></td><td>Backward selections</td><td></td></tr>
|
||||
<tr><td><a href="./selections.ts#L625"><code>selections.faceForward</code></a></td><td>Forward selections</td><td><code>Shift+Alt+;</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L298"><code>selections.filter.regexp</code></a></td><td>Keep matching selections</td><td><code>Alt+K</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L299"><code>selections.filter.regexp.inverse</code></a></td><td>Clear matching selections</td><td><code>Shift+Alt+K</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L738"><code>selections.hideIndices</code></a></td><td>Hide selection indices</td><td></td></tr>
|
||||
<tr><td><a href="./selections.ts#L742"><code>selections.hideIndices</code></a></td><td>Hide selection indices</td><td></td></tr>
|
||||
<tr><td><a href="./selections.ts#L235"><code>selections.pipe.append</code></a></td><td>Pipe and append</td><td><code>Shift+1</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L236"><code>selections.pipe.prepend</code></a></td><td>Pipe and prepend</td><td><code>Shift+Alt+1</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L234"><code>selections.pipe.replace</code></a></td><td>Pipe and replace</td><td><code>Shift+\</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L566"><code>selections.reduce.edges</code></a></td><td>Reduce selections to their ends</td><td><code>Shift+Alt+S</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L737"><code>selections.showIndices</code></a></td><td>Show selection indices</td><td></td></tr>
|
||||
<tr><td><a href="./selections.ts#L570"><code>selections.reduce.edges</code></a></td><td>Reduce selections to their ends</td><td><code>Shift+Alt+S</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="./selections.ts#L741"><code>selections.showIndices</code></a></td><td>Show selection indices</td><td></td></tr>
|
||||
<tr><td><a href="#selectionssplit"><code>selections.split</code></a></td><td>Split selections</td><td><code>Shift+S</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="#selectionssplitLines"><code>selections.splitLines</code></a></td><td>Split selections at line boundaries</td><td><code>Alt+S</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
<tr><td><a href="#selectionstoggleIndices"><code>selections.toggleIndices</code></a></td><td>Toggle selection indices</td><td><code>Enter</code> (<code>editorTextFocus && dance.mode == 'normal'</code>)</td></tr>
|
||||
@ -1047,7 +1047,7 @@ This command:
|
||||
- takes an argument `interactive` of type `boolean`.
|
||||
- takes an input of type `Input<string | RegExp>`.
|
||||
|
||||
### [`selections.split`](./selections.ts#L376-L388)
|
||||
### [`selections.split`](./selections.ts#L377-L389)
|
||||
|
||||
Split selections.
|
||||
|
||||
@ -1057,33 +1057,34 @@ This command:
|
||||
- takes an argument `interactive` of type `boolean`.
|
||||
- takes an input of type `Input<string | RegExp>`.
|
||||
|
||||
### [`selections.splitLines`](./selections.ts#L411-L421)
|
||||
### [`selections.splitLines`](./selections.ts#L412-L423)
|
||||
|
||||
Split selections at line boundaries.
|
||||
|
||||
|
||||
This command:
|
||||
- may be repeated with a given number of repetitions.
|
||||
- takes an argument `excludeEol` of type `boolean`.
|
||||
|
||||
### [`selections.expandToLines`](./selections.ts#L462-L469)
|
||||
### [`selections.expandToLines`](./selections.ts#L466-L473)
|
||||
|
||||
Expand to lines.
|
||||
|
||||
Expand selections to contain full lines (including end-of-line characters).
|
||||
|
||||
### [`selections.trimLines`](./selections.ts#L496-L503)
|
||||
### [`selections.trimLines`](./selections.ts#L500-L507)
|
||||
|
||||
Trim lines.
|
||||
|
||||
Trim selections to only contain full lines (from start to line break).
|
||||
|
||||
### [`selections.trimWhitespace`](./selections.ts#L528-L535)
|
||||
### [`selections.trimWhitespace`](./selections.ts#L532-L539)
|
||||
|
||||
Trim whitespace.
|
||||
|
||||
Trim whitespace at beginning and end of selections.
|
||||
|
||||
### [`selections.reduce`](./selections.ts#L554-L572)
|
||||
### [`selections.reduce`](./selections.ts#L558-L576)
|
||||
|
||||
Reduce selections to their cursor.
|
||||
|
||||
@ -1098,7 +1099,7 @@ Reduce selections to their cursor.
|
||||
This command:
|
||||
- takes an argument `where` of type `"active" | "anchor" | "start" | "end" | "both"`.
|
||||
|
||||
### [`selections.changeDirection`](./selections.ts#L609-L624)
|
||||
### [`selections.changeDirection`](./selections.ts#L613-L628)
|
||||
|
||||
Change direction of selections.
|
||||
|
||||
@ -1111,7 +1112,7 @@ Change direction of selections.
|
||||
| Forward selections | `faceForward` | `a-:` (normal) | `[".selections.changeDirection", { direction: 1 }]` |
|
||||
| Backward selections | `faceBackward` | | `[".selections.changeDirection", { direction: -1 }]` |
|
||||
|
||||
### [`selections.copy`](./selections.ts#L649-L667)
|
||||
### [`selections.copy`](./selections.ts#L653-L671)
|
||||
|
||||
Copy selections below.
|
||||
|
||||
@ -1125,15 +1126,15 @@ Copy selections below.
|
||||
This command:
|
||||
- may be repeated with a given number of repetitions.
|
||||
|
||||
### [`selections.merge`](./selections.ts#L701-L706)
|
||||
### [`selections.merge`](./selections.ts#L705-L710)
|
||||
|
||||
Merge contiguous selections.
|
||||
|
||||
### [`selections.open`](./selections.ts#L710-L713)
|
||||
### [`selections.open`](./selections.ts#L714-L717)
|
||||
|
||||
Open selected file.
|
||||
|
||||
### [`selections.toggleIndices`](./selections.ts#L728-L745)
|
||||
### [`selections.toggleIndices`](./selections.ts#L732-L749)
|
||||
|
||||
Toggle selection indices.
|
||||
|
||||
|
2
src/commands/load-all.ts
generated
2
src/commands/load-all.ts
generated
@ -1123,7 +1123,7 @@ async function loadSelectionsModule(): Promise<CommandDescriptor[]> {
|
||||
),
|
||||
new CommandDescriptor(
|
||||
"dance.selections.splitLines",
|
||||
(_, argument) => _.runAsync((_) => splitLines(_, _.document, _.selections, getRepetitions(_, argument))),
|
||||
(_, argument) => _.runAsync((_) => splitLines(_, _.document, _.selections, getRepetitions(_, argument), argument.excludeEol)),
|
||||
CommandDescriptor.Flags.RequiresActiveEditor,
|
||||
),
|
||||
new CommandDescriptor(
|
||||
|
@ -365,7 +365,8 @@ export function select(
|
||||
|
||||
lastSelectInput = input;
|
||||
|
||||
Selections.set(Selections.selectWithin(input, selections));
|
||||
Selections.set(
|
||||
Selections.bottomToTop(Selections.selectWithin(input, selections)));
|
||||
|
||||
return Promise.resolve(input);
|
||||
});
|
||||
@ -402,7 +403,7 @@ export function split(
|
||||
split = split.filter((s) => !s.isEmpty);
|
||||
}
|
||||
|
||||
Selections.set(split);
|
||||
Selections.set(Selections.bottomToTop(split));
|
||||
|
||||
return Promise.resolve(input);
|
||||
});
|
||||
@ -418,8 +419,10 @@ export function splitLines(
|
||||
document: vscode.TextDocument,
|
||||
selections: readonly vscode.Selection[],
|
||||
repetitions: number,
|
||||
excludeEol: Argument<boolean> = false,
|
||||
) {
|
||||
const newSelections = [] as vscode.Selection[];
|
||||
const newSelections = [] as vscode.Selection[],
|
||||
lineEnd = excludeEol ? Positions.lineEnd : Positions.lineBreak;
|
||||
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i],
|
||||
@ -435,28 +438,29 @@ export function splitLines(
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Add start line.
|
||||
newSelections.push(
|
||||
Selections.fromStartEnd(start, Positions.lineEnd(startLine, document), isReversed, document),
|
||||
Selections.fromStartEnd(start, lineEnd(startLine, document), isReversed, document),
|
||||
);
|
||||
|
||||
// Add intermediate lines.
|
||||
for (let line = startLine + repetitions; line < endLine; line += repetitions) {
|
||||
const start = Positions.lineStart(line),
|
||||
end = Positions.lineEnd(line, document);
|
||||
end = lineEnd(line, document);
|
||||
|
||||
newSelections.push(Selections.fromStartEnd(start, end, isReversed, document));
|
||||
}
|
||||
|
||||
// Add end line.
|
||||
if (endLine % repetitions === 0) {
|
||||
if (endLine % repetitions === 0 && end.character > 0) {
|
||||
newSelections.push(
|
||||
Selections.fromStartEnd(Positions.lineStart(endLine), end, isReversed, document),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Selections.set(newSelections);
|
||||
Selections.set(Selections.bottomToTop(newSelections));
|
||||
}
|
||||
|
||||
/**
|
||||
|
20
test/suite/commands/selections-select.md
Normal file
20
test/suite/commands/selections-select.md
Normal file
@ -0,0 +1,20 @@
|
||||
# 1
|
||||
|
||||
```
|
||||
foo bar
|
||||
^^^^^^^^ 0
|
||||
baz
|
||||
^^^ 0
|
||||
```
|
||||
|
||||
## 1 select
|
||||
[up](#1)
|
||||
|
||||
- .selections.select { input: "b" }
|
||||
|
||||
```
|
||||
foo bar
|
||||
^ 1
|
||||
baz
|
||||
^ 0
|
||||
```
|
45
test/suite/commands/selections-select.test.ts
generated
Normal file
45
test/suite/commands/selections-select.test.ts
generated
Normal file
@ -0,0 +1,45 @@
|
||||
import * as vscode from "vscode";
|
||||
|
||||
import { executeCommand, ExpectedDocument, groupTestsByParentName } from "../utils";
|
||||
|
||||
suite("./test/suite/commands/selections-select.md", function () {
|
||||
// Set up document.
|
||||
let document: vscode.TextDocument,
|
||||
editor: vscode.TextEditor;
|
||||
|
||||
this.beforeAll(async () => {
|
||||
document = await vscode.workspace.openTextDocument();
|
||||
editor = await vscode.window.showTextDocument(document);
|
||||
editor.options.insertSpaces = true;
|
||||
editor.options.tabSize = 2;
|
||||
|
||||
await executeCommand("dance.dev.setSelectionBehavior", { mode: "normal", value: "caret" });
|
||||
});
|
||||
|
||||
this.afterAll(async () => {
|
||||
await executeCommand("workbench.action.closeActiveEditor");
|
||||
});
|
||||
|
||||
test("1 > select", async function () {
|
||||
// Set-up document to be in expected initial state.
|
||||
await ExpectedDocument.apply(editor, 6, String.raw`
|
||||
foo bar
|
||||
^^^^^^^^ 0
|
||||
baz
|
||||
^^^ 0
|
||||
`);
|
||||
|
||||
// Perform all operations.
|
||||
await executeCommand("dance.selections.select", { input: "b" });
|
||||
|
||||
// Ensure document is as expected.
|
||||
ExpectedDocument.assertEquals(editor, "./test/suite/commands/selections-select.md:10:1", 6, String.raw`
|
||||
foo bar
|
||||
^ 1
|
||||
baz
|
||||
^ 0
|
||||
`);
|
||||
});
|
||||
|
||||
groupTestsByParentName(this);
|
||||
});
|
53
test/suite/commands/selections-split.md
Normal file
53
test/suite/commands/selections-split.md
Normal file
@ -0,0 +1,53 @@
|
||||
# 1
|
||||
|
||||
```
|
||||
first line
|
||||
^^^^^^^^^^^ 0
|
||||
second line
|
||||
^^^^^^^^^^^^ 0
|
||||
third line
|
||||
^^^^^^^^^^^ 0
|
||||
|
||||
```
|
||||
|
||||
## 1 split
|
||||
[up](#1)
|
||||
|
||||
- .selections.splitLines
|
||||
|
||||
```
|
||||
first line
|
||||
^^^^^^^^^^^ 2
|
||||
second line
|
||||
^^^^^^^^^^^^ 1
|
||||
third line
|
||||
^^^^^^^^^^^ 0
|
||||
|
||||
```
|
||||
|
||||
# 2
|
||||
|
||||
```
|
||||
first line
|
||||
^^^^^^^^^^^ 0
|
||||
second line
|
||||
^^^^^ 0 ^^^^ 1
|
||||
third line
|
||||
^^^^^ 1
|
||||
|
||||
```
|
||||
|
||||
## 2 split
|
||||
[up](#2)
|
||||
|
||||
- .selections.splitLines
|
||||
|
||||
```
|
||||
first line
|
||||
^^^^^^^^^^^ 3
|
||||
second line
|
||||
^^^^^ 2 ^^^^ 1
|
||||
third line
|
||||
^^^^^ 0
|
||||
|
||||
```
|
78
test/suite/commands/selections-split.test.ts
generated
Normal file
78
test/suite/commands/selections-split.test.ts
generated
Normal file
@ -0,0 +1,78 @@
|
||||
import * as vscode from "vscode";
|
||||
|
||||
import { executeCommand, ExpectedDocument, groupTestsByParentName } from "../utils";
|
||||
|
||||
suite("./test/suite/commands/selections-split.md", function () {
|
||||
// Set up document.
|
||||
let document: vscode.TextDocument,
|
||||
editor: vscode.TextEditor;
|
||||
|
||||
this.beforeAll(async () => {
|
||||
document = await vscode.workspace.openTextDocument();
|
||||
editor = await vscode.window.showTextDocument(document);
|
||||
editor.options.insertSpaces = true;
|
||||
editor.options.tabSize = 2;
|
||||
|
||||
await executeCommand("dance.dev.setSelectionBehavior", { mode: "normal", value: "caret" });
|
||||
});
|
||||
|
||||
this.afterAll(async () => {
|
||||
await executeCommand("workbench.action.closeActiveEditor");
|
||||
});
|
||||
|
||||
test("1 > split", async function () {
|
||||
// Set-up document to be in expected initial state.
|
||||
await ExpectedDocument.apply(editor, 6, String.raw`
|
||||
first line
|
||||
^^^^^^^^^^^ 0
|
||||
second line
|
||||
^^^^^^^^^^^^ 0
|
||||
third line
|
||||
^^^^^^^^^^^ 0
|
||||
|
||||
`);
|
||||
|
||||
// Perform all operations.
|
||||
await executeCommand("dance.selections.splitLines");
|
||||
|
||||
// Ensure document is as expected.
|
||||
ExpectedDocument.assertEquals(editor, "./test/suite/commands/selections-split.md:13:1", 6, String.raw`
|
||||
first line
|
||||
^^^^^^^^^^^ 2
|
||||
second line
|
||||
^^^^^^^^^^^^ 1
|
||||
third line
|
||||
^^^^^^^^^^^ 0
|
||||
|
||||
`);
|
||||
});
|
||||
|
||||
test("2 > split", async function () {
|
||||
// Set-up document to be in expected initial state.
|
||||
await ExpectedDocument.apply(editor, 6, String.raw`
|
||||
first line
|
||||
^^^^^^^^^^^ 0
|
||||
second line
|
||||
^^^^^ 0 ^^^^ 1
|
||||
third line
|
||||
^^^^^ 1
|
||||
|
||||
`);
|
||||
|
||||
// Perform all operations.
|
||||
await executeCommand("dance.selections.splitLines");
|
||||
|
||||
// Ensure document is as expected.
|
||||
ExpectedDocument.assertEquals(editor, "./test/suite/commands/selections-split.md:40:1", 6, String.raw`
|
||||
first line
|
||||
^^^^^^^^^^^ 3
|
||||
second line
|
||||
^^^^^ 2 ^^^^ 1
|
||||
third line
|
||||
^^^^^ 0
|
||||
|
||||
`);
|
||||
});
|
||||
|
||||
groupTestsByParentName(this);
|
||||
});
|
Loading…
Reference in New Issue
Block a user