Skip to content

Commit

Permalink
fix #3338 Format Document on save
Browse files Browse the repository at this point in the history
Format on Save is only available when the preference autoSave is "OFF"
and the preference 'editor.formatOnSave' is "true"

Signed-off-by: Jacques Bouthillier <jacques.bouthillier@ericsson.com>
  • Loading branch information
lmcbout committed Nov 26, 2018
1 parent 5d9f8d6 commit 5d64706
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 22 deletions.
6 changes: 6 additions & 0 deletions packages/editor/src/browser/editor-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ export const editorPreferenceSchema: PreferenceSchema = {
'default': false,
'description': 'Enable auto indentation adjustment.'
},
'editor.formatOnSave': {
'type': 'boolean',
'default': false,
'description': 'Enable format on save when the autoSave preference is off.'
},
'editor.formatOnType': {
'type': 'boolean',
'default': false,
Expand Down Expand Up @@ -504,6 +509,7 @@ export interface EditorConfiguration {
'editor.autoClosingBrackets'?: boolean
'editor.autoIndent'?: boolean
'editor.formatOnType'?: boolean
'editor.formatOnSave'?: boolean
'editor.formatOnPaste'?: boolean
'editor.dragAndDrop'?: boolean
'editor.suggestOnTriggerCharacters'?: boolean
Expand Down
63 changes: 41 additions & 22 deletions packages/editorconfig/src/browser/editorconfig-document-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import { injectable, inject, postConstruct } from 'inversify';
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
import { TextDocumentSaveReason } from '@theia/languages/lib/browser';
import { EditorManager, EditorWidget, TextEditor } from '@theia/editor/lib/browser';
import { EditorManager, EditorWidget, TextEditor, EditorPreferences } from '@theia/editor/lib/browser';
import { EditorconfigService } from '../common/editorconfig-interface';
import { KnownProps } from 'editorconfig';
import { CommandService } from '@theia/core';

@injectable()
export class EditorconfigDocumentManager {
Expand All @@ -29,12 +30,18 @@ export class EditorconfigDocumentManager {
CRLF: '\r\n'
};

@inject(CommandService)
protected readonly commandService: CommandService;

@inject(EditorManager)
protected readonly editorManager: EditorManager;

@inject(EditorconfigService)
protected readonly editorconfigServer: EditorconfigService;

@inject(EditorPreferences)
protected readonly editorPreferences: EditorPreferences;

private properties: { [file: string]: KnownProps } = {};

@postConstruct()
Expand Down Expand Up @@ -62,25 +69,18 @@ export class EditorconfigDocumentManager {
const monacoEditor = MonacoEditor.get(editorWidget);
if (monacoEditor) {
monacoEditor.document.onWillSaveModel(event => {
event.waitUntil(new Promise<monaco.editor.IIdentifiedSingleEditOperation[]>(resolve => {
event.waitUntil(new Promise<monaco.editor.IIdentifiedSingleEditOperation[]>(async resolve => {
const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
const uri = monacoEditor.uri.toString();
const properties = this.properties[uri];

const edits = [];
edits.push(...this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));
// actually format the document (doesn't return an operation)
await this.formatDocument(monacoEditor);

// gather operations
edits.push(...await this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));
const edit = this.getEditInsertingFinalNewLine(monacoEditor, properties);
if (edit) {
edits.push(edit);

// get current cursor position
const cursor = monacoEditor.cursor;

// and then restore it after resolving the promise
setTimeout(() => {
monacoEditor.cursor = cursor;
}, 0);
}
if (edit) { edits.push(edit); }

resolve(edits);
}));
Expand Down Expand Up @@ -206,10 +206,11 @@ export class EditorconfigDocumentManager {
* preceding newline characters and false to ensure it doesn't.
*/
ensureTrimTrailingWhitespace(editor: MonacoEditor, properties: KnownProps): void {
const edits = this.getEditsTrimmingTrailingWhitespaces(editor, properties);
if (edits.length > 0) {
editor.document.textEditorModel.applyEdits(edits);
}
this.getEditsTrimmingTrailingWhitespaces(editor, properties).then(edits => {
if (edits.length > 0) {
editor.document.textEditorModel.applyEdits(edits);
}
});
}

/**
Expand All @@ -218,14 +219,16 @@ export class EditorconfigDocumentManager {
* @param editor editor
* @param properties editorconfig properties
*/
private getEditsTrimmingTrailingWhitespaces(editor: MonacoEditor, properties: KnownProps, saveReason?: TextDocumentSaveReason): monaco.editor.IIdentifiedSingleEditOperation[] {
private async getEditsTrimmingTrailingWhitespaces(
editor: MonacoEditor, properties: KnownProps, saveReason?: TextDocumentSaveReason
): Promise<monaco.editor.IIdentifiedSingleEditOperation[]> {
const edits = [];

if (MonacoEditor.get(this.editorManager.activeEditor) === editor) {
const trimReason = (saveReason !== TextDocumentSaveReason.Manual) ? 'auto-save' : undefined;
editor.commandService.executeCommand('editor.action.trimTrailingWhitespace', {
await new Promise((resolve, reject) => editor.commandService.executeCommand('editor.action.trimTrailingWhitespace', {
reason: trimReason
});
}).then(resolve, reject));
return [];
}

Expand Down Expand Up @@ -296,4 +299,20 @@ export class EditorconfigDocumentManager {
return undefined;
}

/**
* Format the document when the preference "editor.formatOnSave" is set and the
* "editor.autoSave" is set to "OFF". Only re-format when saving is done manually.
*
* @param editor editor
*/
private async formatDocument(editor: MonacoEditor): Promise<void> {
if (MonacoEditor.get(this.editorManager.activeEditor) === editor) {
if (this.editorPreferences['editor.formatOnSave'] && (this.editorPreferences['editor.autoSave']) === 'off') {
await new Promise((resolve, reject) => {
editor.commandService.executeCommand('editor.action.formatDocument').then(resolve, reject);
});
}
}
}

}

0 comments on commit 5d64706

Please sign in to comment.