From 0903aeffa899243057f071e26f3312fd8045ebfd Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 10 Aug 2023 16:03:12 +0900 Subject: [PATCH 1/5] Add Previewer --- autoload/ddc.vim | 5 +++++ denops/ddc/app.ts | 7 +++++++ denops/ddc/base/source.ts | 20 +++++++++++++++++++- denops/ddc/ddc.ts | 32 ++++++++++++++++++++++++++++++++ denops/ddc/types.ts | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/autoload/ddc.vim b/autoload/ddc.vim index 3f65e503..cd170114 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) abort + return ddc#_denops_running() ? + \ denops#request('ddc', 'getPreviewer', [a:item]) : {} +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..a41b387f 100644 --- a/denops/ddc/app.ts +++ b/denops/ddc/app.ts @@ -7,6 +7,7 @@ import { DdcOptions, DdcUserData, Item, + Previewer, UserOptions, } from "./types.ts"; import { Denops, ensure, is, Lock, toFileUrl, vars } from "./deps.ts"; @@ -107,6 +108,12 @@ export function main(denops: Denops) { getCurrent(): Promise { return Promise.resolve(contextBuilder.getCurrent(denops)); }, + async getPreviewer(arg1: unknown): Promise { + const [_skip, context, options] = await contextBuilder + .createContext(denops, "Manual"); + const item = ensure(arg1, is.Record) as DdcItem; + return await ddc.getPreviewer(denops, context, options, item); + }, 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..c61defcb 100644 --- a/denops/ddc/base/source.ts +++ b/denops/ddc/base/source.ts @@ -2,8 +2,10 @@ import { Context, DdcEvent, DdcGatherItems, + DdcItem, DdcOptions, OnCallback, + Previewer, SourceOptions, } from "../types.ts"; import { Denops } from "../deps.ts"; @@ -40,6 +42,15 @@ export type OnCompleteDoneArguments< userData: UserData; }; +export type GetPreviewerArguments = { + denops: Denops; + context: Context; + options: DdcOptions; + sourceOptions: SourceOptions; + sourceParams: Params; + item: DdcItem; +}; + export type GetCompletePositionArguments = { denops: Denops; context: Context; @@ -67,7 +78,7 @@ export abstract class BaseSource< > { name = ""; isInitialized = false; - apiVersion = 5; + apiVersion = 6; events: DdcEvent[] = []; isBytePos = false; @@ -80,6 +91,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..5cb9330b 100644 --- a/denops/ddc/ddc.ts +++ b/denops/ddc/ddc.ts @@ -15,6 +15,7 @@ import { FilterOptions, Item, OnCallback, + Previewer, SourceName, SourceOptions, UiOptions, @@ -883,6 +884,37 @@ export class Ddc { return [filter, filterOptions, filterParams]; } + + async getPreviewer( + denops: Denops, + context: Context, + options: DdcOptions, + item: DdcItem, + ): 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, + }); + + return previewer; + } } function formatAbbr(word: string, abbr: string | undefined): string { diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index 65069893..4e8208e7 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -153,3 +153,42 @@ export interface CallbackContext { revoke(): void; createOnCallback(): OnCallback; } + +export type CommandPreviewer = { + kind: "command"; + + /** + * Command passed to `win_execute()` to render the preview + */ + command: string; +}; + +type TextPreviewer = { + kind: "text"; + + /** + * Path of file to preview + */ + text: string; +}; + +type MarkdownPreviewer = { + kind: "markdown"; + + /** + * Path of file to preview + */ + text: string; +}; + +type EmptyPreviewer = Record; + +/** + * Previewer defines how the preview is rendered + * This must be implemented in the ddc-source + */ +export type Previewer = + | EmptyPreviewer + | CommandPreviewer + | TextPreviewer + | MarkdownPreviewer; From f9cff36a8ef862a92390d34eda7fd4719cdd420d Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 10 Aug 2023 16:13:34 +0900 Subject: [PATCH 2/5] Update the documentation --- denops/ddc/types.ts | 29 ++++++++++----------------- doc/ddc.txt | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index 4e8208e7..a9986920 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -154,34 +154,25 @@ export interface CallbackContext { createOnCallback(): OnCallback; } +type EmptyPreviewer = Record; + export type CommandPreviewer = { kind: "command"; - /** - * Command passed to `win_execute()` to render the preview - */ command: string; }; -type TextPreviewer = { - kind: "text"; - - /** - * Path of file to preview - */ - text: string; -}; - type MarkdownPreviewer = { kind: "markdown"; - /** - * Path of file to preview - */ - text: string; + contents: string; }; -type EmptyPreviewer = Record; +type TextPreviewer = { + kind: "text"; + + contents: string; +}; /** * Previewer defines how the preview is rendered @@ -190,5 +181,5 @@ type EmptyPreviewer = Record; export type Previewer = | EmptyPreviewer | CommandPreviewer - | TextPreviewer - | MarkdownPreviewer; + | MarkdownPreviewer + | TextPreviewer; diff --git a/doc/ddc.txt b/doc/ddc.txt index 69d3cdbb..3e89876d 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| @@ -1061,6 +1063,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* From 287116cc381eb779227ca46a1eba3c22d5633935 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 10 Aug 2023 16:16:51 +0900 Subject: [PATCH 3/5] Update the documentation --- doc/ddc.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/ddc.txt b/doc/ddc.txt index 3e89876d..9f4a994f 100644 --- a/doc/ddc.txt +++ b/doc/ddc.txt @@ -319,6 +319,11 @@ ddc#enable_terminal_completion() NOTE: It is experimental feature in Vim. neovim is recommended. + *ddc#get_previewer()* +ddc#get_previewer({item}) + Get |ddc-previewer| from {item}. + It is useful to render preview information dynamically. + *ddc#hide()* ddc#hide([{event}]) Hide current completion UI. @@ -935,6 +940,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. From 593fd59bcb0adcf2fcfad2742314870218ff4448 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 10 Aug 2023 16:21:50 +0900 Subject: [PATCH 4/5] Fix contents type --- denops/ddc/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index a9986920..7528beca 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -165,13 +165,13 @@ export type CommandPreviewer = { type MarkdownPreviewer = { kind: "markdown"; - contents: string; + contents: string[]; }; type TextPreviewer = { kind: "text"; - contents: string; + contents: string[]; }; /** From 5b7572e88cb5b56dfcc20dfac5f38041694a0496 Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Thu, 10 Aug 2023 18:57:33 +0900 Subject: [PATCH 5/5] Add PreviewContext --- autoload/ddc.vim | 4 ++-- denops/ddc/app.ts | 12 ++++++++++-- denops/ddc/base/source.ts | 2 ++ denops/ddc/ddc.ts | 3 +++ denops/ddc/types.ts | 12 ++++++++++++ doc/ddc.txt | 3 ++- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/autoload/ddc.vim b/autoload/ddc.vim index cd170114..a304cbdd 100644 --- a/autoload/ddc.vim +++ b/autoload/ddc.vim @@ -110,9 +110,9 @@ function ddc#visible() abort \ denops#request('ddc', 'visible', []) : v:false endfunction -function ddc#get_previewer(item) abort +function ddc#get_previewer(item, context={}) abort return ddc#_denops_running() ? - \ denops#request('ddc', 'getPreviewer', [a:item]) : {} + \ denops#request('ddc', 'getPreviewer', [a:item, a:context]) : {} endfunction function ddc#register(type, path) abort diff --git a/denops/ddc/app.ts b/denops/ddc/app.ts index a41b387f..8a1ab7f2 100644 --- a/denops/ddc/app.ts +++ b/denops/ddc/app.ts @@ -7,6 +7,7 @@ import { DdcOptions, DdcUserData, Item, + PreviewContext, Previewer, UserOptions, } from "./types.ts"; @@ -108,11 +109,18 @@ export function main(denops: Denops) { getCurrent(): Promise { return Promise.resolve(contextBuilder.getCurrent(denops)); }, - async getPreviewer(arg1: unknown): Promise { + async getPreviewer(arg1: unknown, arg2: unknown): Promise { const [_skip, context, options] = await contextBuilder .createContext(denops, "Manual"); const item = ensure(arg1, is.Record) as DdcItem; - return await ddc.getPreviewer(denops, context, options, item); + 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 () => { diff --git a/denops/ddc/base/source.ts b/denops/ddc/base/source.ts index c61defcb..0b511f1c 100644 --- a/denops/ddc/base/source.ts +++ b/denops/ddc/base/source.ts @@ -5,6 +5,7 @@ import { DdcItem, DdcOptions, OnCallback, + PreviewContext, Previewer, SourceOptions, } from "../types.ts"; @@ -49,6 +50,7 @@ export type GetPreviewerArguments = { sourceOptions: SourceOptions; sourceParams: Params; item: DdcItem; + previewContext: PreviewContext; }; export type GetCompletePositionArguments = { diff --git a/denops/ddc/ddc.ts b/denops/ddc/ddc.ts index 5cb9330b..b397359f 100644 --- a/denops/ddc/ddc.ts +++ b/denops/ddc/ddc.ts @@ -15,6 +15,7 @@ import { FilterOptions, Item, OnCallback, + PreviewContext, Previewer, SourceName, SourceOptions, @@ -890,6 +891,7 @@ export class Ddc { context: Context, options: DdcOptions, item: DdcItem, + previewContext: PreviewContext, ): Promise { if (!item.__sourceName) { return {}; @@ -911,6 +913,7 @@ export class Ddc { sourceOptions, sourceParams, item, + previewContext, }); return previewer; diff --git a/denops/ddc/types.ts b/denops/ddc/types.ts index 7528beca..ee9be91f 100644 --- a/denops/ddc/types.ts +++ b/denops/ddc/types.ts @@ -154,6 +154,18 @@ export interface CallbackContext { 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 = { diff --git a/doc/ddc.txt b/doc/ddc.txt index 9f4a994f..8ff69fef 100644 --- a/doc/ddc.txt +++ b/doc/ddc.txt @@ -320,8 +320,9 @@ ddc#enable_terminal_completion() recommended. *ddc#get_previewer()* -ddc#get_previewer({item}) +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()*