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)); }