From c01c49a992a477d41abe193e56e50f61e5429b62 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 16 Jan 2024 13:26:32 +0900 Subject: [PATCH 1/5] Load sources as module --- denops/skkeleton/dictionary.ts | 77 +++++++++++++------ denops/skkeleton/dictionary_test.ts | 38 +-------- denops/skkeleton/main.ts | 4 +- denops/skkeleton/sources/deno_kv.ts | 18 ++--- .../sources/google_japanese_input.ts | 14 ++-- denops/skkeleton/sources/skk_dictionary.ts | 14 ++-- denops/skkeleton/sources/skk_server.ts | 14 ++-- denops/skkeleton/sources/user_dictionary.ts | 12 +-- denops/skkeleton/store.ts | 2 +- 9 files changed, 100 insertions(+), 93 deletions(-) diff --git a/denops/skkeleton/dictionary.ts b/denops/skkeleton/dictionary.ts index 7f08253c..68354a99 100644 --- a/denops/skkeleton/dictionary.ts +++ b/denops/skkeleton/dictionary.ts @@ -1,13 +1,11 @@ import { config } from "./config.ts"; +import { Denops, fn, op } from "./deps.ts"; +import { basename, parse, toFileUrl } from "./deps/std/path.ts"; import { JpNum } from "./deps/japanese_numeral.ts"; import { RomanNum } from "./deps/roman.ts"; import { zip } from "./deps/std/collections.ts"; import type { CompletionData, RankData } from "./types.ts"; -import { UserDictionarySource } from "./sources/user_dictionary.ts"; -import { SkkDictionarySource } from "./sources/skk_dictionary.ts"; -import { DenoKvSource } from "./sources/deno_kv.ts"; -import { SkkServerSource } from "./sources/skk_server.ts"; -import { GoogleJapaneseInputSource } from "./sources/google_japanese_input.ts"; +import { Source as UserDictionarySource } from "./sources/user_dictionary.ts"; export const okuriAriMarker = ";; okuri-ari entries."; export const okuriNasiMarker = ";; okuri-nasi entries."; @@ -308,31 +306,62 @@ export class Library { } } -export async function load(): Promise { - const userDictionary = await (new UserDictionarySource()).getUserDictionary(); +export async function load(denops: Denops): Promise { + const cachedPaths = await globpath( + denops, + "denops/skkeleton/sources", + ); + + const userMod = await import( + toFileUrl(cachedPaths["sources/user_dictionary"]).href + ); + const userDictionary = await (new userMod.Source()).getUserDictionary(); const dictionaries: Dictionary[] = []; for (const source of config.sources) { - if (source === "skk_dictionary") { - dictionaries.push( - ...await (new SkkDictionarySource().getDictionaries()), - ); - } else if (source === "deno_kv") { - dictionaries.push( - ...await (new DenoKvSource().getDictionaries()), - ); - } else if (source === "skk_server") { - dictionaries.push( - ...await (new SkkServerSource().getDictionaries()), - ); - } else if (source === "google_japanese_input") { - dictionaries.push( - ...await (new GoogleJapaneseInputSource().getDictionaries()), - ); - } else { + const key = `sources/${source}`; + const path = cachedPaths[key]; + + if (!path) { console.error(`Invalid source name: ${source}`); + continue; } + + const mod = await import(toFileUrl(path).href); + + dictionaries.push( + ...await (new mod.Source().getDictionaries()), + ); } return new Library(dictionaries, userDictionary); } + +async function globpath( + denops: Denops, + search: string, +): Promise> { + const runtimepath = await op.runtimepath.getGlobal(denops); + + const paths: Record = {}; + const glob = await fn.globpath( + denops, + runtimepath, + search + "/*.ts", + 1, + 1, + ); + + for (const path of glob) { + // Skip already added name. + const parsed = parse(path); + const key = `${basename(parsed.dir)}/${parsed.name}`; + if (key in paths) { + continue; + } + + paths[key] = path; + } + + return paths; +} diff --git a/denops/skkeleton/dictionary_test.ts b/denops/skkeleton/dictionary_test.ts index 460ab0fe..0d89f6b7 100644 --- a/denops/skkeleton/dictionary_test.ts +++ b/denops/skkeleton/dictionary_test.ts @@ -1,15 +1,9 @@ -import { config } from "./config.ts"; import { dirname, fromFileUrl, join } from "./deps/std/path.ts"; import { assertEquals } from "./deps/std/assert.ts"; -import { - Dictionary, - Library, - load as loadDictionary, - wrapDictionary, -} from "./dictionary.ts"; -import { SkkDictionary } from "./sources/skk_dictionary.ts"; -import { DenoKvDictionary } from "./sources/deno_kv.ts"; -import { UserDictionaryDictionary as UserDictionary } from "./sources/user_dictionary.ts"; +import { Dictionary, Library, wrapDictionary } from "./dictionary.ts"; +import { Dictionary as SkkDictionary } from "./sources/skk_dictionary.ts"; +import { Dictionary as DenoKvDictionary } from "./sources/deno_kv.ts"; +import { Dictionary as UserDictionary } from "./sources/user_dictionary.ts"; const newJisyoJson = join( dirname(fromFileUrl(import.meta.url)), @@ -29,12 +23,6 @@ const globalJisyo = join( "globalJisyo", ); -const globalJisyo2 = join( - dirname(fromFileUrl(import.meta.url)), - "testdata", - "globalJisyo2", -); - const numJisyo = join( dirname(fromFileUrl(import.meta.url)), "testdata", @@ -280,21 +268,3 @@ Deno.test({ assertEquals(c, ["piyo"]); }, }); - -Deno.test({ - name: "multi dictionary", - async fn() { - config.globalDictionaries = [ - [globalJisyo, "euc-jp"], - [globalJisyo2, "utf-8"], - ]; - const lib = await loadDictionary(); - assertEquals(await lib.getHenkanResult("okurinasi", "てすと"), [ - "テスト", - "test", - "テスト", - ]); - assertEquals(await lib.getHenkanResult("okurinasi", "あ"), ["a"]); - assertEquals(await lib.getHenkanResult("okurinasi", "い"), ["i"]); - }, -}); diff --git a/denops/skkeleton/main.ts b/denops/skkeleton/main.ts index 8b7bf4e5..52dded38 100644 --- a/denops/skkeleton/main.ts +++ b/denops/skkeleton/main.ts @@ -4,7 +4,7 @@ import { assert, AssertError, is } from "./deps/unknownutil.ts"; import { functions, modeFunctions } from "./function.ts"; import { disable as disableFunc } from "./function/disable.ts"; import { load as loadDictionary } from "./dictionary.ts"; -import { DenoKvDictionary } from "./sources/deno_kv.ts"; +import { Dictionary as DenoKvDictionary } from "./sources/deno_kv.ts"; import { currentKanaTable, registerKanaTable } from "./kana.ts"; import { handleKey, registerKeyMap } from "./keymap.ts"; import { initializeStateWithAbbrev } from "./mode.ts"; @@ -64,7 +64,7 @@ async function init(denops: Denops) { console.log(e); } currentContext.get().denops = denops; - currentLibrary.setInitializer(loadDictionary); + currentLibrary.setInitializer(() => loadDictionary(denops)); await receiveNotation(denops); autocmd.group(denops, "skkeleton-internal-denops", (helper) => { helper.remove("*"); diff --git a/denops/skkeleton/sources/deno_kv.ts b/denops/skkeleton/sources/deno_kv.ts index 8a8db75e..c4913725 100644 --- a/denops/skkeleton/sources/deno_kv.ts +++ b/denops/skkeleton/sources/deno_kv.ts @@ -3,11 +3,11 @@ import { getKanaTable } from "../kana.ts"; import { readFileWithEncoding } from "../util.ts"; import type { CompletionData } from "../types.ts"; import { - Dictionary, + Dictionary as BaseDictionary, HenkanType, okuriAriMarker, okuriNasiMarker, - Source, + Source as BaseSource, wrapDictionary, } from "../dictionary.ts"; import { jisyoschema, jsonschema, msgpack, yaml } from "../deps/dictionary.ts"; @@ -31,12 +31,12 @@ function calcKeySize(keys: string[]): number { return size; } -export class DenoKvSource implements Source { - async getDictionaries(): Promise { +export class Source implements BaseSource { + async getDictionaries(): Promise { const globalDictionaries = await Promise.all( config.globalDictionaries.map(async ([path, encodingName]) => { try { - const dict = await DenoKvDictionary.create(path, encodingName); + const dict = await Dictionary.create(path, encodingName); await dict.load(); return dict; } catch (e) { @@ -50,7 +50,7 @@ export class DenoKvSource implements Source { }), ); - const dictionaries: Dictionary[] = []; + const dictionaries: BaseDictionary[] = []; for (const d of globalDictionaries) { if (d) { dictionaries.push(wrapDictionary(d)); @@ -61,7 +61,7 @@ export class DenoKvSource implements Source { } } -export class DenoKvDictionary implements Dictionary { +export class Dictionary implements BaseDictionary { #db: Deno.Kv; #atm: Deno.AtomicOperation; #path: string; @@ -82,8 +82,8 @@ export class DenoKvDictionary implements Dictionary { path: string, encoding: string, databasePath?: string, - ): Promise { - return new DenoKvDictionary( + ): Promise { + return new Dictionary( await Deno.openKv(databasePath ?? config.databasePath), path, encoding, diff --git a/denops/skkeleton/sources/google_japanese_input.ts b/denops/skkeleton/sources/google_japanese_input.ts index faffc42c..38142fb3 100644 --- a/denops/skkeleton/sources/google_japanese_input.ts +++ b/denops/skkeleton/sources/google_japanese_input.ts @@ -1,15 +1,19 @@ import { config } from "../config.ts"; -import { Dictionary, HenkanType, Source } from "../dictionary.ts"; +import { + Dictionary as BaseDictionary, + HenkanType, + Source as BaseSource, +} from "../dictionary.ts"; import type { CompletionData } from "../types.ts"; import { deadline, DeadlineError } from "../deps/std/async.ts"; -export class GoogleJapaneseInputSource implements Source { - getDictionaries(): Promise { - return Promise.resolve([new GoogleJapaneseInputDictionary()]); +export class Source implements BaseSource { + getDictionaries(): Promise { + return Promise.resolve([new Dictionary()]); } } -export class GoogleJapaneseInputDictionary implements Dictionary { +export class Dictionary implements BaseDictionary { async connect() {} async getHenkanResult(_type: HenkanType, word: string): Promise { // It should not work for "okuriari". diff --git a/denops/skkeleton/sources/skk_dictionary.ts b/denops/skkeleton/sources/skk_dictionary.ts index d3e00213..557dcae2 100644 --- a/denops/skkeleton/sources/skk_dictionary.ts +++ b/denops/skkeleton/sources/skk_dictionary.ts @@ -3,11 +3,11 @@ import { getKanaTable } from "../kana.ts"; import { readFileWithEncoding } from "../util.ts"; import type { CompletionData } from "../types.ts"; import { - Dictionary, + Dictionary as BaseDictionary, HenkanType, okuriAriMarker, okuriNasiMarker, - Source, + Source as BaseSource, wrapDictionary, } from "../dictionary.ts"; import { jisyoschema, jsonschema, msgpack, yaml } from "../deps/dictionary.ts"; @@ -17,12 +17,12 @@ interface Jisyo { okuri_nasi: Record; } -export class SkkDictionarySource implements Source { - async getDictionaries(): Promise { +export class Source implements BaseSource { + async getDictionaries(): Promise { const globalDictionaries = await Promise.all( config.globalDictionaries.map(async ([path, encodingName]) => { try { - const dict = new SkkDictionary(); + const dict = new Dictionary(); await dict.load(path, encodingName); return dict; } catch (e) { @@ -36,7 +36,7 @@ export class SkkDictionarySource implements Source { }), ); - const dictionaries: Dictionary[] = []; + const dictionaries: BaseDictionary[] = []; for (const d of globalDictionaries) { if (d) { dictionaries.push(wrapDictionary(d)); @@ -47,7 +47,7 @@ export class SkkDictionarySource implements Source { } } -export class SkkDictionary implements Dictionary { +export class Dictionary implements BaseDictionary { #okuriAri: Map; #okuriNasi: Map; diff --git a/denops/skkeleton/sources/skk_server.ts b/denops/skkeleton/sources/skk_server.ts index 8e499f32..8288153a 100644 --- a/denops/skkeleton/sources/skk_server.ts +++ b/denops/skkeleton/sources/skk_server.ts @@ -3,7 +3,11 @@ import { encoding } from "../deps/encoding_japanese.ts"; import { Encode } from "../types.ts"; import { getKanaTable } from "../kana.ts"; import { TextLineStream } from "../deps/std/streams.ts"; -import { Dictionary, HenkanType, Source } from "../dictionary.ts"; +import { + Dictionary as BaseDictionary, + HenkanType, + Source as BaseSource, +} from "../dictionary.ts"; import type { CompletionData, Encoding, SkkServerOptions } from "../types.ts"; type Server = { @@ -12,9 +16,9 @@ type Server = { writer: WritableStreamDefaultWriter; }; -export class SkkServerSource implements Source { - async getDictionaries(): Promise { - const skkServer = new SkkServerDictionary({ +export class Source implements BaseSource { + async getDictionaries(): Promise { + const skkServer = new Dictionary({ hostname: config.skkServerHost, port: config.skkServerPort, requestEnc: config.skkServerReqEnc, @@ -34,7 +38,7 @@ export class SkkServerSource implements Source { } } -export class SkkServerDictionary implements Dictionary { +export class Dictionary implements BaseDictionary { #server: Server | undefined; responseEncoding: Encoding; requestEncoding: Encoding; diff --git a/denops/skkeleton/sources/user_dictionary.ts b/denops/skkeleton/sources/user_dictionary.ts index 7b29999f..4551e345 100644 --- a/denops/skkeleton/sources/user_dictionary.ts +++ b/denops/skkeleton/sources/user_dictionary.ts @@ -2,24 +2,24 @@ import { config } from "../config.ts"; import { getKanaTable } from "../kana.ts"; import type { CompletionData, RankData } from "../types.ts"; import { - Dictionary, + Dictionary as BaseDictionary, HenkanType, okuriAriMarker, okuriNasiMarker, - Source, + Source as BaseSource, UserDictionary, UserDictionaryPath, } from "../dictionary.ts"; import { wrap } from "../deps/iterator_helpers.ts"; import { assert, is } from "../deps/unknownutil.ts"; -export class UserDictionarySource implements Source { - async getDictionaries(): Promise { +export class Source implements BaseSource { + async getDictionaries(): Promise { return [await this.getUserDictionary()]; } async getUserDictionary(): Promise { - const userDictionary = new UserDictionaryDictionary(); + const userDictionary = new Dictionary(); try { await userDictionary.load({ path: config.userDictionary, @@ -37,7 +37,7 @@ export class UserDictionarySource implements Source { } } -export class UserDictionaryDictionary implements UserDictionary { +export class Dictionary implements UserDictionary { #okuriAri: Map; #okuriNasi: Map; #rank: Map; diff --git a/denops/skkeleton/store.ts b/denops/skkeleton/store.ts index 5ae371d3..60d6657f 100644 --- a/denops/skkeleton/store.ts +++ b/denops/skkeleton/store.ts @@ -1,7 +1,7 @@ import { Context } from "./context.ts"; import { Library } from "./dictionary.ts"; import { Cell, LazyCell } from "./util.ts"; -import { UserDictionaryDictionary as UserDictionary } from "./sources/user_dictionary.ts"; +import { Dictionary as UserDictionary } from "./sources/user_dictionary.ts"; export const currentContext = new Cell(() => new Context()); export const currentLibrary = new LazyCell(() => From 667e58ebabe71f5c23f3da4c28c292c09552d427 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 16 Jan 2024 13:28:43 +0900 Subject: [PATCH 2/5] Fix --- denops/skkeleton/dictionary.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/denops/skkeleton/dictionary.ts b/denops/skkeleton/dictionary.ts index 68354a99..66a6cf19 100644 --- a/denops/skkeleton/dictionary.ts +++ b/denops/skkeleton/dictionary.ts @@ -5,7 +5,6 @@ import { JpNum } from "./deps/japanese_numeral.ts"; import { RomanNum } from "./deps/roman.ts"; import { zip } from "./deps/std/collections.ts"; import type { CompletionData, RankData } from "./types.ts"; -import { Source as UserDictionarySource } from "./sources/user_dictionary.ts"; export const okuriAriMarker = ";; okuri-ari entries."; export const okuriNasiMarker = ";; okuri-nasi entries."; From 36af249708fe0c10b298357fa34000e26fa9593d Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 16 Jan 2024 13:38:10 +0900 Subject: [PATCH 3/5] Fix load() args --- denops/skkeleton/dictionary.ts | 43 ++++------------------------------ denops/skkeleton/main.ts | 15 +++++++++++- denops/skkeleton/util.ts | 32 ++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/denops/skkeleton/dictionary.ts b/denops/skkeleton/dictionary.ts index 66a6cf19..7472ba2f 100644 --- a/denops/skkeleton/dictionary.ts +++ b/denops/skkeleton/dictionary.ts @@ -1,6 +1,5 @@ import { config } from "./config.ts"; -import { Denops, fn, op } from "./deps.ts"; -import { basename, parse, toFileUrl } from "./deps/std/path.ts"; +import { toFileUrl } from "./deps/std/path.ts"; import { JpNum } from "./deps/japanese_numeral.ts"; import { RomanNum } from "./deps/roman.ts"; import { zip } from "./deps/std/collections.ts"; @@ -305,21 +304,16 @@ export class Library { } } -export async function load(denops: Denops): Promise { - const cachedPaths = await globpath( - denops, - "denops/skkeleton/sources", - ); - +export async function load(paths: Record): Promise { const userMod = await import( - toFileUrl(cachedPaths["sources/user_dictionary"]).href + toFileUrl(paths["sources/user_dictionary"]).href ); const userDictionary = await (new userMod.Source()).getUserDictionary(); const dictionaries: Dictionary[] = []; for (const source of config.sources) { const key = `sources/${source}`; - const path = cachedPaths[key]; + const path = paths[key]; if (!path) { console.error(`Invalid source name: ${source}`); @@ -335,32 +329,3 @@ export async function load(denops: Denops): Promise { return new Library(dictionaries, userDictionary); } - -async function globpath( - denops: Denops, - search: string, -): Promise> { - const runtimepath = await op.runtimepath.getGlobal(denops); - - const paths: Record = {}; - const glob = await fn.globpath( - denops, - runtimepath, - search + "/*.ts", - 1, - 1, - ); - - for (const path of glob) { - // Skip already added name. - const parsed = parse(path); - const key = `${basename(parsed.dir)}/${parsed.name}`; - if (key in paths) { - continue; - } - - paths[key] = path; - } - - return paths; -} diff --git a/denops/skkeleton/main.ts b/denops/skkeleton/main.ts index 52dded38..949dfa32 100644 --- a/denops/skkeleton/main.ts +++ b/denops/skkeleton/main.ts @@ -10,6 +10,7 @@ import { handleKey, registerKeyMap } from "./keymap.ts"; import { initializeStateWithAbbrev } from "./mode.ts"; import { keyToNotation, notationToKey, receiveNotation } from "./notation.ts"; import { currentContext, currentLibrary, variables } from "./store.ts"; +import { globpath } from "./util.ts"; import type { CompletionData, RankData } from "./types.ts"; type Opts = { @@ -64,8 +65,18 @@ async function init(denops: Denops) { console.log(e); } currentContext.get().denops = denops; - currentLibrary.setInitializer(() => loadDictionary(denops)); + + currentLibrary.setInitializer(async () => + loadDictionary( + await globpath( + denops, + "denops/skkeleton/sources", + ), + ) + ); + await receiveNotation(denops); + autocmd.group(denops, "skkeleton-internal-denops", (helper) => { helper.remove("*"); // Note: 使い終わったステートを初期化する @@ -81,11 +92,13 @@ async function init(denops: Denops) { `call skkeleton#disable()`, ); }); + try { await denops.cmd("doautocmd User skkeleton-initialize-post"); } catch (e) { console.log(e); } + initialized = true; } diff --git a/denops/skkeleton/util.ts b/denops/skkeleton/util.ts index e4d3e7bd..120ae0fa 100644 --- a/denops/skkeleton/util.ts +++ b/denops/skkeleton/util.ts @@ -1,4 +1,5 @@ -import { Denops, fn } from "./deps.ts"; +import { Denops, fn, op } from "./deps.ts"; +import { basename, parse } from "./deps/std/path.ts"; import { encoding } from "./deps/encoding_japanese.ts"; export class Cell { @@ -101,3 +102,32 @@ export async function readFileWithEncoding( const decoder = new TextDecoder(fileEncoding); return decoder.decode(uint); } + +export async function globpath( + denops: Denops, + search: string, +): Promise> { + const runtimepath = await op.runtimepath.getGlobal(denops); + + const paths: Record = {}; + const glob = await fn.globpath( + denops, + runtimepath, + search + "/*.ts", + 1, + 1, + ); + + for (const path of glob) { + // Skip already added name. + const parsed = parse(path); + const key = `${basename(parsed.dir)}/${parsed.name}`; + if (key in paths) { + continue; + } + + paths[key] = path; + } + + return paths; +} From 45c357096bab95b3b99f13d4c45782802e10f2b3 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Tue, 16 Jan 2024 13:51:50 +0900 Subject: [PATCH 4/5] Use test() --- denops/skkeleton/function/mode_test.ts | 43 +++++++++++++------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/denops/skkeleton/function/mode_test.ts b/denops/skkeleton/function/mode_test.ts index b698b6cb..23a8920d 100644 --- a/denops/skkeleton/function/mode_test.ts +++ b/denops/skkeleton/function/mode_test.ts @@ -52,27 +52,6 @@ test({ }, }); -Deno.test({ - name: "can convert okuri string properly when mode changed", - async fn() { - const lib = await currentLibrary.get(); - await lib.registerHenkanResult("okuriari", "はg", "剥"); - const context = currentContext.init(); - - await katakana(context); - await dispatch(context, ";ha;ge"); - assertEquals(context.toString(), "▼剥ゲ"); - await kakutei(context); - assertEquals(context.preEdit.output(""), "剥ゲ"); - - await hankatakana(context); - await dispatch(context, ";ha;ge"); - assertEquals(context.toString(), "▼剥ゲ"); - await kakutei(context); - assertEquals(context.preEdit.output(""), "剥ゲ"); - }, -}); - Deno.test({ name: "abbrev", async fn() { @@ -100,6 +79,28 @@ Deno.test({ }, }); +test({ + mode: "all", + name: "can convert okuri string properly when mode changed", + async fn(_d: Denops) { + const lib = await currentLibrary.get(); + await lib.registerHenkanResult("okuriari", "はg", "剥"); + const context = currentContext.init(); + + await katakana(context); + await dispatch(context, ";ha;ge"); + assertEquals(context.toString(), "▼剥ゲ"); + await kakutei(context); + assertEquals(context.preEdit.output(""), "剥ゲ"); + + await hankatakana(context); + await dispatch(context, ";ha;ge"); + assertEquals(context.toString(), "▼剥ゲ"); + await kakutei(context); + assertEquals(context.preEdit.output(""), "剥ゲ"); + }, +}); + test({ mode: "all", name: "mode change at enable", From a12c189960595fd05967d40e86c76665894a8b01 Mon Sep 17 00:00:00 2001 From: kuuote Date: Sat, 20 Jan 2024 14:28:23 +0900 Subject: [PATCH 5/5] fix: execute initialize before test --- denops/skkeleton/main.ts | 7 ++++++- denops/skkeleton/testutil.ts | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/denops/skkeleton/main.ts b/denops/skkeleton/main.ts index 949dfa32..d667c82f 100644 --- a/denops/skkeleton/main.ts +++ b/denops/skkeleton/main.ts @@ -255,6 +255,8 @@ function buildResult(result: string): HandleResult { } export async function main(denops: Denops) { + // Note: pending initialize for reload plugin + initialized = false; if (await vars.g.get(denops, "skkeleton#debug", false)) { config.debug = true; } @@ -350,7 +352,10 @@ export async function main(denops: Denops) { async getConfig() { return config; }, - async initialize() { + async initialize(force = false) { + if (force) { + initialized = false; + } await init(denops); // NOTE: Initialize dictionary diff --git a/denops/skkeleton/testutil.ts b/denops/skkeleton/testutil.ts index ce06ea1d..dbb85906 100644 --- a/denops/skkeleton/testutil.ts +++ b/denops/skkeleton/testutil.ts @@ -16,6 +16,7 @@ export function test(def: DenopsTest.TestDefinition): void { ...def, async fn(denops: Denops, t: Deno.TestContext) { await main(denops); + await denops.dispatcher.initialize(true); await autocmd.emit(denops, "User", "DenopsSystemPluginPost:skkeleton", { nomodeline: true, });