KeyWatcher
keyの変換にはvim-like-key-notationを使った
$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/takker/KeyWatcher/mod.ts
code:mod.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
import { textInput } from "../scrapbox-userscript-std/dom.ts";
import { promisify } from "../async-lib/mod.ts";
import { stringify } from "../vim-like-key-notation/mod.ts";
export const KeyWatcher = class {
private sequence = "";
private adaptor = promisify<
KeyboardEvent | CompositionEvent
({ maxQueued: 0 });
private keyWatcher = this.adaptor0;
private handleKey = this.adaptor1;
private handleKeydown = (e: KeyboardEvent) => {
if (e.isComposing) return;
this.handleKey(e);
};
constructor(private dom: HTMLElement | Document | (typeof globalThis) = globalThis) {
this.dom.addEventListener("keydown", this.handleKeydown as EventListener);
textInput()!.addEventListener("compositionstart", this.handleKey);
}
public reset(): void {
this.sequence = "";
}
private dispose (): void {
this.dom.removeEventListener("keydown", this.handleKeydown as EventListener);
textInput()!.removeEventListener("compositionstart", this.handleKey);
};
public async* listen(): AsyncGenerator<string> {
while (true) {
const event = await this.keyWatcher();
if (event instanceof KeyboardEvent) {
this.sequence += stringify(event);
} else {
// 入力が確定したときのみ取得する
const { data } = await new Promise<CompositionEvent>((resolve) => {
textInput()!.addEventListener("compositionend", resolve, { once: true });
});
this.sequence += data;
}
yield this.sequence;
}
}
};
#2024-05-24 18:05:58
#2023-11-01