Skip to content

Commit 6ff34bf

Browse files
abogoyavlenskyavli
authored andcommitted
Use VS Code built-in provider for code formatting
1 parent b7b8d03 commit 6ff34bf

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

package.json

-4
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@
9595
{
9696
"command": "clojureVSCode.stopDisconnectNRepl",
9797
"title": "Clojure: Disconnect from nREPL"
98-
},
99-
{
100-
"command": "clojureVSCode.formatFile",
101-
"title": "Clojure: Format file or selection"
10298
}
10399
],
104100
"views": {

src/clojureFormat.ts

+37-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as vscode from 'vscode';
22

33
import { cljConnection } from './cljConnection';
4-
import { cljParser } from './cljParser';
54
import { nreplClient } from './nreplClient';
65

76
function slashEscape(contents: string) {
@@ -18,15 +17,14 @@ function slashUnescape(contents: string) {
1817
});
1918
}
2019

21-
export const formatFile = (textEditor: vscode.TextEditor, edit?: vscode.TextEditorEdit): void => {
20+
21+
export const formatFile = (document: vscode.TextDocument, range: vscode.Range): Promise<vscode.TextEdit[] | undefined> => {
2222

2323
if (!cljConnection.isConnected()) {
24-
vscode.window.showErrorMessage("Formatting functions don't work, connect to nREPL first.");
25-
return;
24+
return Promise.reject("Formatting functions don't work, connect to nREPL first.");
2625
}
2726

28-
const selection = textEditor.selection;
29-
let contents: string = selection.isEmpty ? textEditor.document.getText() : textEditor.document.getText(selection);
27+
let contents: string = document.getText(range);
3028

3129
// Escaping the string before sending it to nREPL
3230
contents = slashEscape(contents)
@@ -41,43 +39,60 @@ export const formatFile = (textEditor: vscode.TextEditor, edit?: vscode.TextEdit
4139
// time it is called. I have no idea what causes this behavior so I decided to put the require
4240
// statement right here - don't think it does any harm. If someone knows how to fix it
4341
// please send a pull request with a fix.
44-
nreplClient.evaluate(`(require 'cljfmt.core) (cljfmt.core/reformat-string "${contents}" ${cljfmtParams})`)
42+
return nreplClient.evaluate(`(require 'cljfmt.core) (cljfmt.core/reformat-string "${contents}" ${cljfmtParams})`)
4543
.then(value => {
4644
if ('ex' in value[0]) {
47-
vscode.window.showErrorMessage(value[1].err);
48-
return;
45+
return Promise.reject(value[1].err);
4946
};
5047
if (('value' in value[1]) && (value[1].value != 'nil')) {
5148
let new_content: string = value[1].value.slice(1, -1);
5249
new_content = slashUnescape(new_content);
53-
let selection = textEditor.selection;
54-
if (textEditor.selection.isEmpty) {
55-
const lines: string[] = textEditor.document.getText().split(/\r?\n/g);
56-
const lastChar: number = lines[lines.length - 1].length;
57-
selection = new vscode.Selection(new vscode.Position(0, 0), new vscode.Position(textEditor.document.lineCount, lastChar));
58-
}
59-
textEditor.edit(editBuilder => {
60-
editBuilder.replace(selection, new_content);
61-
});
50+
return Promise.resolve([vscode.TextEdit.replace(range, new_content)]);
6251
};
6352
});
6453
}
6554

55+
6656
export const maybeActivateFormatOnSave = () => {
6757
vscode.workspace.onWillSaveTextDocument(e => {
6858
const document = e.document;
6959
if (document.languageId !== "clojure") {
7060
return;
7161
}
7262
let textEditor = vscode.window.activeTextEditor;
73-
if (!textEditor) {
63+
if (!textEditor || textEditor.document.isClosed) {
7464
return
7565
}
7666
let editorConfig = vscode.workspace.getConfiguration('editor');
77-
const globalEditorFormatOnSave = editorConfig && editorConfig.has('formatOnSave') && editorConfig.get('formatOnSave') === true;
78-
let clojureConfig = vscode.workspace.getConfiguration('clojureVSCode');
67+
const globalEditorFormatOnSave = editorConfig && editorConfig.has('formatOnSave') && editorConfig.get('formatOnSave') === true,
68+
clojureConfig = vscode.workspace.getConfiguration('clojureVSCode'),
69+
currentText = textEditor.document.getText(),
70+
lastLine = textEditor.document.lineCount - 1,
71+
lastPosition = textEditor.document.lineAt(lastLine).range.end,
72+
range = new vscode.Range(new vscode.Position(0, 0), lastPosition);
73+
7974
if ((clojureConfig.formatOnSave || globalEditorFormatOnSave) && textEditor.document === document) {
80-
formatFile(textEditor, undefined);
75+
formatFile(textEditor.document, range).then(value => {
76+
if (textEditor && value && currentText != value[0].newText) {
77+
textEditor.edit(editBuilder => {
78+
editBuilder.replace(range, value[0].newText);
79+
});
80+
}
81+
}).catch(reason => {
82+
vscode.window.showErrorMessage(reason);
83+
});
8184
}
8285
});
8386
}
87+
88+
89+
export class ClojureRangeFormattingEditProvider implements vscode.DocumentRangeFormattingEditProvider {
90+
provideDocumentRangeFormattingEdits(
91+
document: vscode.TextDocument,
92+
range: vscode.Range,
93+
options: vscode.FormattingOptions,
94+
token: vscode.CancellationToken): vscode.ProviderResult<vscode.TextEdit[]> {
95+
96+
return formatFile(document, range);
97+
}
98+
}

src/clojureMain.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ClojureSignatureProvider } from './clojureSignature';
1010
import { JarContentProvider } from './jarContentProvider';
1111
import { nreplController } from './nreplController';
1212
import { cljConnection } from './cljConnection';
13-
import { formatFile, maybeActivateFormatOnSave } from './clojureFormat';
13+
import { ClojureRangeFormattingEditProvider, maybeActivateFormatOnSave } from './clojureFormat';
1414

1515
import { buildTestProvider } from './testRunner'
1616

@@ -39,7 +39,7 @@ export function activate(context: vscode.ExtensionContext) {
3939
vscode.commands.registerCommand('clojureVSCode.runAllTests', () => runAllTests(evaluationResultChannel, testResultDataProvidier));
4040
vscode.window.registerTreeDataProvider('clojure', testResultDataProvidier);
4141

42-
vscode.commands.registerTextEditorCommand('clojureVSCode.formatFile', formatFile);
42+
context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(CLOJURE_MODE, new ClojureRangeFormattingEditProvider()));
4343

4444
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(CLOJURE_MODE, new ClojureCompletionItemProvider(), '.', '/'));
4545
context.subscriptions.push(vscode.languages.registerDefinitionProvider(CLOJURE_MODE, new ClojureDefinitionProvider()));

0 commit comments

Comments
 (0)