refactor: add promptEnd event
This commit is contained in:
parent
697d23e932
commit
6c8d6e0790
|
|
@ -60,25 +60,14 @@ export class GameHost<TState extends Record<string, unknown>> {
|
||||||
this._activePromptSchema.value = activePrompt?.schema ?? null;
|
this._activePromptSchema.value = activePrompt?.schema ?? null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap _tryCommit to update schema after commit
|
|
||||||
const originalTryCommit = this.commands._tryCommit.bind(this.commands);
|
|
||||||
(this.commands as any)._tryCommit = (input: string) => {
|
|
||||||
const result = originalTryCommit(input);
|
|
||||||
updateSchema();
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Wrap _cancel to update schema after cancel
|
|
||||||
const originalCancel = this.commands._cancel.bind(this.commands);
|
|
||||||
(this.commands as any)._cancel = (reason?: string) => {
|
|
||||||
originalCancel(reason);
|
|
||||||
updateSchema();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.commands.on('prompt', () => {
|
this.commands.on('prompt', () => {
|
||||||
updateSchema();
|
updateSchema();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.commands.on('promptEnd', () => {
|
||||||
|
updateSchema();
|
||||||
|
});
|
||||||
|
|
||||||
updateSchema();
|
updateSchema();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Command, CommandSchema } from './types';
|
import type { Command, CommandSchema } from './types';
|
||||||
import type {CommandResult, CommandRunner, CommandRunnerContext, PromptEvent} from './command-runner';
|
import type {CommandResult, CommandRunner, CommandRunnerContext, CommandRunnerEvents, PromptEvent} from './command-runner';
|
||||||
import { parseCommand } from './command-parse';
|
import { parseCommand } from './command-parse';
|
||||||
import { applyCommandSchema } from './command-validate';
|
import { applyCommandSchema } from './command-validate';
|
||||||
import { parseCommandSchema } from './schema-parse';
|
import { parseCommandSchema } from './schema-parse';
|
||||||
|
|
@ -39,7 +39,8 @@ export function getCommand<TContext>(
|
||||||
return registry.get(name);
|
return registry.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Listener = (e: PromptEvent) => void;
|
type PromptListener = (e: PromptEvent) => void;
|
||||||
|
type PromptEndListener = () => void;
|
||||||
|
|
||||||
export type CommandRunnerContextExport<TContext> = CommandRunnerContext<TContext> & {
|
export type CommandRunnerContextExport<TContext> = CommandRunnerContext<TContext> & {
|
||||||
registry: CommandRegistry<TContext>;
|
registry: CommandRegistry<TContext>;
|
||||||
|
|
@ -54,14 +55,29 @@ export function createCommandRunnerContext<TContext>(
|
||||||
registry: CommandRegistry<TContext>,
|
registry: CommandRegistry<TContext>,
|
||||||
context: TContext
|
context: TContext
|
||||||
): CommandRunnerContextExport<TContext> {
|
): CommandRunnerContextExport<TContext> {
|
||||||
const listeners = new Set<Listener>();
|
const promptListeners = new Set<PromptListener>();
|
||||||
|
const promptEndListeners = new Set<PromptEndListener>();
|
||||||
|
|
||||||
const on = (_event: 'prompt', listener: Listener) => {
|
const emitPromptEnd = () => {
|
||||||
listeners.add(listener);
|
for (const listener of promptEndListeners) {
|
||||||
|
listener();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const off = (_event: 'prompt', listener: Listener) => {
|
const on = <T extends keyof CommandRunnerEvents>(_event: T, listener: (e: CommandRunnerEvents[T]) => void) => {
|
||||||
listeners.delete(listener);
|
if (_event === 'prompt') {
|
||||||
|
promptListeners.add(listener as PromptListener);
|
||||||
|
} else {
|
||||||
|
promptEndListeners.add(listener as PromptEndListener);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const off = <T extends keyof CommandRunnerEvents>(_event: T, listener: (e: CommandRunnerEvents[T]) => void) => {
|
||||||
|
if (_event === 'prompt') {
|
||||||
|
promptListeners.delete(listener as PromptListener);
|
||||||
|
} else {
|
||||||
|
promptEndListeners.delete(listener as PromptEndListener);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let activePrompt: PromptEvent | null = null;
|
let activePrompt: PromptEvent | null = null;
|
||||||
|
|
@ -71,6 +87,7 @@ export function createCommandRunnerContext<TContext>(
|
||||||
const result = activePrompt.tryCommit(commandOrInput);
|
const result = activePrompt.tryCommit(commandOrInput);
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
activePrompt = null;
|
activePrompt = null;
|
||||||
|
emitPromptEnd();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -81,6 +98,7 @@ export function createCommandRunnerContext<TContext>(
|
||||||
if (activePrompt) {
|
if (activePrompt) {
|
||||||
activePrompt.cancel(reason);
|
activePrompt.cancel(reason);
|
||||||
activePrompt = null;
|
activePrompt = null;
|
||||||
|
emitPromptEnd();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -106,7 +124,7 @@ export function createCommandRunnerContext<TContext>(
|
||||||
};
|
};
|
||||||
activePrompt = { schema: resolvedSchema, tryCommit, cancel };
|
activePrompt = { schema: resolvedSchema, tryCommit, cancel };
|
||||||
const event: PromptEvent = { schema: resolvedSchema, tryCommit, cancel };
|
const event: PromptEvent = { schema: resolvedSchema, tryCommit, cancel };
|
||||||
for (const listener of listeners) {
|
for (const listener of promptListeners) {
|
||||||
listener(event);
|
listener(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -136,7 +154,7 @@ export function createCommandRunnerContext<TContext>(
|
||||||
get(){
|
get(){
|
||||||
if (!promptQueue) {
|
if (!promptQueue) {
|
||||||
promptQueue = new AsyncQueue();
|
promptQueue = new AsyncQueue();
|
||||||
listeners.add(async (event) => {
|
promptListeners.add(async (event) => {
|
||||||
promptQueue.push(event);
|
promptQueue.push(event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ export type PromptEvent = {
|
||||||
|
|
||||||
export type CommandRunnerEvents = {
|
export type CommandRunnerEvents = {
|
||||||
prompt: PromptEvent;
|
prompt: PromptEvent;
|
||||||
|
/** 当 prompt 结束(tryCommit 成功或 cancel)时触发 */
|
||||||
|
promptEnd: void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CommandResult<T=unknown> = {
|
export type CommandResult<T=unknown> = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue