diff --git a/denops/ddc/context.ts b/denops/ddc/context.ts index 76776ad..89972dd 100644 --- a/denops/ddc/context.ts +++ b/denops/ddc/context.ts @@ -1,8 +1,8 @@ import type { BaseParams, + Callback, Context, ContextBuilder, - ContextCallback, ContextCallbacks, DdcEvent, DdcOptions, @@ -12,7 +12,7 @@ import type { UserOptions, } from "./types.ts"; import { defaultSourceOptions } from "./base/source.ts"; -import { printError } from "./utils.ts"; +import { callCallback, printError } from "./utils.ts"; import type { Denops } from "jsr:@denops/std@~7.3.0"; import * as op from "jsr:@denops/std@~7.3.0/option"; @@ -65,6 +65,7 @@ export function defaultDdcOptions(): DdcOptions { ], backspaceCompletion: false, cmdlineSources: [], + dynamicUi: "", filterOptions: {}, filterParams: {}, hideOnEvents: false, @@ -204,32 +205,23 @@ class Custom { bufnr: number, options: UserOptions, ): Promise { - const callContextCallback = async (callback: ContextCallback) => { - if (!denops || !callback) { - return {}; - } - - if (is.String(callback)) { - if (callback === "") { - return {}; - } - - return await denops.call( - "denops#callback#call", - callback, - ) as Partial; - } else { - return await callback(denops); - } - }; - - const contextGlobal = await callContextCallback(this.context.global); + const contextGlobal = await callCallback( + denops, + this.context.global, + {}, + ) as Partial; const filetype = this.filetype[ft] || {}; - const contextFiletype = await callContextCallback( + const contextFiletype = await callCallback( + denops, this.context.filetype[ft], - ); + {}, + ) as Partial; const buffer = this.buffer[bufnr] || {}; - const contextBuffer = await callContextCallback(this.context.buffer[bufnr]); + const contextBuffer = await callCallback( + denops, + this.context.buffer[bufnr], + {}, + ) as Partial; return foldMerge(mergeDdcOptions, defaultDdcOptions, [ this.global, @@ -254,15 +246,15 @@ class Custom { this.buffer[bufnr] = options; return this; } - setContextGlobal(callback: ContextCallback): Custom { + setContextGlobal(callback: Callback): Custom { this.context.global = callback; return this; } - setContextFiletype(callback: ContextCallback, ft: string): Custom { + setContextFiletype(callback: Callback, ft: string): Custom { this.context.filetype[ft] = callback; return this; } - setContextBuffer(callback: ContextCallback, bufnr: number): Custom { + setContextBuffer(callback: Callback, bufnr: number): Custom { this.context.buffer[bufnr] = callback; return this; } @@ -528,13 +520,13 @@ export class ContextBuilderImpl implements ContextBuilder { setBuffer(bufnr: number, options: Partial) { this.#custom.setBuffer(bufnr, options); } - setContextGlobal(callback: ContextCallback) { + setContextGlobal(callback: Callback) { this.#custom.setContextGlobal(callback); } - setContextFiletype(callback: ContextCallback, ft: string) { + setContextFiletype(callback: Callback, ft: string) { this.#custom.setContextFiletype(callback, ft); } - setContextBuffer(callback: ContextCallback, bufnr: number) { + setContextBuffer(callback: Callback, bufnr: number) { this.#custom.setContextBuffer(callback, bufnr); } diff --git a/denops/ddc/ddc.ts b/denops/ddc/ddc.ts index 488ac16..d3dd93f 100644 --- a/denops/ddc/ddc.ts +++ b/denops/ddc/ddc.ts @@ -24,6 +24,7 @@ import { getSource, getUi, } from "./ext.ts"; +import { callCallback } from "./utils.ts"; import type { Denops } from "jsr:@denops/std@~7.3.0"; import * as autocmd from "jsr:@denops/std@~7.3.0/autocmd"; @@ -476,6 +477,14 @@ export class Ddc { return; } + const dynamicUi = await callCallback(denops, options.dynamicUi, { + completePos, + items, + }) as string | null; + if (dynamicUi) { + options.ui = dynamicUi; + } + await (async function write(ddc: Ddc) { await batch(denops, async (denops: Denops) => { await vars.g.set(denops, "ddc#_changedtick", context.changedTick); diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index 8a19f77..b1c0149 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -26,14 +26,14 @@ export type Context = { nextInput: string; }; -export type ContextCallback = +export type Callback = | string - | ((denops: Denops) => Promise>); + | ((denops: Denops, args: Record) => Promise); export type ContextCallbacks = { - global: ContextCallback; - filetype: Record; - buffer: Record; + global: Callback; + filetype: Record; + buffer: Record; }; export interface ContextBuilder { @@ -45,9 +45,9 @@ export interface ContextBuilder { setGlobal(options: Partial): void; setFiletype(ft: string, options: Partial): void; setBuffer(bufnr: number, options: Partial): void; - setContextGlobal(callback: ContextCallback): void; - setContextFiletype(callback: ContextCallback, ft: string): void; - setContextBuffer(callback: ContextCallback, bufnr: number): void; + setContextGlobal(callback: Callback): void; + setContextFiletype(callback: Callback, ft: string): void; + setContextBuffer(callback: Callback, bufnr: number): void; patchGlobal(options: Partial): void; patchFiletype(ft: string, options: Partial): void; patchBuffer(bufnr: number, options: Partial): void; @@ -70,6 +70,7 @@ export type DdcOptions = { autoCompleteEvents: DdcEvent[]; backspaceCompletion: boolean; cmdlineSources: UserSource[] | Record; + dynamicUi: Callback; filterOptions: Record>; filterParams: Record>; hideOnEvents: boolean; diff --git a/denops/ddc/utils.ts b/denops/ddc/utils.ts index d122c92..b296b23 100644 --- a/denops/ddc/utils.ts +++ b/denops/ddc/utils.ts @@ -1,6 +1,9 @@ +import type { Callback } from "./types.ts"; + import type { Denops } from "jsr:@denops/std@~7.3.0"; import * as op from "jsr:@denops/std@~7.3.0/option"; +import { is } from "jsr:@core/unknownutil@~4.3.0/is"; import { assertEquals } from "jsr:@std/assert@~1.0.2/equals"; export async function convertKeywordPattern( @@ -107,6 +110,30 @@ export async function safeStat(path: string): Promise { return null; } +export async function callCallback( + denops: Denops | null, + callback: Callback, + args: Record, +): Promise { + if (!denops || !callback) { + return null; + } + + if (is.String(callback)) { + if (callback === "") { + return null; + } + + return await denops.call( + "denops#callback#call", + callback, + args, + ); + } else { + return await callback(denops, args); + } +} + Deno.test("vimoption2ts", () => { assertEquals(vimoption2ts("@,48-57,_,\\"), "a-zA-Z0-9_\\\\"); assertEquals(vimoption2ts("@,-,48-57,_"), "a-zA-Z0-9_-"); diff --git a/doc/ddc.txt b/doc/ddc.txt index f47e506..9ce132a 100644 --- a/doc/ddc.txt +++ b/doc/ddc.txt @@ -143,6 +143,16 @@ cmdlineSources \ '=': ['input'], \ }) < + *ddc-option-dynamicUi* +dynamicUi + It is the function which overwrites |ddc-option-ui| after + gather items. + The function returns new ui name. + NOTE: {func} is evaluated after user input and it affects + completion performance. + + Default: "" + *ddc-option-filterOptions* filterOptions It is a dictionary that maps filter names to its options. @@ -1710,6 +1720,9 @@ https://github.com/Milly/ddc-unprintable ============================================================================== COMPATIBILITY *ddc-compatibility* +2024.11.04 +* Change callback function type. + 2024.08.30 * Refactor types.ts.