Skip to content

Commit

Permalink
a prefix-based quick open handler should be initialized on each open
Browse files Browse the repository at this point in the history
Otherwise it displays outdated commands for example.

Signed-off-by: Anton Kosyakov <[email protected]>
  • Loading branch information
akosyakov committed Aug 31, 2018
1 parent eb162cb commit 4a8a1a1
Showing 1 changed file with 51 additions and 77 deletions.
128 changes: 51 additions & 77 deletions packages/core/src/browser/quick-open/prefix-quick-open-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject, postConstruct } from 'inversify';
import { injectable, inject } from 'inversify';
import { QuickOpenModel, QuickOpenItem, QuickOpenMode } from './quick-open-model';
import { QuickOpenService, QuickOpenOptions } from './quick-open-service';
import { Disposable, DisposableCollection } from '../../common/disposable';
Expand Down Expand Up @@ -129,81 +129,16 @@ export class QuickOpenHandlerRegistry implements Disposable {
}
}

/**
* The quick open model just delegates all the calls to another model depending on the used prefix.
*/
class PrefixModel implements QuickOpenModel {

/**
* Stores the current handler for the quick open widget opened in a prefix-aware mode.
* Allows to detect that another model is called.
*/
protected currentHandler: QuickOpenHandler;

constructor(
protected readonly handlers: QuickOpenHandlerRegistry,
protected readonly openService: PrefixQuickOpenService
) { }

onType(lookFor: string, acceptor: (items: QuickOpenItem[]) => void): void {
const handler = this.handlers.getHandlerOrDefault(lookFor);
if (handler === undefined) {
const items: QuickOpenItem[] = [];
items.push(new QuickOpenItem({
label: lookFor.length === 0 ? 'No default handler is registered' : `No handlers matches the prefix ${lookFor} and no default handler is registered.`
}));
acceptor(items);
} else if (handler !== this.currentHandler) {
this.onHandlerChanged(handler, lookFor);
} else {
const handlerModel = handler.getModel();
const searchValue = this.handlers.isDefaultHandler(handler) ? lookFor : lookFor.substr(handler.prefix.length);
handlerModel.onType(searchValue, items => acceptor(items));
}
}

/**
* Handles changing the currently used handler as a result of user's typing.
* @param handler quick open handler that should be used
* @param prefix value that is currently typed in the quick open widget
*/
protected async onHandlerChanged(handler: QuickOpenHandler, prefix: string): Promise<void> {
// need to notify the previous handler's model about closing the quick open widget
if (this.currentHandler) {
const closingHandler = this.currentHandler.getOptions().onClose;
if (closingHandler) {
closingHandler(true);
}
}
this.currentHandler = handler;
if (handler.init) {
await handler.init();
}
// a prefix has been changed, so the quick open widget needs to be reopened with the new options
this.openService.open(prefix);
}
}

/** Prefix-based quick open service. */
@injectable()
export class PrefixQuickOpenService {

/**
* The internal model which is used when the quick open widget is opened in handling prefix mode.
*/
protected model: QuickOpenModel;

@inject(QuickOpenHandlerRegistry)
protected readonly handlers: QuickOpenHandlerRegistry;

@inject(QuickOpenService)
protected readonly quickOpenService: QuickOpenService;

@postConstruct()
init() {
this.model = new PrefixModel(this.handlers, this);
}

/**
* Opens a quick open widget with the model that handles the known prefixes.
* @param prefix string that may contain a prefix of some of the known quick open handlers.
Expand All @@ -212,26 +147,65 @@ export class PrefixQuickOpenService {
*/
open(prefix: string): void {
const handler = this.handlers.getHandlerOrDefault(prefix);
if (handler === undefined) {
this.quickOpenService.open(this.model);
this.setCurrentHandler(prefix, handler);
}

protected toDisposeCurrent = new DisposableCollection();
protected currentHandler: QuickOpenHandler | undefined;

protected async setCurrentHandler(prefix: string, handler: QuickOpenHandler | undefined): Promise<void> {
this.toDisposeCurrent.dispose();
this.currentHandler = handler;
this.toDisposeCurrent.push(Disposable.create(() => {
const closingHandler = handler && handler.getOptions().onClose;
if (closingHandler) {
closingHandler(true);
}
}));
if (!handler) {
this.doOpen();
return;
}

if (handler.init) {
await handler.init();
}
let optionsPrefix = prefix;
// cut the prefix for a default handler
if (this.handlers.isDefaultHandler(handler) && prefix.startsWith(handler.prefix)) {
optionsPrefix = prefix.substr(handler.prefix.length);
}
const skipPrefix = this.handlers.isDefaultHandler(handler) ? 0 : handler.prefix.length;
const handlerOptions = QuickOpenOptions.resolve(handler.getOptions());
const placeholder = handlerOptions.placeholder || "Type '?' to get help on the actions you can take from here";
const options = QuickOpenOptions.resolve({
const handlerOptions = handler.getOptions();
this.doOpen({
prefix: optionsPrefix,
placeholder,
skipPrefix
}, handlerOptions);
this.quickOpenService.open(this.model, options);
placeholder: "Type '?' to get help on the actions you can take from here",
skipPrefix,
...handlerOptions
});
}

protected doOpen(options?: QuickOpenOptions): void {
this.quickOpenService.open({
onType: (lookFor, acceptor) => this.onType(lookFor, acceptor)
}, options);
}

protected onType(lookFor: string, acceptor: (items: QuickOpenItem[]) => void): void {
const handler = this.handlers.getHandlerOrDefault(lookFor);
if (handler === undefined) {
const items: QuickOpenItem[] = [];
items.push(new QuickOpenItem({
label: lookFor.length === 0 ? 'No default handler is registered' : `No handlers matches the prefix ${lookFor} and no default handler is registered.`
}));
acceptor(items);
} else if (handler !== this.currentHandler) {
this.setCurrentHandler(lookFor, handler);
} else {
const handlerModel = handler.getModel();
const searchValue = this.handlers.isDefaultHandler(handler) ? lookFor : lookFor.substr(handler.prefix.length);
handlerModel.onType(searchValue, items => acceptor(items));
}
}

}

@injectable()
Expand Down

0 comments on commit 4a8a1a1

Please sign in to comment.