From 320e96a89e3e756bb4ae54764495b3caf620752f Mon Sep 17 00:00:00 2001 From: Shougo Matsushita Date: Fri, 21 Jun 2024 11:27:45 +0900 Subject: [PATCH] Add multiple_hooks --- autoload/dpp/min.vim | 3 +- autoload/dpp/util.vim | 45 +++++++++++++++++++------ denops/dpp/base/config.ts | 8 +++++ denops/dpp/dpp.ts | 70 +++++++++++++++++++++++++++++++++------ denops/dpp/types.ts | 6 +++- 5 files changed, 110 insertions(+), 22 deletions(-) diff --git a/autoload/dpp/min.vim b/autoload/dpp/min.vim index 7d2bd51..53ea7bc 100644 --- a/autoload/dpp/min.vim +++ b/autoload/dpp/min.vim @@ -20,7 +20,7 @@ function dpp#min#load_state(path, name=v:progname->fnamemodify(':r')) abort endtry endfunction function dpp#min#_init() abort - const g:dpp#_state_version = 1 + const g:dpp#_state_version = 2 const g:dpp#_is_sudo = $SUDO_USER !=# '' && $USER !=# $SUDO_USER \ && $HOME !=# ('~'.$USER)->expand() \ && $HOME ==# ('~'.$SUDO_USER)->expand() @@ -36,6 +36,7 @@ function dpp#min#_init() abort let g:dpp#_plugins = {} let g:dpp#_options = {} let g:dpp#_check_files = [] + let g:dpp#_multiple_hooks = [] augroup dpp autocmd! diff --git a/autoload/dpp/util.vim b/autoload/dpp/util.vim index 40d760b..1c207d2 100644 --- a/autoload/dpp/util.vim +++ b/autoload/dpp/util.vim @@ -95,16 +95,39 @@ function dpp#util#_call_hook(hook_name, plugins = []) abort \ && (!val->has_key('if') || val.if->eval()) \ }) for plugin in plugins - call dpp#util#_execute_hook(plugin, hook, plugin[hook]) + call dpp#util#_execute_hook(plugin, hook, plugin.name, plugin[hook]) endfor + + if a:hook_name ==# 'source' || a:hook_name ==# 'post_source' + " Check multiple_hooks + for hooks in g:dpp#_multiple_hooks + if hooks->get(hook, '') ==# '' + continue + endif + + if hooks.plugins->len() ==# + \ dpp#util#_get_plugins(hooks.plugins) + \ ->filter({ _, val -> val.sourced })->len() + " All plugins are sourced + + call dpp#util#_execute_hook( + \ {}, hook, string(hooks.plugins), hooks[hook]) + + " Skip twice call + let hooks[hook] = '' + endif + endfor + endif endfunction -function dpp#util#_execute_hook(plugin, hook_name, hook) abort +function dpp#util#_execute_hook(plugin, hook_name, plugin_name, hook) abort " Skip twice call - if !a:plugin->has_key('called') - let a:plugin.called = {} - endif - if a:plugin.called->has_key(a:hook->string()) - return + if !a:plugin->empty() + if !a:plugin->has_key('called') + let a:plugin.called = {} + endif + if a:plugin.called->has_key(a:hook->string()) + return + endif endif try @@ -116,15 +139,17 @@ function dpp#util#_execute_hook(plugin, hook_name, hook) abort else call execute(cmds, '') endif - - let a:plugin.called[string(a:hook)] = v:true catch call dpp#util#_error( \ printf('Error occurred while executing %s: %s', \ a:hook_name, - \ a:plugin->get('name', 'g:dpp#_hook_add'))) + \ a:plugin_name)) call dpp#util#_error(v:exception) endtry + + if !a:plugin->empty() + let a:plugin.called[string(a:hook)] = v:true + endif endfunction function dpp#util#_tsort(plugins) abort diff --git a/denops/dpp/base/config.ts b/denops/dpp/base/config.ts index fa7d4f6..a83a399 100644 --- a/denops/dpp/base/config.ts +++ b/denops/dpp/base/config.ts @@ -10,10 +10,18 @@ export type ConfigArguments = { name: string; }; +export type MultipleHook = { + hook_add?: string; + hook_post_source?: string; + hook_source?: string; + plugins: string[]; +}; + export type ConfigReturn = { checkFiles?: string[]; ftplugins?: Record; hooksFiles?: string[]; + multipleHooks?: MultipleHook[]; plugins: Plugin[]; stateLines?: string[]; }; diff --git a/denops/dpp/dpp.ts b/denops/dpp/dpp.ts index 16addd4..ad11236 100644 --- a/denops/dpp/dpp.ts +++ b/denops/dpp/dpp.ts @@ -65,6 +65,23 @@ export class Dpp { const hasWindows = await fn.has(denops, "win32"); const hasLua = denops.meta.host === "nvim" || await fn.has(denops, "lua"); + const multipleHooks = configReturn.multipleHooks ?? []; + // Convert head backslashes + for (const hooks of multipleHooks) { + if (hooks.hook_add) { + hooks.hook_add = hooks.hook_add.replaceAll( + /\n\s*\\/g, + "", + ); + } + if (hooks.hook_source) { + hooks.hook_source = hooks.hook_source.replaceAll( + /\n\s*\\/g, + "", + ); + } + } + // Initialize plugins const protocols = await getProtocols(denops, this.#loader, options); const recordPlugins: Record = {}; @@ -164,14 +181,15 @@ export class Dpp { // Add plugins runtimepath const depends = new Set(); - const nonLazyPlugins = Object.values(recordPlugins).filter((plugin) => + const availablePlugins = Object.values(recordPlugins).filter(async ( + plugin, + ) => plugin.path && await isDirectory(plugin.path) && await checkIf(plugin)); + const nonLazyPlugins = availablePlugins.filter((plugin) => !plugin.lazy ); const hookSources = []; for (const plugin of nonLazyPlugins) { - if ( - !plugin.rtp || !await isDirectory(plugin.rtp) || !await checkIf(plugin) - ) { + if (!plugin.rtp || !await isDirectory(plugin.rtp)) { continue; } @@ -226,7 +244,13 @@ export class Dpp { let startupLines = [ `if g:dpp#_state_version !=# ${stateVersion}` + `| throw "State version error" | endif`, - "let [g:dpp#_plugins, g:dpp#ftplugin, g:dpp#_options, g:dpp#_check_files] = g:dpp#_state", + "let [" + + "g:dpp#_plugins," + + "g:dpp#ftplugin," + + "g:dpp#_options," + + "g:dpp#_check_files," + + "g:dpp#_multiple_hooks" + + "] = g:dpp#_state", `let g:dpp#_config_path = '${configPath}'`, `let &runtimepath = '${newRuntimepath}'`, ]; @@ -295,11 +319,7 @@ export class Dpp { } } - for (const plugin of Object.values(recordPlugins)) { - if (!plugin.path || !await isDirectory(plugin.path)) { - continue; - } - + for (const plugin of availablePlugins) { if (plugin.hooks_file) { for (const hooksFile of convert2List(plugin.hooks_file)) { checkFiles.push(hooksFile); @@ -315,6 +335,35 @@ export class Dpp { } } + // Check hook_add for multipleHooks + const availablePluginNames = availablePlugins.map((plugin) => + plugin.name + ); + const nonLazyPluginNames = nonLazyPlugins.map((plugin) => + plugin.name + ); + for (const hooks of multipleHooks) { + if ( + hooks.hook_add && + hooks.plugins.every((pluginName) => + availablePluginNames.includes(pluginName) + ) + ) { + startupLines.push(hooks.hook_add); + hooks.hook_add = ""; + } + + if ( + hooks.hook_source && + hooks.plugins.every((pluginName) => + nonLazyPluginNames.includes(pluginName) + ) + ) { + hookSources.push(hooks.hook_source); + hooks.hook_source = ""; + } + } + // Merge non lazy plugins hook_source startupLines = startupLines.concat(hookSources); @@ -333,6 +382,7 @@ export class Dpp { {}, options, checkFiles, + multipleHooks, ]), ]; await Deno.writeTextFile(stateFile, stateLines.join("\n")); diff --git a/denops/dpp/types.ts b/denops/dpp/types.ts index c8abf22..9de059d 100644 --- a/denops/dpp/types.ts +++ b/denops/dpp/types.ts @@ -3,7 +3,11 @@ import { BaseProtocol, BaseProtocolParams } from "./base/protocol.ts"; import { Denops } from "./deps.ts"; export { BaseConfig } from "./base/config.ts"; -export type { ConfigArguments, ConfigReturn } from "./base/config.ts"; +export type { + ConfigArguments, + ConfigReturn, + MultipleHook, +} from "./base/config.ts"; export { BaseExt } from "./base/ext.ts"; export type { BaseExtParams } from "./base/ext.ts"; export { BaseProtocol } from "./base/protocol.ts";