import { Disposable, Event } from 'vscode';
import { combinedDisposable } from './disposableUtils';
/**
* Wrap an event in an event that only fire when a certain condition is true
* @param event The event that will be wrapped
* @param filter A predicate function whhich will be run on the event result to determine if the event should be propagated.
*/
export function filterEvent<T> (event: Event<T>, filter: (e: T) => boolean): Event<T> {
return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
}
/**
* Returns an event that fires when any of the given events fire
* @param events An array of events that will trigger the returned event
*/
export function anyEvent<T> (...events: Array<Event<T>>): Event<T> {
return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => {
const result = combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i))));
if (disposables) {
disposables.push(result);
}
return result;
};
}
/**
* Create a new event that wraps an event and fires the first time the wrapped event
* fires, then disposes of itself.
* @param event The event to wrap.
*/
export function onceEvent<T> (event: Event<T>): Event<T> {
return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => {
const result = event(e => {
result.dispose();
return listener.call(thisArgs, e);
}, null, disposables);
return result;
};
}
/**
* Wraps an event in an event that prevents it from firing too frequently
* @param event The event that will be wrapped
* @param delay The minimum amount of time between event fires
*/
export function debounceEvent<T> (event: Event<T>, delay: number): Event<T> {
return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => {
let timer: NodeJS.Timer;
return event(e => {
clearTimeout(timer);
timer = setTimeout(() => listener.call(thisArgs, e), delay);
}, null, disposables);
};
}
/**
* Convert an event into an awaitable promise
* @param event The event that can be awaited
*/
export async function eventToPromise<T> (event: Event<T>): Promise<T> {
return await new Promise<T>(resolve => onceEvent(event)(resolve));
}