提交 38e0840f 编写于 作者: A Alex Dima

Merge remote-tracking branch 'origin/master' into keybindings-service

...@@ -17,6 +17,7 @@ import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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'; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; // Update Editor if file (or any parent of the input) got renamed or moved
} if (paths.isEqualOrParent(resource.fsPath, oldResource.fsPath)) {
let reopenFileResource: URI;
let inputResource: URI; if (oldResource.toString() === resource.toString()) {
if (input instanceof FileEditorInput) { reopenFileResource = newResource; // file got moved
inputResource = (<FileEditorInput>input).getResource(); } 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 }
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 // Reopen
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 { ...@@ -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', () => { ...@@ -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', () => { ...@@ -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 { ...@@ -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[] {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册