Skip to content

Commit 99e4a40

Browse files
Add limited support for :sort
- Works on a range - ! option is supported to reverse the sort - Other options not supported at this time Fixes: #1341
1 parent 862ef4a commit 99e4a40

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

src/cmd_line/commands/sort.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"use strict";
2+
3+
import * as vscode from "vscode";
4+
import * as node from "../node";
5+
import * as token from "../token";
6+
import { ModeHandler } from "../../mode/modeHandler";
7+
import { TextEditor } from "../../textEditor";
8+
9+
export interface ISortCommandArguments extends node.ICommandArgs {
10+
reverse: boolean;
11+
}
12+
13+
14+
export class SortCommand extends node.CommandBase {
15+
16+
protected _arguments : ISortCommandArguments;
17+
18+
constructor(args: ISortCommandArguments) {
19+
super();
20+
this._arguments = args;
21+
}
22+
23+
get arguments() : ISortCommandArguments {
24+
return this._arguments;
25+
}
26+
27+
async execute(modeHandler : ModeHandler): Promise<void> {
28+
await this.sortLines(new vscode.Position(0, 0), new vscode.Position(TextEditor.getLineCount() - 1, 0));
29+
}
30+
31+
async sortLines(startLine: vscode.Position, endLine: vscode.Position) {
32+
let originalLines: String[] = [];
33+
34+
for (let currentLine = startLine.line; currentLine <= endLine.line && currentLine < TextEditor.getLineCount(); currentLine++) {
35+
originalLines.push(TextEditor.readLineAt(currentLine));
36+
}
37+
38+
let lastLineLength = originalLines[originalLines.length - 1].length;
39+
let sortedLines = originalLines.sort();
40+
41+
if (this._arguments.reverse) {
42+
sortedLines.reverse();
43+
}
44+
45+
let sortedContent = sortedLines.join("\n");
46+
47+
await TextEditor.replace(new vscode.Range(startLine.line, 0, endLine.line, lastLineLength), sortedContent);
48+
}
49+
50+
async executeWithRange(modeHandler : ModeHandler, range: node.LineRange) {
51+
let startLine: vscode.Position;
52+
let endLine: vscode.Position;
53+
54+
if (range.left[0].type === token.TokenType.Percent) {
55+
startLine = new vscode.Position(0, 0);
56+
endLine = new vscode.Position(TextEditor.getLineCount() - 1, 0);
57+
} else {
58+
startLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.left, modeHandler);
59+
endLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.right, modeHandler);
60+
}
61+
62+
await this.sortLines(startLine, endLine);
63+
}
64+
}

src/cmd_line/subparser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { parseSubstituteCommandArgs } from './subparsers/substitute';
1212
import { parseReadCommandArgs } from './subparsers/read';
1313
import { parseRegisterCommandArgs } from './subparsers/register';
1414
import { parseDeleteRangeLinesCommandArgs } from './subparsers/deleteRange';
15+
import { parseSortCommandArgs } from './subparsers/sort';
1516

1617
// maps command names to parsers for said commands.
1718
export const commandParsers = {
@@ -83,4 +84,6 @@ export const commandParsers = {
8384

8485
d: parseDeleteRangeLinesCommandArgs,
8586

87+
sort: parseSortCommandArgs,
88+
8689
};

src/cmd_line/subparsers/sort.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"use strict";
2+
3+
import * as node from "../commands/sort";
4+
5+
export function parseSortCommandArgs(args : string) : node.SortCommand {
6+
7+
let reverse_ = false;
8+
if (args != null && args.indexOf("!") >= 0) {
9+
reverse_ = true;
10+
}
11+
12+
return new node.SortCommand({
13+
reverse: reverse_,
14+
});
15+
16+
}

test/cmd_line/sort.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"use strict";
2+
3+
import { ModeHandler } from '../../src/mode/modeHandler';
4+
import { setupWorkspace, cleanUpWorkspace, assertEqualLines } from './../testUtils';
5+
import { runCmdLine } from '../../src/cmd_line/main';
6+
7+
suite("Basic sort", () => {
8+
let modeHandler: ModeHandler;
9+
10+
setup(async () => {
11+
await setupWorkspace();
12+
modeHandler = new ModeHandler();
13+
});
14+
15+
teardown(cleanUpWorkspace);
16+
17+
test("Sort whole file, asc", async () => {
18+
await modeHandler.handleMultipleKeyEvents(['i', 'b', '<Esc>', 'o', 'a', '<Esc>', 'o', 'c', '<Esc>']);
19+
await runCmdLine("sort", modeHandler);
20+
21+
assertEqualLines([
22+
"a",
23+
"b",
24+
"c"
25+
]);
26+
});
27+
28+
test("Sort whole file, dsc", async () => {
29+
await modeHandler.handleMultipleKeyEvents(['i', 'b', '<Esc>', 'o', 'a', '<Esc>', 'o', 'c', '<Esc>']);
30+
await runCmdLine("sort!", modeHandler);
31+
32+
assertEqualLines([
33+
"c",
34+
"b",
35+
"a"
36+
]);
37+
});
38+
39+
test("Sort range, asc", async () => {
40+
await modeHandler.handleMultipleKeyEvents(['i', 'b', '<Esc>', 'o', 'd', '<Esc>', 'o', 'a', '<Esc>', 'o', 'c', '<Esc>']);
41+
await runCmdLine("1,3sort", modeHandler);
42+
43+
assertEqualLines([
44+
"a",
45+
"b",
46+
"d",
47+
"c"
48+
]);
49+
});
50+
51+
test("Sort range, dsc", async () => {
52+
await modeHandler.handleMultipleKeyEvents(['i', 'b', '<Esc>', 'o', 'd', '<Esc>', 'o', 'a', '<Esc>', 'o', 'c', '<Esc>']);
53+
await runCmdLine("2,4sort!", modeHandler);
54+
55+
assertEqualLines([
56+
"b",
57+
"d",
58+
"c",
59+
"a"
60+
]);
61+
});
62+
});

0 commit comments

Comments
 (0)