{"id":22756621,"url":"https://github.com/yukimemi/dvpm","last_synced_at":"2025-04-14T16:43:46.654Z","repository":{"id":165168255,"uuid":"640533859","full_name":"yukimemi/dvpm","owner":"yukimemi","description":"dvpm - Denops Vim/Neovim Plugin Manager","archived":false,"fork":false,"pushed_at":"2024-10-01T14:07:01.000Z","size":310,"stargazers_count":17,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-08T19:13:06.875Z","etag":null,"topics":["deno","denops","neovim","plugin-manager","vim","vim-denops"],"latest_commit_sha":null,"homepage":"https://jsr.io/@yukimemi/dvpm","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yukimemi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-14T12:16:02.000Z","updated_at":"2024-10-01T14:07:05.000Z","dependencies_parsed_at":"2024-01-05T07:25:40.935Z","dependency_job_id":"cd3fb8a9-a8cf-4bb2-8e83-a7c13a8701fa","html_url":"https://github.com/yukimemi/dvpm","commit_stats":null,"previous_names":[],"tags_count":114,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yukimemi%2Fdvpm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yukimemi%2Fdvpm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yukimemi%2Fdvpm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yukimemi%2Fdvpm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yukimemi","download_url":"https://codeload.github.com/yukimemi/dvpm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248918344,"owners_count":21183171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","denops","neovim","plugin-manager","vim","vim-denops"],"created_at":"2024-12-11T07:14:30.774Z","updated_at":"2025-04-14T16:43:46.647Z","avatar_url":"https://github.com/yukimemi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dvpm - Denops Vim/Neovim Plugin Manager !\n\n`dvpm` is a plugin manager for Vim and Neovim, powered by\n[denops.vim](https://github.com/vim-denops/denops.vim).\n\n- Vim / Neovim starts up very fast !\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/yukimemi/files/blob/main/dvpm/startuptime.png?raw=true\" title=\"startuptime\" /\u003e\n\u003c/div\u003e\n\n...but plugins are not loaded yet at startup ＼(^o^)／\n\nAll plugins are loaded lazily.\n\n- You can write all Vim / Neovim settings in typescript\n\n## Requirement\n\n- [Deno - A modern runtime for JavaScript and TypeScript](https://deno.land/)\n\n## Sample configuration\n\n### Neovim\n\n- ~/.config/nvim/init.lua (Mac / Linux)\n- ~/AppData/Local/nvim/init.lua (Windows)\n\n```lua\nlocal denops = vim.fn.expand(\"~/.cache/nvim/dvpm/github.com/vim-denops/denops.vim\")\nif not vim.loop.fs_stat(denops) then\n  vim.fn.system({ \"git\", \"clone\", \"https://github.com/vim-denops/denops.vim\", denops })\nend\nvim.opt.runtimepath:prepend(denops)\n```\n\n### Vim\n\n- `~/.vimrc` (Mac / Linux)\n- `~/_vimrc` (Windows)\n\n```vim\nlet s:denops = expand(\"~/.cache/vim/dvpm/github.com/vim-denops/denops.vim\")\nif !isdirectory(s:denops)\n  execute 'silent! !git clone https://github.com/vim-denops/denops.vim ' .. s:denops\nendif\nexecute 'set runtimepath^=' . substitute(fnamemodify(s:denops, ':p') , '[/\\\\]$', '', '')\n```\n\n---\n\n### Neovim\n\n- ~/.config/nvim/denops/config/main.ts (Mac / Linux)\n- ~/AppData/Local/nvim/denops/config/main.ts (Windows)\n\n### Vim\n\n- ~/.vim/denops/config/main.ts (Mac / Linux)\n- ~/vimfiles/denops/config/main.ts (Windows)\n\n```typescript\nimport type { Denops, Entrypoint } from \"jsr:@denops/std\";\nimport * as fn from \"jsr:@denops/std/function\";\nimport * as mapping from \"jsr:@denops/std/mapping\";\nimport * as vars from \"jsr:@denops/std/variable\";\nimport { ensure, is } from \"jsr:@core/unknownutil\";\nimport { execute } from \"jsr:@denops/std/helper\";\n\nimport { Dvpm } from \"jsr:@yukimemi/dvpm\";\n\nexport const main: Entrypoint = async (denops: Denops) =\u003e {\n  const base_path = (await fn.has(denops, \"nvim\")) ? \"~/.cache/nvim/dvpm\" : \"~/.cache/vim/dvpm\";\n  const base = ensure(await fn.expand(denops, base_path), is.String);\n\n  // First, call Dvpm.begin with denops object and base path.\n  const dvpm = await Dvpm.begin(denops, { base });\n\n  // URL only (GitHub).\n  await dvpm.add({ url: \"yukimemi/autocursor.vim\" });\n  // URL only (not GitHub).\n  await dvpm.add({ url: \"https://notgithub.com/some/other/plugin\" });\n  // With branch.\n  // await dvpm.add({ url: \"neoclide/coc.nvim\", branch: \"release\" });\n  // build option. Execute after install or update.\n  await dvpm.add({\n    url: \"neoclide/coc.nvim\",\n    branch: \"master\",\n    build: async ({ info }) =\u003e {\n      if (!info.isUpdate || !info.isLoad) {\n        // build option is called after git pull, even if there are no changes\n        // so you need to check for changes\n        return;\n      }\n      const args = [\"install\", \"--frozen-lockfile\"];\n      const cmd = new Deno.Command(\"yarn\", { args, cwd: info.dst });\n      const output = await cmd.output();\n      console.log(new TextDecoder().decode(output.stdout));\n    },\n  });\n  // shalow clone.\n  await dvpm.add({ url: \"yukimemi/chronicle.vim\", depth: 1 });\n  // before setting.\n  await dvpm.add({\n    url: \"yukimemi/silentsaver.vim\",\n    before: async ({ denops }) =\u003e {\n      await vars.g.set(\n        denops,\n        \"silentsaver_dir\",\n        ensure(await fn.expand(denops, \"~/.cache/nvim/silentsaver\"), is.String),\n      );\n    },\n  });\n  // after setting.\n  await dvpm.add({\n    url: \"folke/which-key.nvim\",\n    after: async ({ denops }) =\u003e {\n      await execute(denops, `lua require(\"which-key\").setup()`);\n    },\n  });\n  // dst setting. (for develop)\n  await dvpm.add({\n    url: \"yukimemi/spectrism.vim\",\n    dst: \"~/src/github.com/yukimemi/spectrism.vim\",\n    before: async ({ denops }) =\u003e {\n      await mapping.map(denops, \"\u003cspace\u003ero\", \"\u003ccmd\u003eChangeColorscheme\u003ccr\u003e\", {\n        mode: \"n\",\n      });\n      await mapping.map(\n        denops,\n        \"\u003cspace\u003erd\",\n        \"\u003ccmd\u003eDisableThisColorscheme\u003ccr\u003e\",\n        { mode: \"n\" },\n      );\n      await mapping.map(denops, \"\u003cspace\u003erl\", \"\u003ccmd\u003eLikeThisColorscheme\u003ccr\u003e\", {\n        mode: \"n\",\n      });\n      await mapping.map(denops, \"\u003cspace\u003erh\", \"\u003ccmd\u003eHateThisColorscheme\u003ccr\u003e\", {\n        mode: \"n\",\n      });\n    },\n  });\n  // Disable setting.\n  await dvpm.add({\n    url: \"yukimemi/hitori.vim\",\n    enabled: false,\n  });\n  // Disable with function.\n  await dvpm.add({\n    url: \"editorconfig/editorconfig-vim\",\n    enabled: async ({ denops }) =\u003e !(await fn.has(denops, \"nvim\")),\n  });\n  // With dependencies. dependencies plugin must be added.\n  await dvpm.add({ url: \"lambdalisue/askpass.vim\" });\n  await dvpm.add({ url: \"lambdalisue/guise.vim\" });\n  await dvpm.add({\n    url: \"lambdalisue/gin.vim\",\n    dependencies: [\n      \"lambdalisue/askpass.vim\",\n      \"lambdalisue/guise.vim\",\n    ],\n  });\n  // Load from file. ( `.lua` or `.vim` )\n  await dvpm.add({\n    url: \"rcarriga/nvim-notify\",\n    beforeFile: \"~/.config/nvim/rc/before/nvim-notify.lua\",\n    afterFile: \"~/.config/nvim/rc/after/nvim-notify.lua\",\n  });\n\n  // Finally, call Dvpm.end.\n  await dvpm.end();\n\n  console.log(\"Load completed !\");\n};\n```\n\nSee my dotfiles for more complex examples.\n\n[dotfiles/.config/nvim at main · yukimemi/dotfiles · GitHub](https://github.com/yukimemi/dotfiles/tree/main/.config/nvim)\n\n## API\n\n### Dvpm.begin\n\n```typescript\npublic static async begin(denops: Denops, dvpmOption: DvpmOption): Promise\u003cDvpm\u003e\n```\n\n```typescript\nexport type DvpmOption = {\n  // Base path for git clone.\n  base: string;\n  // Cache file path. See `Cache setting`.\n  cache?: string;\n  // debug print. Default is false.\n  debug?: boolean;\n  // If specified in profiles, only plugins that match the profiles specified in `Plug` will be loaded\n  // See `Profile setting`\n  profiles?: string[];\n  // Number of concurrent processes. Default is 8.\n  // This is used plugin install, update, source.\n  concurrency?: number;\n  // Use `vim.notify` for Install and Update log. Default is false. (Neovim only)\n  notify?: boolean;\n  // git log arg. Used for :DvpmUpdate command output. Default is [].\n  logarg?: string[];\n};\n```\n\n### Dvpm.end\n\n```typescript\npublic async end(): Promise\u003cvoid\u003e\n```\n\nAdd plugin to runtimepath and source plugin/*.vim and plugin/*.lua.\n\n### Dvpm.add\n\n```typescript\npublic async add(plug: Plug): Promise\u003cvoid\u003e\n```\n\n```typescript\nexport type Plug = {\n  // Github `username/repository` or URL that can be cloned with git.\n  url: string;\n  // The path to git clone. (Option)\n  dst?: string;\n  // Git branch or revision name. (Option)\n  rev?: string;\n  // clone depth. (Option)\n  depth?: number;\n  // enable or disable. Default is true.\n  enabled?: Bool;\n  // If profiles are specified in DvpmOption, the plugin will be enabled only if the profiles specified here are included in the profiles of DvpmOption.\n  profiles: string[];\n  // Processing to be performed before source plugin/*.vim and plugin/*.lua. (Option)\n  before?: ({\n    denops,\n    info,\n  }: {\n    denops: Denops;\n    info: PlugInfo;\n  }) =\u003e Promise\u003cvoid\u003e;\n  // Processing to be performed after source plugin/*.vim and plugin/*.lua. (Option)\n  after?: ({\n    denops,\n    info,\n  }: {\n    denops: Denops;\n    info: PlugInfo;\n  }) =\u003e Promise\u003cvoid\u003e;\n  // File path of processing to be performed before source plugin/*.vim and plugin/*.lua. (Option)\n  beforeFile?: string;\n  // File path of processing to be performed after source plugin/*.vim and plugin/*.lua. (Option)\n  afterFile?: string;\n  // build option. Execute after install or update. (Option)\n  // Executed even if there are no changes in the update\n  // Therefore, conditionally branch on `info.isLoad` and `info.isUpdate` as necessary\n  build?: ({\n    denops,\n    info,\n  }: {\n    denops: Denops;\n    info: PlugInfo;\n  }) =\u003e Promise\u003cvoid\u003e;\n  // Cache settings. See `Cache setting`.\n  cache?: {\n    enabled?: Bool;\n    before?: string;\n    after?: string;\n    beforeFile?: string;\n    afterFile?: string;\n  };\n  // Whether to git clone and update. Default is true. (Option)\n  // If this option is set to false, then `enabled` is also set to false.\n  clone?: Bool;\n  // dependencies. (Option)\n  dependencies?: string[];\n};\n```\n\n```typescript\nexport type Bool =\n  | boolean\n  | (({\n    denops,\n    info,\n  }: {\n    denops: Denops;\n    info: PlugInfo;\n  }) =\u003e Promise\u003cboolean\u003e);\n```\n\n`PlugInfo` type is almost same as `Plug`.\nContains the calculated results for each variable, such as `enabled`.\n\n### Dvpm.cache\n\n```typescript\npublic async cache(arg: { script: string; path: string }): Promise\u003cvoid\u003e\n```\n\nCache the script to path.\n\ne.g.\n\n```typescript\nawait dvpm.cache({\n  script: `\n    if !v:vim_did_enter \u0026\u0026 has('reltime')\n      let s:startuptime = reltime()\n      au VimEnter * ++once let s:startuptime = reltime(s:startuptime) | redraw\n            \\\\ | echomsg 'startuptime: ' .. reltimestr(s:startuptime)\n    endif\n  `,\n  path: \"~/.config/nvim/plugin/dvpm_cache.vim\",\n});\n\nawait dvpm.cache({\n  script: `\n    vim.g.loaded_2html_plugin = 1\n    vim.g.loaded_gzip = 1\n    vim.g.loaded_man = 1\n    vim.g.loaded_matchit = 1\n    vim.g.loaded_matchparen = 1\n    vim.g.loaded_netrwPlugin = 1\n    vim.g.loaded_tarPlugin = 1\n    vim.g.loaded_tutor_mode_plugin = 1\n    vim.g.loaded_zipPlugin = 1\n  `,\n  path: \"~/.config/nvim/plugin/dvpm_cache.lua\",\n});\n```\n\n### Dvpm.list\n\n```typescript\npublic list(): Plugin[]\n```\n\nIf you want a list of plugin information, you can get it with the dvpm.list() function. The return\nvalue is `Plugin[]`. See the [doc](https://jsr.io/@yukimemi/dvpm/doc/~/Plugin) for type information.\n\n## Command\n\n```vim\n:DvpmUpdate [url]\n```\n\nUpdate installed plugins.\n\nIf url is specified, update only target plugins, if not specified, update all plugins.\n\n```vim\n:DvpmList\n```\n\nIt outputs the list of plugins to the dvpm://list buffer.\n\n## Cache setting\n\nIf you want some plugins to be loaded before VimEnter, enable the `cache` setting. A sample\nconfiguration is shown below.\n\n```typescript\nexport const main: Entrypoint = async (denops: Denops) =\u003e {\n  const base_path = (await fn.has(denops, \"nvim\")) ? \"~/.cache/nvim/dvpm\" : \"~/.cache/vim/dvpm\";\n  const base = ensure(await fn.expand(denops, base_path), is.String);\n  const cache_path = (await fn.has(denops, \"nvim\"))\n    ? \"~/.config/nvim/plugin/dvpm_plugin_cache.vim\"\n    : \"~/.config/vim/plugin/dvpm_plugin_cache.vim\";\n  // This cache path must be pre-appended to the runtimepath.\n  // Add it in vimrc or init.lua by yourself, or specify the path originally added to\n  // runtimepath of Vim / Neovim.\n  const cache = ensure(await fn.expand(denops, cache_path), is.String);\n\n  // Specify `cache` to Dvpm.begin.\n  const dvpm = await Dvpm.begin(denops, { base, cache });\n\n  await dvpm.add({\n    url: \"tani/vim-artemis\",\n    // Just set `cache.enabled` to true if you don't need plugin settings.\n    cache: { enabled: true },\n  });\n  await dvpm.add({\n    url: \"nvim-lua/plenary.nvim\",\n    cache: { enabled: true },\n    enabled: async ({ denops }) =\u003e await fn.has(denops, \"nvim\"),\n  });\n\n  await dvpm.add({\n    url: \"startup-nvim/startup.nvim\",\n    // deno-lint-ignore require-await\n    enabled: async ({ denops }) =\u003e denops.meta.host === \"nvim\",\n    // Specify `before` or `after` if you need to configure the plugin.\n    // `before` is executed before the plugin is added to the runtimepath.\n    // `after` runs after the plugin is added to the runtimepath.\n    cache: {\n      before: `echomsg \"Load startup !\"`,\n      after: `\n        lua require(\"startup\").setup({ theme = \"startify\" })\n      `,\n    },\n  });\n\n  await dvpm.add({\n    url: \"rcarriga/nvim-notify\",\n    enabled: async ({ denops }) =\u003e await fn.has(denops, \"nvim\"),\n    cache: {\n      // `before` and `after` can be set independently.\n      after: `\n        lua \u003c\u003c EOB\n          require(\"notify\").setup({\n            stages = \"slide\",\n          })\n          vim.notify = require(\"notify\")\n        EOB\n      `,\n      // If you want to read it in a separate file, specify as follows. (.lua and .vim can be specified)\n      // afterFile: \"~/.config/nvim/rc/after/notify.lua\",\n    },\n  });\n\n  // Finally, call Dvpm.end.\n  await dvpm.end();\n};\n```\n\nAfter performing the above settings, when you start Vim / Neovim, the following should be output to\nthe file specified as `cache` in `Dvpm.begin`. And the next time Vim / Neovim starts, the plugin\nwill be enabled before `VimEnter`.\n\n- `~/.config/nvim/plugin/dvpm_plugin_cache.vim` (for Neovim)\n\n```\n\" This file is generated by dvpm.\nset runtimepath+=/Users/yukimemi/.cache/nvim/dvpm/github.com/tani/vim-artemis\nset runtimepath+=/Users/yukimemi/.cache/nvim/dvpm/github.com/nvim-lua/plenary.nvim\nechomsg \"Load startup !\"\nset runtimepath+=/Users/yukimemi/.cache/nvim/dvpm/github.com/startup-nvim/startup.nvim\nlua require(\"startup\").setup({theme = \"startify\"})\nset runtimepath+=/Users/yukimemi/.cache/nvim/dvpm/github.com/rcarriga/nvim-notify\nlua \u003c\u003c EOB\nrequire(\"notify\").setup({\nstages = \"slide\",\n})\nvim.notify = require(\"notify\")\nEOB\n```\n\n## Autocmd\n\n- DvpmCacheUpdated\n\nFires after updating the cache.\n\ne.g.\n\n```typescript\nimport * as autocmd from \"jsr:@denops/std/autocmd\";\n\n~~~\n\nawait autocmd.define(denops, \"User\", \"DvpmCacheUpdated\", \"echo 'dvpm cache updated !'\");\n```\n\n## Profile setting\n\nIf `profiles` is specified in `DvpmOption`, the plugins to be enabled can be restricted by the specified profile.\n\ne.g.\n\n```typescript\n~~~\nexport const main: Entrypoint = async (denops: Denops) =\u003e {\n  const base_path = (await fn.has(denops, \"nvim\")) ? \"~/.cache/nvim/dvpm\" : \"~/.cache/vim/dvpm\";\n  const base = ensure(await fn.expand(denops, base_path), is.String);\n\n  const dvpm = await Dvpm.begin(denops, {\n    base,\n    // Use only minimal plugins\n    profiles: [\"minimal\"],\n  });\n\n  await dvpm.add({\n    url: \"yukimemi/chronicle.vim\",\n    profiles: [\"minimal\"],\n  });\n  await dvpm.add({\n    url: \"yukimemi/silentsaver.vim\",\n    profiles: [\"default\"],\n  });\n  await dvpm.add({\n    url: \"yukimemi/autocursor.vim\",\n    profiles: [\"full\"],\n  });\n\n  await dvpm.end();\n};\n```\n\nIn this case, only `yukimemi/chronicle.vim` is enabled.\n\ne.g.\n\n```typescript\n~~~\nexport const main: Entrypoint = async (denops: Denops) =\u003e {\n  const base_path = (await fn.has(denops, \"nvim\")) ? \"~/.cache/nvim/dvpm\" : \"~/.cache/vim/dvpm\";\n  const base = ensure(await fn.expand(denops, base_path), is.String);\n\n  const dvpm = await Dvpm.begin(denops, {\n    base,\n    // Use only minimal and default plugins\n    profiles: [\"minimal\", \"default\"],\n  });\n\n  await dvpm.add({\n    url: \"yukimemi/chronicle.vim\",\n    profiles: [\"minimal\"],\n  });\n  await dvpm.add({\n    url: \"yukimemi/silentsaver.vim\",\n    profiles: [\"default\"],\n  });\n  await dvpm.add({\n    url: \"yukimemi/autocursor.vim\",\n    profiles: [\"full\"],\n  });\n\n  await dvpm.end();\n};\n```\n\nIn this case, `yukimemi/chronicle.vim` and `yukimemi/silentsaver.vim` are enabled.\n\nIf you specify `[\"minimal\", \"default\", \"full\"]` in `DvpmOption.profiles`, all three plugins will be enabled.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyukimemi%2Fdvpm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyukimemi%2Fdvpm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyukimemi%2Fdvpm/lists"}