diff --git a/denops/@dpp-exts/local.ts b/denops/@dpp-exts/local.ts index 99c634a..a0ab50e 100644 --- a/denops/@dpp-exts/local.ts +++ b/denops/@dpp-exts/local.ts @@ -1,10 +1,5 @@ -import { - Actions, - BaseExt, -} from "../dpp/types.ts"; -import { - Denops, -} from "../dpp/deps.ts"; +import { Actions, BaseExt } from "../dpp/types.ts"; +import { Denops } from "../dpp/deps.ts"; type Params = Record; @@ -16,7 +11,7 @@ export class Ext extends BaseExt { console.log("hello"); }, }, - } + }; override params(): Params { return {}; diff --git a/denops/dpp/base/config.ts b/denops/dpp/base/config.ts index 7650520..fc0f0e1 100644 --- a/denops/dpp/base/config.ts +++ b/denops/dpp/base/config.ts @@ -1,8 +1,12 @@ +import { ContextBuilder } from "../context.ts"; import { Denops } from "../deps.ts"; +import { Dpp } from "../types.ts"; export type ConfigArguments = { denops: Denops; basePath: string; + contextBuilder: ContextBuilder; + dpp: Dpp; }; export abstract class BaseConfig { diff --git a/denops/dpp/base/ext.ts b/denops/dpp/base/ext.ts index cf38dce..3aa6bef 100644 --- a/denops/dpp/base/ext.ts +++ b/denops/dpp/base/ext.ts @@ -1,7 +1,14 @@ -import { Actions } from "../types.ts"; +import { Denops } from "../deps.ts"; +import { Actions, ExtOptions } from "../types.ts"; export type BaseExtParams = Record; +export type OnInitArguments = { + denops: Denops; + extOptions: ExtOptions; + extParams: Params; +}; + export abstract class BaseExt { apiVersion = 1; @@ -9,7 +16,13 @@ export abstract class BaseExt { path = ""; isInitialized = false; + onInit(_args: OnInitArguments): void | Promise {} + abstract params(): Params; actions: Actions = {}; } + +export function defaultExtOptions(): ExtOptions { + return {}; +} diff --git a/denops/dpp/dpp.ts b/denops/dpp/dpp.ts index 10c185d..3630400 100644 --- a/denops/dpp/dpp.ts +++ b/denops/dpp/dpp.ts @@ -1,14 +1,147 @@ -import { ActionName, ExtName } from "./types.ts"; +import { Denops } from "./deps.ts"; +import { + ActionName, + BaseExt, + BaseExtParams, + Context, + DppOptions, + ExtName, + ExtOptions, +} from "./types.ts"; +import { + defaultContext, + defaultDppOptions, + defaultDummy, + foldMerge, + mergeExtOptions, + mergeExtParams, +} from "./context.ts"; import { Loader } from "./loader.ts"; +import { defaultExtOptions } from "./base/ext.ts"; import { errorException } from "./utils.ts"; export class Dpp { private loader: Loader; + private context: Context = defaultContext(); + private options: DppOptions = defaultDppOptions(); constructor(loader: Loader) { this.loader = loader; } - async extAction(extName: ExtName, actionName: ActionName, params: unknown) { + async extAction( + denops: Denops, + extName: ExtName, + actionName: ActionName, + actionParams: unknown = {}, + ) { + const [ext, extOptions, extParams] = await this.getExt(denops, extName); + if (!ext) { + return; + } + + const action = ext.actions[actionName]; + if (!action) { + await denops.call( + "ddu#util#print_error", + `Not found UI action: ${actionName}`, + ); + return; + } + + const ret = await action.callback({ + denops, + context: this.context, + options: this.options, + extOptions, + extParams, + actionParams, + }); + + return ret; + } + + private async getExt( + denops: Denops, + extName: ExtName, + ): Promise< + [ + BaseExt | undefined, + ExtOptions, + BaseExtParams, + ] + > { + if (!this.loader.getExt(extName)) { + await this.loader.autoload(denops, "ext", extName); + } + + const ext = this.loader.getExt(extName); + if (!ext) { + if (extName.length !== 0) { + await denops.call( + "dpp#util#print_error", + `Not found ext: "${extName}"`, + ); + } + return [ + undefined, + defaultExtOptions(), + defaultDummy(), + ]; + } + + const [extOptions, extParams] = extArgs(this.options, ext); + await checkExtOnInit(ext, denops, extOptions, extParams); + + return [ext, extOptions, extParams]; } } + +async function checkExtOnInit( + ext: BaseExt, + denops: Denops, + extOptions: ExtOptions, + extParams: BaseExtParams, +) { + if (ext.isInitialized) { + return; + } + + try { + await ext.onInit({ + denops, + extOptions, + extParams, + }); + + ext.isInitialized = true; + } catch (e: unknown) { + await errorException( + denops, + e, + `ext: ${ext.name} "onInit()" failed`, + ); + } +} + +function extArgs< + Params extends BaseExtParams, +>( + options: DppOptions, + ext: BaseExt, +): [ExtOptions, BaseExtParams] { + const o = foldMerge( + mergeExtOptions, + defaultExtOptions, + [ + options.extOptions["_"], + options.extOptions[ext.name], + ], + ); + const p = foldMerge(mergeExtParams, defaultDummy, [ + ext.params(), + options.extParams["_"], + options.extParams[ext.name], + ]); + return [o, p]; +} diff --git a/denops/dpp/loader.ts b/denops/dpp/loader.ts index 01ef264..85b88a2 100644 --- a/denops/dpp/loader.ts +++ b/denops/dpp/loader.ts @@ -16,7 +16,7 @@ type Mod = { }; export class Loader { - private extensions: Record = {}; + private extension: Extension = new Extension(); private mods: Record> = { ext: {}, protocol: {}, @@ -48,32 +48,21 @@ export class Loader { }); } - getExt(index: string, name: ExtName): BaseExt | null { + getExt(name: ExtName): BaseExt | null { const mod = this.mods.ext[name]; if (!mod) { return null; } - return this.getExtension(index).getExt(mod, name); + return this.extension.getExt(mod, name); } - getProtocol( - index: string, - name: ProtocolName, - ): BaseProtocol | null { + getProtocol(name: ProtocolName): BaseProtocol | null { const mod = this.mods.protocol[name]; if (!mod) { return null; } - return this.getExtension(index).getProtocol(mod, name); - } - - private getExtension(index: string): Extension { - if (!this.extensions[index]) { - this.extensions[index] = new Extension(); - } - - return this.extensions[index]; + return this.extension.getProtocol(mod, name); } private async register(type: DppExtType, path: string) {