diff --git a/autoload/ddc.vim b/autoload/ddc.vim index 3f65e503..a304cbdd 100644 --- a/autoload/ddc.vim +++ b/autoload/ddc.vim @@ -110,6 +110,11 @@ function ddc#visible() abort \ denops#request('ddc', 'visible', []) : v:false endfunction +function ddc#get_previewer(item, context={}) abort + return ddc#_denops_running() ? + \ denops#request('ddc', 'getPreviewer', [a:item, a:context]) : {} +endfunction + function ddc#register(type, path) abort call ddc#_notify('register', [a:type, a:path]) endfunction diff --git a/denops/ddc/app.ts b/denops/ddc/app.ts index 29e00c06..8a1ab7f2 100644 --- a/denops/ddc/app.ts +++ b/denops/ddc/app.ts @@ -7,6 +7,8 @@ import { DdcOptions, DdcUserData, Item, + PreviewContext, + Previewer, UserOptions, } from "./types.ts"; import { Denops, ensure, is, Lock, toFileUrl, vars } from "./deps.ts"; @@ -107,6 +109,19 @@ export function main(denops: Denops) { getCurrent(): Promise { return Promise.resolve(contextBuilder.getCurrent(denops)); }, + async getPreviewer(arg1: unknown, arg2: unknown): Promise { + const [_skip, context, options] = await contextBuilder + .createContext(denops, "Manual"); + const item = ensure(arg1, is.Record) as DdcItem; + const previewContext = ensure(arg2, is.Record) as PreviewContext; + return await ddc.getPreviewer( + denops, + context, + options, + item, + previewContext, + ); + }, async loadConfig(arg1: unknown): Promise { await lock.lock(async () => { const path = ensure(arg1, is.String); diff --git a/denops/ddc/base/source.ts b/denops/ddc/base/source.ts index 86e42886..0b511f1c 100644 --- a/denops/ddc/base/source.ts +++ b/denops/ddc/base/source.ts @@ -2,8 +2,11 @@ import { Context, DdcEvent, DdcGatherItems, + DdcItem, DdcOptions, OnCallback, + PreviewContext, + Previewer, SourceOptions, } from "../types.ts"; import { Denops } from "../deps.ts"; @@ -40,6 +43,16 @@ export type OnCompleteDoneArguments< userData: UserData; }; +export type GetPreviewerArguments = { + denops: Denops; + context: Context; + options: DdcOptions; + sourceOptions: SourceOptions; + sourceParams: Params; + item: DdcItem; + previewContext: PreviewContext; +}; + export type GetCompletePositionArguments = { denops: Denops; context: Context; @@ -67,7 +80,7 @@ export abstract class BaseSource< > { name = ""; isInitialized = false; - apiVersion = 5; + apiVersion = 6; events: DdcEvent[] = []; isBytePos = false; @@ -80,6 +93,13 @@ export abstract class BaseSource< _args: OnCompleteDoneArguments, ): Promise {} + // deno-lint-ignore require-await + async getPreviewer( + _args: GetPreviewerArguments, + ): Promise { + return Promise.resolve({}); + } + async getCompletePosition( args: GetCompletePositionArguments, ): Promise { diff --git a/denops/ddc/ddc.ts b/denops/ddc/ddc.ts index 596278bc..b397359f 100644 --- a/denops/ddc/ddc.ts +++ b/denops/ddc/ddc.ts @@ -15,6 +15,8 @@ import { FilterOptions, Item, OnCallback, + PreviewContext, + Previewer, SourceName, SourceOptions, UiOptions, @@ -883,6 +885,39 @@ export class Ddc { return [filter, filterOptions, filterParams]; } + + async getPreviewer( + denops: Denops, + context: Context, + options: DdcOptions, + item: DdcItem, + previewContext: PreviewContext, + ): Promise { + if (!item.__sourceName) { + return {}; + } + + const [source, sourceOptions, sourceParams] = await this.getSource( + denops, + options, + item.__sourceName, + ); + if (!source || !source.getPreviewer) { + return {}; + } + + const previewer = await source.getPreviewer({ + denops, + context, + options, + sourceOptions, + sourceParams, + item, + previewContext, + }); + + return previewer; + } } function formatAbbr(word: string, abbr: string | undefined): string { diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index 65069893..ee9be91f 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -153,3 +153,45 @@ export interface CallbackContext { revoke(): void; createOnCallback(): OnCallback; } + +/** + * Information of preview window + */ +export type PreviewContext = { + row?: number; + col?: number; + width?: number; + height?: number; + isFloating?: boolean; + split?: "horizontal" | "vertical" | "no"; +}; + +type EmptyPreviewer = Record; + +export type CommandPreviewer = { + kind: "command"; + + command: string; +}; + +type MarkdownPreviewer = { + kind: "markdown"; + + contents: string[]; +}; + +type TextPreviewer = { + kind: "text"; + + contents: string[]; +}; + +/** + * Previewer defines how the preview is rendered + * This must be implemented in the ddc-source + */ +export type Previewer = + | EmptyPreviewer + | CommandPreviewer + | MarkdownPreviewer + | TextPreviewer; diff --git a/doc/ddc.txt b/doc/ddc.txt index 69d3cdbb..8ff69fef 100644 --- a/doc/ddc.txt +++ b/doc/ddc.txt @@ -31,6 +31,8 @@ Create source |ddc-create-source| Item attributes |ddc-item-attributes| Create filter |ddc-create-filter| filter attributes |ddc-filter-attributes| +Previewer |ddc-previewer| + previewer attributes |ddc-previewer-attributes| FAQ |ddc-faq| Compatibility |ddc-compatibility| @@ -317,6 +319,12 @@ ddc#enable_terminal_completion() NOTE: It is experimental feature in Vim. neovim is recommended. + *ddc#get_previewer()* +ddc#get_previewer({item}[, {context}]) + Get |ddc-previewer| from {item}. + {context} is used as preview window context. + It is useful to render preview information dynamically. + *ddc#hide()* ddc#hide([{event}]) Hide current completion UI. @@ -933,6 +941,10 @@ getCompletePosition (function) (Optional) Default : |ddc-source-option-keywordPattern| is used. + *ddc-source-attribute-getPreviewer* +getPreviewer (function) (Optional) + Called to get |ddc-previewer|. + *ddc-source-attribute-onCompleteDone* onCompleteDone (function) (Optional) Called after the completion. @@ -1061,6 +1073,52 @@ params (function) (Required) Called to get filter params. +============================================================================== +PREVIEWER *ddc-previewer* + +Previewer defines how the preview is rendered by UI. + + + *ddc-previewer-CommandPreviewer* +CommandPreviewer + Preview type which shows the command specified by the + |ddc-previewer-attribute-command|. + + *ddc-previewer-MarkdownPreviewer* +MarkdownPreviewer + Preview type which shows the markdown contents specified by the + |ddc-previewer-attribute-contents|. + + *ddc-previewer-TextPreviewer* +TextPreviewer + Preview type which shows the text contents specified by the + |ddc-previewer-attribute-contents|. + + +------------------------------------------------------------------------------ +PREVIEWER ATTRIBUTES *ddc-previewer-attributes* + + *ddc-previewer-attribute-command* +command (string) (Required) + Commands passed to |win_execute()| to render the preview. + NOTE: It is only avaiable in |ddc-previewer-CommandPreviewer|. + + *ddc-previewer-attribute-contents* +contents (string[]) (Required) + Contents to be shown in the preview buffer. + NOTE: It is only avaiable in |ddc-previewer-MarkdownPreviewer| + or |ddc-previewer-TextPreviewer|. + + *ddc-previewer-attribute-kind* +kind (string) (Required) + Previewer type. + It must be "command" or "markdown" or "text". + + "command" CommandPreviewer + "markdown" MarkdownPreviewer + "text" TextPreviewer + + ============================================================================== FREQUENTLY ASKED QUESTIONS (FAQ) *ddc-faq*