Merge remote-tracking branch 'origin/master' into keybindings-service
This commit is contained in:
commit
38e0840fb4
5 changed files with 67 additions and 78 deletions
|
@ -17,6 +17,7 @@ import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions
|
||||||
import { getSnippetController } from 'vs/editor/contrib/snippet/common/snippet';
|
import { getSnippetController } from 'vs/editor/contrib/snippet/common/snippet';
|
||||||
import { Context as SuggestContext } from 'vs/editor/contrib/suggest/common/suggest';
|
import { Context as SuggestContext } from 'vs/editor/contrib/suggest/common/suggest';
|
||||||
import { SuggestModel } from '../common/suggestModel';
|
import { SuggestModel } from '../common/suggestModel';
|
||||||
|
import { CompletionItem } from '../common/completionModel';
|
||||||
import { SuggestWidget } from './suggestWidget';
|
import { SuggestWidget } from './suggestWidget';
|
||||||
|
|
||||||
export class SuggestController implements IEditorContribution {
|
export class SuggestController implements IEditorContribution {
|
||||||
|
@ -29,18 +30,23 @@ export class SuggestController implements IEditorContribution {
|
||||||
private model: SuggestModel;
|
private model: SuggestModel;
|
||||||
private widget: SuggestWidget;
|
private widget: SuggestWidget;
|
||||||
private triggerCharacterListeners: IDisposable[];
|
private triggerCharacterListeners: IDisposable[];
|
||||||
private toDispose: IDisposable[];
|
private toDispose: IDisposable[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private editor: ICodeEditor,
|
private editor: ICodeEditor,
|
||||||
@IInstantiationService instantiationService: IInstantiationService
|
@IInstantiationService instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
this.model = new SuggestModel(this.editor);
|
this.model = new SuggestModel(this.editor);
|
||||||
this.widget = instantiationService.createInstance(SuggestWidget, this.editor, this.model);
|
this.widget = instantiationService.createInstance(SuggestWidget, this.editor);
|
||||||
|
|
||||||
|
this.toDispose.push(this.model.onDidTrigger(e => this.widget.showTriggered(e)));
|
||||||
|
this.toDispose.push(this.model.onDidSuggest(e => this.widget.showSuggestions(e)));
|
||||||
|
this.toDispose.push(this.model.onDidCancel(e => this.widget.showDidCancel(e)));
|
||||||
|
|
||||||
|
this.toDispose.push(this.widget.onDidSelect(this.onDidSelectItem, this));
|
||||||
|
|
||||||
this.triggerCharacterListeners = [];
|
this.triggerCharacterListeners = [];
|
||||||
|
|
||||||
this.toDispose = [];
|
|
||||||
this.toDispose.push(editor.onDidChangeConfiguration(() => this.update()));
|
this.toDispose.push(editor.onDidChangeConfiguration(() => this.update()));
|
||||||
this.toDispose.push(editor.onDidChangeModel(() => this.update()));
|
this.toDispose.push(editor.onDidChangeModel(() => this.update()));
|
||||||
this.toDispose.push(editor.onDidChangeModelMode(() => this.update()));
|
this.toDispose.push(editor.onDidChangeModelMode(() => this.update()));
|
||||||
|
@ -69,6 +75,15 @@ export class SuggestController implements IEditorContribution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onDidSelectItem(item: CompletionItem): void {
|
||||||
|
if (!item) {
|
||||||
|
this.model.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {overwriteBefore, overwriteAfter} = item.suggestion;
|
||||||
|
this.model.accept(item.suggestion, overwriteBefore, overwriteAfter);
|
||||||
|
}
|
||||||
|
|
||||||
private update(): void {
|
private update(): void {
|
||||||
|
|
||||||
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
|
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
|
||||||
|
@ -126,7 +141,8 @@ export class SuggestController implements IEditorContribution {
|
||||||
|
|
||||||
acceptSelectedSuggestion(): void {
|
acceptSelectedSuggestion(): void {
|
||||||
if (this.widget) {
|
if (this.widget) {
|
||||||
this.widget.acceptSelectedSuggestion();
|
const item = this.widget.getFocusedItem();
|
||||||
|
this.onDidSelectItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import 'vs/css!./suggest';
|
import 'vs/css!./suggest';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import * as strings from 'vs/base/common/strings';
|
import * as strings from 'vs/base/common/strings';
|
||||||
|
import Event, { Emitter } from 'vs/base/common/event';
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
@ -23,7 +24,7 @@ import { IConfigurationChangedEvent } from 'vs/editor/common/editorCommon';
|
||||||
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||||
import { Context as SuggestContext } from '../common/suggest';
|
import { Context as SuggestContext } from '../common/suggest';
|
||||||
import { CompletionItem, CompletionModel } from '../common/completionModel';
|
import { CompletionItem, CompletionModel } from '../common/completionModel';
|
||||||
import { ICancelEvent, ISuggestEvent, ITriggerEvent, SuggestModel } from '../common/suggestModel';
|
import { ICancelEvent, ISuggestEvent, ITriggerEvent } from '../common/suggestModel';
|
||||||
import { alert } from 'vs/base/browser/ui/aria/aria';
|
import { alert } from 'vs/base/browser/ui/aria/aria';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
|
||||||
|
@ -323,13 +324,14 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
private suggestWidgetMultipleSuggestions: IContextKey<boolean>;
|
private suggestWidgetMultipleSuggestions: IContextKey<boolean>;
|
||||||
private suggestionSupportsAutoAccept: IContextKey<boolean>;
|
private suggestionSupportsAutoAccept: IContextKey<boolean>;
|
||||||
|
|
||||||
|
private onDidSelectEmitter = new Emitter<CompletionItem>();
|
||||||
|
|
||||||
private editorBlurTimeout: TPromise<void>;
|
private editorBlurTimeout: TPromise<void>;
|
||||||
private showTimeout: TPromise<void>;
|
private showTimeout: TPromise<void>;
|
||||||
private toDispose: IDisposable[];
|
private toDispose: IDisposable[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private editor: ICodeEditor,
|
private editor: ICodeEditor,
|
||||||
private model: SuggestModel,
|
|
||||||
@ITelemetryService private telemetryService: ITelemetryService,
|
@ITelemetryService private telemetryService: ITelemetryService,
|
||||||
@IContextKeyService contextKeyService: IContextKeyService,
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
@IInstantiationService instantiationService: IInstantiationService
|
@IInstantiationService instantiationService: IInstantiationService
|
||||||
|
@ -361,10 +363,7 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
editor.onDidBlurEditorText(() => this.onEditorBlur()),
|
editor.onDidBlurEditorText(() => this.onEditorBlur()),
|
||||||
this.list.onSelectionChange(e => this.onListSelection(e)),
|
this.list.onSelectionChange(e => this.onListSelection(e)),
|
||||||
this.list.onFocusChange(e => this.onListFocus(e)),
|
this.list.onFocusChange(e => this.onListFocus(e)),
|
||||||
this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged()),
|
this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged())
|
||||||
this.model.onDidTrigger(e => this.onDidTrigger(e)),
|
|
||||||
this.model.onDidSuggest(e => this.onDidSuggest(e)),
|
|
||||||
this.model.onDidCancel(e => this.onDidCancel(e))
|
|
||||||
];
|
];
|
||||||
|
|
||||||
this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
|
this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
|
||||||
|
@ -411,8 +410,7 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = e.elements[0];
|
const item = e.elements[0];
|
||||||
const {overwriteBefore, overwriteAfter} = item.suggestion;
|
this.onDidSelectEmitter.fire(item);
|
||||||
this.model.accept(item.suggestion, overwriteBefore, overwriteAfter);
|
|
||||||
|
|
||||||
alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.suggestion.label));
|
alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.suggestion.label));
|
||||||
|
|
||||||
|
@ -544,7 +542,11 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDidTrigger(e: ITriggerEvent) {
|
get onDidSelect():Event<CompletionItem> {
|
||||||
|
return this.onDidSelectEmitter.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
showTriggered(e: ITriggerEvent) {
|
||||||
if (this.state !== State.Hidden) {
|
if (this.state !== State.Hidden) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -559,7 +561,7 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDidSuggest(e: ISuggestEvent): void {
|
showSuggestions(e: ISuggestEvent): void {
|
||||||
if (this.loadingTimeout) {
|
if (this.loadingTimeout) {
|
||||||
clearTimeout(this.loadingTimeout);
|
clearTimeout(this.loadingTimeout);
|
||||||
this.loadingTimeout = null;
|
this.loadingTimeout = null;
|
||||||
|
@ -623,7 +625,7 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDidCancel(e: ICancelEvent) {
|
showDidCancel(e: ICancelEvent) {
|
||||||
if (this.loadingTimeout) {
|
if (this.loadingTimeout) {
|
||||||
clearTimeout(this.loadingTimeout);
|
clearTimeout(this.loadingTimeout);
|
||||||
this.loadingTimeout = null;
|
this.loadingTimeout = null;
|
||||||
|
@ -694,22 +696,12 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptSelectedSuggestion(): boolean {
|
getFocusedItem(): CompletionItem {
|
||||||
switch (this.state) {
|
if (this.state !== State.Hidden
|
||||||
case State.Hidden:
|
&& this.state !== State.Empty
|
||||||
return false;
|
&& this.state !== State.Loading) {
|
||||||
case State.Empty:
|
|
||||||
return false;
|
return this.list.getFocusedElements()[0];
|
||||||
case State.Loading:
|
|
||||||
return !this.isAuto;
|
|
||||||
default:
|
|
||||||
const focus = this.list.getFocusedElements()[0];
|
|
||||||
if (focus) {
|
|
||||||
this.list.setSelection(this.completionModel.items.indexOf(focus));
|
|
||||||
} else {
|
|
||||||
this.model.cancel();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +744,7 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||||
if (this.state === State.Details) {
|
if (this.state === State.Details) {
|
||||||
this.toggleDetails();
|
this.toggleDetails();
|
||||||
} else {
|
} else {
|
||||||
this.model.cancel();
|
this.showDidCancel({ retrigger: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ export class FileTracker implements IWorkbenchContribution {
|
||||||
let before = e.getBefore();
|
let before = e.getBefore();
|
||||||
let after = e.getAfter();
|
let after = e.getAfter();
|
||||||
|
|
||||||
this.handleMovedFileInVisibleEditors(before ? before.resource : null, after ? after.resource : null, after ? after.mime : null);
|
this.handleMovedFileInOpenedEditors(before ? before.resource : null, after ? after.resource : null, after ? after.mime : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose all known inputs passed on resource if deleted or moved
|
// Dispose all known inputs passed on resource if deleted or moved
|
||||||
|
@ -279,47 +279,29 @@ export class FileTracker implements IWorkbenchContribution {
|
||||||
return input instanceof FileEditorInput && (<FileEditorInput>input).getResource().toString() === resource.toString();
|
return input instanceof FileEditorInput && (<FileEditorInput>input).getResource().toString() === resource.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleMovedFileInVisibleEditors(oldResource: URI, newResource: URI, mimeHint?: string): void {
|
private handleMovedFileInOpenedEditors(oldResource: URI, newResource: URI, mimeHint?: string): void {
|
||||||
let stacks = this.editorGroupService.getStacksModel();
|
const stacks = this.editorGroupService.getStacksModel();
|
||||||
let editors = this.editorService.getVisibleEditors();
|
stacks.groups.forEach(group => {
|
||||||
editors.forEach(editor => {
|
group.getEditors().forEach(input => {
|
||||||
let group = stacks.groupAt(editor.position);
|
if (input instanceof FileEditorInput) {
|
||||||
let input = editor.input;
|
const resource = input.getResource();
|
||||||
if (input instanceof DiffEditorInput) {
|
|
||||||
input = (<DiffEditorInput>input).modifiedInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inputResource: URI;
|
// Update Editor if file (or any parent of the input) got renamed or moved
|
||||||
if (input instanceof FileEditorInput) {
|
if (paths.isEqualOrParent(resource.fsPath, oldResource.fsPath)) {
|
||||||
inputResource = (<FileEditorInput>input).getResource();
|
let reopenFileResource: URI;
|
||||||
}
|
if (oldResource.toString() === resource.toString()) {
|
||||||
|
reopenFileResource = newResource; // file got moved
|
||||||
|
} else {
|
||||||
|
let index = resource.fsPath.indexOf(oldResource.fsPath);
|
||||||
|
reopenFileResource = URI.file(paths.join(newResource.fsPath, resource.fsPath.substr(index + oldResource.fsPath.length + 1))); // parent folder got moved
|
||||||
|
}
|
||||||
|
|
||||||
// Editor Input with associated Resource
|
// Reopen
|
||||||
if (inputResource) {
|
|
||||||
|
|
||||||
// Update Editor if file (or any parent of the input) got renamed or moved
|
|
||||||
let updateInput = false;
|
|
||||||
if (paths.isEqualOrParent(inputResource.fsPath, oldResource.fsPath)) {
|
|
||||||
updateInput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do update from move
|
|
||||||
if (updateInput) {
|
|
||||||
let reopenFileResource: URI;
|
|
||||||
if (oldResource.toString() === inputResource.toString()) {
|
|
||||||
reopenFileResource = newResource;
|
|
||||||
} else {
|
|
||||||
let index = inputResource.fsPath.indexOf(oldResource.fsPath);
|
|
||||||
reopenFileResource = URI.file(paths.join(newResource.fsPath, inputResource.fsPath.substr(index + oldResource.fsPath.length + 1))); // update the path by changing the old path value to the new one
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reopen File Input
|
|
||||||
if (input instanceof FileEditorInput) {
|
|
||||||
const editorInput = this.instantiationService.createInstance(FileEditorInput, reopenFileResource, mimeHint || MIME_UNKNOWN, void 0);
|
const editorInput = this.instantiationService.createInstance(FileEditorInput, reopenFileResource, mimeHint || MIME_UNKNOWN, void 0);
|
||||||
this.editorService.openEditor(editorInput, { preserveFocus: true, pinned: group.isPinned(input), index: group.indexOf(input) }, editor.position).done(null, errors.onUnexpectedError);
|
this.editorService.openEditor(editorInput, { preserveFocus: true, pinned: group.isPinned(input), index: group.indexOf(input), inactive: !group.isActive(input) }, stacks.positionOfGroup(group)).done(null, errors.onUnexpectedError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +340,7 @@ export class FileTracker implements IWorkbenchContribution {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleDeleteOrMove(resource: URI, movedTo?: URI): void {
|
public handleDeleteOrMove(resource: URI, movedTo?: URI): void {
|
||||||
if (this.textFileService.isDirty(resource)) {
|
if (this.textFileService.isDirty(resource)) {
|
||||||
return; // never dispose dirty resources from a delete
|
return; // never dispose dirty resources from a delete
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,11 +164,11 @@ suite('Files - FileEditorInput', () => {
|
||||||
let sameOtherInput = instantiationService.createInstance(FileEditorInput, toResource('/fooss5/bar/file2.js'), 'text/javascript', void 0);
|
let sameOtherInput = instantiationService.createInstance(FileEditorInput, toResource('/fooss5/bar/file2.js'), 'text/javascript', void 0);
|
||||||
return editorService.resolveEditorModel(inputToResolve).then(function (resolved) {
|
return editorService.resolveEditorModel(inputToResolve).then(function (resolved) {
|
||||||
return editorService.resolveEditorModel(sameOtherInput).then(function (resolved) {
|
return editorService.resolveEditorModel(sameOtherInput).then(function (resolved) {
|
||||||
(<any>tracker).handleDelete(toResource('/bar'), []);
|
tracker.handleDeleteOrMove(toResource('/bar'), []);
|
||||||
assert(!inputToResolve.isDisposed());
|
assert(!inputToResolve.isDisposed());
|
||||||
assert(!sameOtherInput.isDisposed());
|
assert(!sameOtherInput.isDisposed());
|
||||||
|
|
||||||
(<any>tracker).handleDelete(toResource('/fooss5/bar/file2.js'), []);
|
tracker.handleDeleteOrMove(toResource('/fooss5/bar/file2.js'), []);
|
||||||
|
|
||||||
assert(inputToResolve.isDisposed());
|
assert(inputToResolve.isDisposed());
|
||||||
assert(sameOtherInput.isDisposed());
|
assert(sameOtherInput.isDisposed());
|
||||||
|
@ -206,11 +206,11 @@ suite('Files - FileEditorInput', () => {
|
||||||
let sameOtherInput = instantiationService.createInstance(FileEditorInput, toResource('/foo6/bar/file.js'), 'text/javascript', void 0);
|
let sameOtherInput = instantiationService.createInstance(FileEditorInput, toResource('/foo6/bar/file.js'), 'text/javascript', void 0);
|
||||||
return editorService.resolveEditorModel(inputToResolve, true).then(function (resolved) {
|
return editorService.resolveEditorModel(inputToResolve, true).then(function (resolved) {
|
||||||
return editorService.resolveEditorModel(sameOtherInput, true).then(function (resolved) {
|
return editorService.resolveEditorModel(sameOtherInput, true).then(function (resolved) {
|
||||||
(<any>tracker).handleDelete(toResource('/bar'), []);
|
tracker.handleDeleteOrMove(toResource('/bar'), []);
|
||||||
assert(!inputToResolve.isDisposed());
|
assert(!inputToResolve.isDisposed());
|
||||||
assert(!sameOtherInput.isDisposed());
|
assert(!sameOtherInput.isDisposed());
|
||||||
|
|
||||||
(<any>tracker).handleDelete(toResource('/foo6'), []);
|
tracker.handleDeleteOrMove(toResource('/foo6'), []);
|
||||||
|
|
||||||
assert(inputToResolve.isDisposed());
|
assert(inputToResolve.isDisposed());
|
||||||
assert(sameOtherInput.isDisposed());
|
assert(sameOtherInput.isDisposed());
|
||||||
|
|
|
@ -62,10 +62,9 @@ export class TerminalPanel extends Panel {
|
||||||
if (!dimension) {
|
if (!dimension) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let activeIndex = this.terminalService.getActiveTerminalIndex();
|
this.terminalInstances.forEach((t) => {
|
||||||
if (activeIndex !== -1 && this.terminalInstances.length > 0) {
|
t.layout(dimension);
|
||||||
this.terminalInstances[this.terminalService.getActiveTerminalIndex()].layout(dimension);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getActions(): IAction[] {
|
public getActions(): IAction[] {
|
||||||
|
|
Loading…
Reference in a new issue