Skip to content

Commit

Permalink
[WIP] issue #3338 Format on save
Browse files Browse the repository at this point in the history
Seems to work when only reformat is selected if
there is some extra char at end of line and
re-format, then no.
Also, may need two save to reset the dirty flag,
seems the re-format occurs after and make the file dirty again.

Signed-off-by: Jacques Bouthillier <jacques.bouthillier@ericsson.com>
  • Loading branch information
lmcbout committed Nov 22, 2018
1 parent fb5ec9a commit e6ab1cc
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 22 deletions.
66 changes: 66 additions & 0 deletions SampleAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package helloproject.actions;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;

/**
* Our sample action implements workbench action delegate.
* The action proxy will be created by the workbench and
* shown in the UI. When the user tries to use the action,
* this delegate will be created and execution will be
* delegated to it.
* @see IWorkbenchWindowActionDelegate
*/
public class SampleAction implements IWorkbenchWindowActionDelegate {
private IWorkbenchWindow window;
/**
* The constructor.
*/
public SampleAction() {

//JB add a new line
}

/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* @see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
MessageDialog.openInformation(
window.getShell(),
"HelloProject",
"Hello, Eclipse world");
}

/**
* Selection in the workbench has been changed. We
* can change the state of the 'real' action here
* if we want, but this can only happen after
* the delegate has been created.
* @see IWorkbenchWindowActionDelegate#selectionChanged
*/
public void selectionChanged(IAction action, ISelection selection) {
}

/**
* We can use this method to dispose of any system
* resources we previously allocated.
* @see IWorkbenchWindowActionDelegate#dispose
*/
public void dispose() {
}

/**
* We will cache window object in order to
* be able to provide parent shell for the message dialog.
* @see IWorkbenchWindowActionDelegate#init
*/
public void init(IWorkbenchWindow window) {
this.window = window;
}
}
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
123 changes: 101 additions & 22 deletions packages/editorconfig/src/browser/editorconfig-document-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +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 +29,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 All @@ -61,29 +67,63 @@ export class EditorconfigDocumentManager {
protected addOnSaveHandler(editorWidget: EditorWidget) {
const monacoEditor = MonacoEditor.get(editorWidget);
if (monacoEditor) {
monacoEditor.document.onDidSaveModel(event => {
// monacoEditor.document.save();
console.log(`onDidSaveModel dirty: ${monacoEditor.document.dirty}`);
});
monacoEditor.document.onWillSaveModel(event => {
console.log('onWillSaveModel should be first');
// this.formatDocument(monacoEditor).then(() => {
console.log(`------------command should have been done----------------- event: ${event}`);
event.waitUntil(new Promise<monaco.editor.IIdentifiedSingleEditOperation[]>(resolve => {
const uri = monacoEditor.uri.toString();
const properties = this.properties[uri];

const edits = [];
edits.push(...this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));

const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
// edits.push(...this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason));
const edit = this.getEditInsertingFinalNewLine(monacoEditor, properties);
if (edit) {
edits.push(edit);
return Promise.all([
this.getEditsTrimmingTrailingWhitespaces(monacoEditor, properties, event.reason),
this.formatDocument(monacoEditor)
]).then(() => {
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);
}
console.log('JB --- reformat should have been done');
return resolve(edits);
});
// return this.formatDocument(monacoEditor).then(() => {
// // if (this.editorPreferences['editor.formatOnSave']) {
// // monacoEditor.commandService.executeCommand('editor.action.formatDocument').then(() => {

// get current cursor position
const cursor = monacoEditor.cursor;
// if (edit) {
// edits.push(edit);

// and then restore it after resolving the promise
setTimeout(() => {
monacoEditor.cursor = cursor;
}, 0);
}
// // get current cursor position
// const cursor = monacoEditor.cursor;

resolve(edits);
// // and then restore it after resolving the promise
// setTimeout(() => {
// monacoEditor.cursor = cursor;
// }, 0);
// }
// console.log('JB --- reformat should have been done');
// return resolve(edits);
// });

// }

// resolve(edits);
}));
// });
});
}
}
Expand Down Expand Up @@ -206,10 +246,16 @@ 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);
}
// 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 +264,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 +344,35 @@ 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) {
// console.log(`--JB formatOnSave: ${this.editorPreferences['editor.formatOnSave']} editor.autoSave: ${this.editorPreferences['editor.autoSave']} `);
// if (this.editorPreferences['editor.formatOnSave'] && (this.editorPreferences['editor.autoSave']) === 'off') {
// await editor.commandService.executeCommand('editor.action.formatDocument', {
// aa: console.log('-----JBJB format document -------JBJB'),
// });
// } else {
// console.log('-----===== JB **NO** FORMAT on save');
// }
if (this.editorPreferences['editor.formatOnSave'] && (this.editorPreferences['editor.autoSave']) === 'off') {
await new Promise((resolve, reject) => {
editor.commandService.executeCommand('editor.action.formatDocument').then(() => {
console.log('----------------formatDocument JB----------------');
resolve();
}, () => {
console.log('command rejected');
reject();
});
});

}
}
}

}
17 changes: 17 additions & 0 deletions packages/workspace/src/browser/workspace-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ export namespace WorkspaceCommands {
category: WORKSPACE_CATEGORY,
label: 'Save Workspace As...'
};
export const LIANG_COM: Command = {
id: 'workspace:liang',
category: WORKSPACE_CATEGORY,
label: 'Run Liang Command'
};
}

@injectable()
Expand Down Expand Up @@ -293,6 +298,18 @@ export class WorkspaceCommandContribution implements CommandContribution {
}
}
}));
registry.registerCommand(WorkspaceCommands.LIANG_COM, this.newMultiUriAwareCommandHandler({
isEnabled: () => true,
isVisible: () => true,
execute: async uris =>
new Promise(resolve => {
setTimeout(() => {
console.log('Liang promise resolved');
resolve();
}, 5000);
}
)
}));
this.preferences.ready.then(() => {
registry.registerCommand(WorkspaceCommands.ADD_FOLDER, this.newMultiUriAwareCommandHandler({
isEnabled: () => this.workspaceService.isMultiRootWorkspaceOpened,
Expand Down

0 comments on commit e6ab1cc

Please sign in to comment.