Skip to content

Commit

Permalink
Merge pull request #25 from 1nVitr0/feature/#24/sort-on-save
Browse files Browse the repository at this point in the history
Feature/#24/sort-on-save
  • Loading branch information
1nVitr0 authored Dec 13, 2021
2 parents dab27e8 + 971a400 commit 587bb88
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 136 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ dist
node_modules
.vscode-test/
*.vsix
**/.vscode/settings.json
51 changes: 23 additions & 28 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,27 @@
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "npm: test-watch"
}
]
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": ["${workspaceFolder}/out/test/**/*.js"],
"preLaunchTask": "npm: test-watch"
}
]
}
46 changes: 20 additions & 26 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off",
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#a82700",
"activityBar.activeBorder": "#009f25",
"activityBar.background": "#a82700",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#009f25",
"activityBarBadge.foreground": "#e7e7e7",
"statusBar.background": "#751b00",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#a82700",
"titleBar.activeBackground": "#a82700",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#a8270099",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#a82700"
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#2c665a",
"activityBar.activeBorder": "#b679c5",
"activityBar.background": "#2c665a",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#b679c5",
"activityBarBadge.foreground": "#15202b",
"sash.hoverBorder": "#2c665a",
"statusBar.background": "#1d423b",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#2d655b",
"statusBarItem.remoteBackground": "#1d423b",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#2c665a",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#2c665a99",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#2c665a"
}
6 changes: 3 additions & 3 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{
"type": "npm",
"script": "compile",
"problemMatcher": ["$ts-webpack-watch", "$tslint-webpack-watch"],
"problemMatcher": ["$ts-webpack", "$tslint-webpack"],
"isBackground": true,
"presentation": {
"reveal": "never"
Expand All @@ -15,8 +15,8 @@
},
{
"type": "npm",
"script": "test-watch",
"problemMatcher": "$tsc-watch",
"script": "watch",
"problemMatcher": ["$ts-webpack-watch", "$tslint-webpack-watch"],
"isBackground": true,
"presentation": {
"reveal": "never"
Expand Down
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ If something is already selected, the extension tries it's best to validate and

Additional features include:

- `@blocksort` markers and `source.fixAll` code actions for auto-sorting on save
- deep (multilevel) sorting for nested blocks
- "*natural*" sorting for lines containing numbers

Expand All @@ -34,6 +35,48 @@ This extension contributed the following commands:

`Sort Blocks Deep Descending (Multilevel)`: Sorts the selected code blocks in descending order, including nested blocks up to a specified depth.

## Code Actions

The extension provides the following code actions:

`source.fixAll.blocksort`: This can be executed on save to auto-sort all blocks following a `@blocksort` marker.

To enable auto Sorting, you must set the `editor.codeActionsOnSave` in your `settings.json`:
```json
{
"editor.codeActionsOnSave": {
"source.fixAll.blocksort": true
}
}
```

This will enable auto-sorting for blocks following a `@blocksort` marker.
The marker can additionally be followed by the options `asc` or `desc` to control the sorting order,
as well as a number for the sorting depth:

```js
// @blocksort asc
switch(value) {
case 1:
return 1;
case 2:
return 2;
default:
return 2;
}
```

```yaml
# @blocksort asc 9
some:
nested:
- code
- (will be
sorted:
- up to
- 9 levels)
```
## Extension Settings
This extension contributed the following settings:#
Expand All @@ -58,7 +101,7 @@ This extension contributed the following settings:#

- The automatic selection validation is fairly complicated. Some languages or edge cases might not work yet (feel free to open an issue)
- some spacings between the original blocks may not be preserved
- The extension does NOT check for code erros due to sorting
- The extension does NOT check for code errors due to sorting
- The extension assumes valid code, invalid formatting will probably result in invalid sorting
- When comments and / or decorators are involved the results may vary (the extension tries it's best, comments will stick to the lines below them)
- "Natural" sorting may break on UUID strings containing a mix of numbers, letters and/or dashes
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"block sort"
],
"activationEvents": [
"onStartupFinished",
"onCommand:blocksort.sortBlocksAsc",
"onCommand:blocksort.sortBlocksDesc",
"onCommand:blocksort.sortBlocksMultilevelAsc",
Expand Down
33 changes: 16 additions & 17 deletions src/commands/blockSort.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
import { commands, InputBoxOptions, Selection, TextEditor, TextEditorEdit, window } from 'vscode';
import BlockSortProvider from '../providers/BlockSortProvider';
import ConfigurationProvider from '../providers/ConfigurationProvider';
import { commands, InputBoxOptions, Selection, Range, TextEditor, TextEditorEdit, window } from "vscode";
import BlockSortProvider from "../providers/BlockSortProvider";
import ConfigurationProvider from "../providers/ConfigurationProvider";
import FormattingProvider from "../providers/FormattingProvider";

export function blockSort(
editor: TextEditor,
editor: TextEditor | undefined,
editBuilder: TextEditorEdit,
sortFunction: (a: string, b: string) => number,
sortChildren = 0
) {
if (!window.activeTextEditor) return;
const { document, selection } = window.activeTextEditor;
if (!editor) editor = window.activeTextEditor;
if (!editor) return;

const blockSort = new BlockSortProvider(document);
const range = blockSort.expandSelection(selection);
const blocks = blockSort.getBlocks(range);
const sorted = blockSort.sortBlocks(blocks, sortFunction, sortChildren);
const { document, selection } = editor;

editor.selection = new Selection(range.start, range.end);
editBuilder.replace(range, sorted.join('\n'));
const edit = FormattingProvider.getBlockSortEdit(document, selection, { sortFunction, sortChildren });
editBuilder.replace(edit.range, edit.newText);
editor.selection = new Selection(edit.range.start, edit.range.end);
}

function blockSortMultilevel(sortFunction: (a: string, b: string) => number) {
const defaultDepth = ConfigurationProvider.getDefaultMultilevelDepth();
if (!ConfigurationProvider.getAskForMultilevelDepth())
return commands.executeCommand('blocksort._sortBlocks', sortFunction, defaultDepth);
return commands.executeCommand("blocksort._sortBlocks", sortFunction, defaultDepth);

let options: InputBoxOptions = {
prompt: 'Indentation Depth: ',
placeHolder: '(number)',
prompt: "Indentation Depth: ",
placeHolder: "(number)",
value: defaultDepth.toString(),
validateInput: (value) => (/\-?\d+/.test(value) ? null : 'Only integer values allowed. Use -1 for infinite depth'),
validateInput: (value) => (/\-?\d+/.test(value) ? null : "Only integer values allowed. Use -1 for infinite depth"),
};

window.showInputBox(options).then((value) => {
if (value === undefined) return;
commands.executeCommand('blocksort._sortBlocks', sortFunction, parseInt(value));
commands.executeCommand("blocksort._sortBlocks", sortFunction, parseInt(value));
});
}

Expand Down
14 changes: 14 additions & 0 deletions src/contribute/formattingActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { languages } from "vscode";
import BlockSortActionProvider from "../providers/BlockSortActionProvider";
import FormattingProvider from "../providers/FormattingProvider";

export default function contributeFormattingActions() {
const formattingProvider = new FormattingProvider();
const codeActionsProvider = new BlockSortActionProvider(formattingProvider);
return [
languages.registerDocumentFormattingEditProvider("*", formattingProvider),
languages.registerDocumentRangeFormattingEditProvider("*", formattingProvider),
languages.registerCodeLensProvider("*", codeActionsProvider),
languages.registerCodeActionsProvider("*", codeActionsProvider),
];
}
7 changes: 4 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ExtensionContext } from 'vscode';
import contributeCommands from './contribute/commands';
import { ExtensionContext } from "vscode";
import contributeFormattingActions from "./contribute/formattingActions";
import contributeCommands from "./contribute/commands";

export function activate(context: ExtensionContext) {
context.subscriptions.push(...contributeCommands());
context.subscriptions.push(...contributeCommands(), ...contributeFormattingActions());
}
Loading

0 comments on commit 587bb88

Please sign in to comment.