import { is, maybe } from "jsr:@core/unknownutil"; import { Denops } from "jsr:@denops/std"; import * as fn from "jsr:@denops/std/function"; import * as lambda from "jsr:@denops/std/lambda"; import * as mapping from "jsr:@denops/std/mapping"; const { bufnr } = fn; const dispatchName = "lambda.map" + performance.now(); const dispatcher = new Map<string, lambda.Fn>(); export async function map( denops: Denops, lhs: string, rhs: lambda.Fn, options: mapping.MapOptions = {}, ): Promise<void> { denops.dispatcher[dispatchName] = (functionName: unknown) => dispatcher.get(String(functionName))?.() ?? Promise.resolve(); const mode = options.mode; const modeStr = maybe(mode, is.Array)?.join("") ?? maybe(mode, is.String) ?? ""; const bufNr = options.buffer ? await bufnr(denops) : -1; const lhsEscaped = lhs.replaceAll(/</g, "[less]"); const functionName = `${modeStr}:${bufNr}:${lhsEscaped}`; dispatcher.set(functionName, rhs); const rhsStr = `<Cmd>call denops#request('${denops.name}', '${dispatchName}', ['${functionName}'])<CR>`; await mapping.map(denops, lhs, rhsStr, options); } export type CommandOptions = { async?: boolean; buffer?: boolean; }; export type CommandArg = { bang: boolean; arg: string; }; export type CommandFn = (arg: CommandArg) => void | Promise<void>; const cmdFunc = "vimrc.lambda.cmd" + Math.random(); const cmdTable: Record<string, CommandFn> = {}; export async function cmd( denops: Denops, name: string, fn: CommandFn, opt: CommandOptions = {}, ) { denops.dispatcher[cmdFunc] = ( functionName: unknown, bang: unknown, arg: unknown, ) => cmdTable[String(functionName)]?.({ bang: Boolean(bang), arg: String(arg), }) ?? Promise.resolve(); const bufNr = opt.buffer ? Number(await denops.call("bufnr")) : -1; const functionName = `${bufNr}:${name}`; cmdTable[functionName] = fn; await denops.cmd( `command! ${opt.buffer ? "-buffer" : ""} -nargs=* ${name} call denops#${ opt.async ? "notify" : "request" }('${denops.name}', '${cmdFunc}', ['${functionName}', <bang>0, <q-args>])`, ); }