├── .gitignore ├── .luarc.json ├── LICENSE ├── README.md └── init.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /.luarc.json: -------------------------------------------------------------------------------- 1 | { 2 | "Lua": { 3 | "diagnostics": { 4 | "globals": ["vis"] 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Erlend Lind Madsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vis-plug 🍜 2 | 3 | A minimal plugin-manager for [vis](https://github.com/martanne/vis) 4 | 5 | `vis-plug` plugins are defined by a Lua file in a git repository and can be both a [plugin](https://github.com/martanne/vis/wiki/Plugins) or a [theme](https://github.com/martanne/vis/wiki/Themes). 6 | 7 | [Configure](#Configure) plugins in your `visrc` and use [Commands](#Commands) to install and more. 8 | 9 | Plugins are installed using `git` (in the background) to a cache folder and required on `init`. 10 | 11 | ## Install 12 | 13 | git clone `vis-plug` and require it in your `visrc`. 14 | 15 | You can use this one-liner to install `vis-plug` and then require it in your `visrc`: 16 | 17 | ```sh 18 | [ -n "${XDG_CONFIG_HOME:-$HOME}" ] && [ -d "${XDG_CONFIG_HOME:-$HOME/.config}/vis/plugins" ] && git clone https://github.com/erf/vis-plug.git "${XDG_CONFIG_HOME:-$HOME/.config}/vis/plugins/vis-plug" || echo "Error: The plugin path could not be determined or does not exist. Ensure XDG_CONFIG_HOME or HOME is set and that the path exists." 19 | ``` 20 | 21 | Alternatively, you can add the following to your `visrc` to automatically fetch `vis-plug` to your plugins folder and require it: 22 | 23 | ```lua 24 | local plug = (function() if not pcall(require, 'plugins/vis-plug') then 25 | os.execute('git clone --quiet https://github.com/erf/vis-plug ' .. 26 | (os.getenv('XDG_CONFIG_HOME') or os.getenv('HOME') .. '/.config') 27 | .. '/vis/plugins/vis-plug') 28 | end return require('plugins/vis-plug') end)() 29 | ``` 30 | 31 | ## Configure 32 | 33 | Configure plugins in your `visrc` as a list of tables given to the `plug.init` method. 34 | 35 | Example: 36 | 37 | ```Lua 38 | 39 | local plug = require('plugins/vis-plug') 40 | 41 | -- configure plugins in an array of tables with git urls and options 42 | local plugins = { 43 | 44 | -- load a plugin given a repo (https://github.com/ can be omitted and expects a 'init.lua' file) 45 | { 'erf/vis-cursors' }, 46 | 47 | -- first parameter is a shorthand for 'url' 48 | { url = 'erf/vis-cursors' }, 49 | 50 | -- specify the lua file to require (or theme to set) and give a ref (commit, branch, tag) to checkout 51 | { 'erf/vis-test', file = 'test', ref = 'some-branch' }, 52 | 53 | -- specify an alias to later use to access plugin variables (see example below) 54 | { 'erf/vis-highlight', alias = 'hi' }, 55 | 56 | -- configure themes by setting 'theme = true'. The theme 'file' will be set on INIT 57 | { 'samlwood/vis-gruvbox', theme = true, file = 'gruvbox' }, 58 | } 59 | 60 | -- require and optionally install plugins on init 61 | plug.init(plugins, true) 62 | 63 | -- access plugins via alias 64 | plug.plugins.hi.patterns[' +\n'] = { style = 'back:#444444' } 65 | ``` 66 | 67 | Each plugin table can have the following options: 68 | 69 | - `url` - the url to the git repo (`https://github.com or https://` can be omitted) 70 | - `file` - the relative path to the lua file (defaults to `init`, skip the `.lua` part) (optional) 71 | - `ref` - checkout a spesific commit, branch or tag (optional) 72 | - `alias` - access plugins via `plug.plugins.{alias}` (optional) 73 | - `theme` - set `theme = true` if theme; will set theme on INIT event (optional) 74 | 75 | ### Install on init 76 | 77 | Pass _true_ as second argument to `init` to install on init. 78 | 79 | ```Lua 80 | require('plugins/vis-plug').init(plugins, true) 81 | ``` 82 | 83 | ### Install path 84 | 85 | Plugins are installed (cloned) to the following path (in this order): 86 | 87 | `(VIS_PLUG_HOME|(XDG_CACHE_HOME|HOME/.cache)/vis-plug)/{plugins|themes}` 88 | 89 | Use `plug.path` to set a custom install path: 90 | 91 | ```Lua 92 | plug.path('/Users/user/my-plugins') 93 | ``` 94 | 95 | ### Themes 96 | 97 | Install themes using the `{ theme = true, file = 'somepath/theme-file' }` option (don't include .lua) 98 | 99 | The first theme in the config table is set on the `INIT` event. 100 | 101 | Example theme: 102 | 103 | ``` 104 | local plugins = { 105 | { 'timoha/vis-acme', theme = true, file = 'acme' }, 106 | } 107 | ``` 108 | 109 | ## Commands 110 | 111 | We support the following `vis` commands: 112 | 113 | `:plug-list` - list plugins and themes 114 | 115 | `:plug-install` - install plugins (git clone) 116 | 117 | `:plug-update` - update outdated plugins (git pull) 118 | 119 | `:plug-outdated` - check if plugins are up-to-date 120 | 121 | `:plug-upgrade` - upgrade to latest vis-plug using git pull 122 | 123 | `:plug-remove` - delete plugin by {name} (`:plug-list` for names) 124 | 125 | `:plug-clean` - delete all plugins from disk 126 | 127 | `:plug-checkout` - checkout {name} {commit|branch|tag} 128 | 129 | `:plug-commands` - list commands (these) 130 | 131 | ## vis-plugins 132 | 133 | I've created [vis-plugins](https://github.com/erf/vis-plugins) - a web page with is a list of plugins and themes based on the [vis wiki](https://github.com/martanne/vis/wiki). 134 | 135 | It's hosted by github at [https://erf.github.io/vis-plugins](https://erf.github.io/vis-plugins) 136 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | -- the required plugins are stored here 4 | M.plugins = {} 5 | 6 | -- the plugins configurations set in visrc.lua 7 | local plugins_conf = {} 8 | 9 | -- the dir where we store plugins on disk 10 | local plugins_path = nil 11 | 12 | -- we store commands in a list of tables {name, func, desc} 13 | local command_list = {} 14 | 15 | -- add a searcher to find plugins by filename, not module path 16 | table.insert(package.searchers, function(name) 17 | local file, err = package.searchpath(name, package.path, '', '') -- don't replace . with / 18 | if file then 19 | return loadfile(file), file 20 | else 21 | return nil, err 22 | end 23 | end) 24 | 25 | -- set custom path and add it first to package.path for require 26 | M.path = function(path) 27 | plugins_path = path 28 | package.path = path .. '/?.lua;' .. path .. '/?/init.lua;' .. package.path 29 | end 30 | 31 | -- e.g. /Users/some-user/.cache/vis-plug 32 | local get_plugins_path = function() 33 | local VIS_PLUG_HOME = os.getenv('VIS_PLUG_HOME') 34 | local XDG_CACHE_HOME = os.getenv('XDG_CACHE_HOME') 35 | local HOME_CACHE = os.getenv('HOME') .. '/.cache' 36 | return VIS_PLUG_HOME or (XDG_CACHE_HOME or HOME_CACHE) .. '/vis-plug' 37 | end 38 | 39 | -- set default install path for plugins 40 | M.path(get_plugins_path()) 41 | 42 | -- execute a command and return result string 43 | local execute = function(command) 44 | local file = io.popen(command) 45 | if not file then 46 | return nil 47 | end 48 | local result = file:read("*a") 49 | result = result:gsub('(.-)%s*$', '%1') -- strip trailing spaces 50 | local success, message, code = file:close() 51 | return result, success, message, code 52 | end 53 | 54 | -- check if file exists 55 | local file_exists = function(path) 56 | local file = io.open(path) 57 | if not file then 58 | return false 59 | end 60 | file:close() 61 | return true 62 | end 63 | 64 | -- get plugin name from repo dir 65 | -- E.g. https://github.com/erf/{vis-highlight}.git -> vis-highlight 66 | local get_name_from_url = function(url) 67 | return url:match('^.*/([^.]+)') 68 | end 69 | 70 | -- get the dir from the given file 71 | local get_dir_from_file = function(file) 72 | return file:match('(.+)%/.+$') 73 | end 74 | 75 | -- separate folders in $VIS_PLUG_HOME/{plugins|themes} 76 | local get_folder = function(theme) 77 | if theme then 78 | return '/themes' 79 | else 80 | return '/plugins' 81 | end 82 | end 83 | 84 | -- E.g. '~/$VIS_PLUG_HOME/plugins/' 85 | local get_base_path = function(theme) 86 | return plugins_path .. get_folder(theme) 87 | end 88 | 89 | -- get path to file 90 | local get_file_path = function(plug) 91 | return plug.path .. '/' .. plug.file .. '.lua' 92 | end 93 | 94 | -- '{http[s]://github.com}/erf/vis-cursors.git' 95 | local is_github_url = function(url) 96 | return url:find('^http[s]?://github.com.+') ~= nil 97 | end 98 | 99 | -- return true if has the protocol part of the url 100 | -- '{https://}github.com/erf/vis-cursors.git' 101 | local is_host_url = function(url) 102 | return url:find('^.+://') ~= nil 103 | end 104 | 105 | -- return true if has the protocol part of the url 106 | -- '{github.com/}erf/vis-cursors.git' 107 | local is_no_host_url = function(url) 108 | return url:find('^%w+%.%w+[^/]') ~= nil 109 | end 110 | 111 | -- [user@]server:project.git 112 | local is_short_ssh_url = function(url) 113 | return url:find('^.+@.+:.+') 114 | end 115 | 116 | -- remove protocol from url to make it shorter for output 117 | local get_short_url = function(url) 118 | if is_github_url(url) then 119 | return url:match('^.+://.-/(.*)') 120 | elseif is_host_url(url) then 121 | return url:match('^.+://(.*)') 122 | elseif is_short_ssh_url(url) then 123 | return url -- TODO shorten? 124 | else 125 | return url 126 | end 127 | end 128 | 129 | -- given a github short hand url, return the full url 130 | -- E.g. 'erf/vis-cursors' -> 'https://github.com/erf/vis-cursors.git' 131 | local get_full_url = function(url) 132 | if is_host_url(url) then 133 | return url 134 | elseif is_no_host_url(url) then 135 | return 'https://' .. url 136 | elseif is_short_ssh_url(url) then 137 | return url 138 | else 139 | return 'https://github.com/' .. url 140 | end 141 | end 142 | 143 | -- find the plug in conf by name, used by plug-rm 144 | local get_plug_by_name = function(name) 145 | if name == nil then 146 | return nil 147 | end 148 | for _, plug in ipairs(plugins_conf) do 149 | if plug.name == name then 150 | return plug 151 | end 152 | end 153 | end 154 | 155 | -- iterate the plugins conf and call an operation per plugin 156 | local for_each_plugin = function(func, args) 157 | for _, plug in ipairs(plugins_conf) do 158 | func(plug, args) 159 | end 160 | end 161 | 162 | -- prepare the plug configuration 163 | local plug_init = function(plug, args) 164 | plug.file = plug.file or '' 165 | plug.url = get_full_url(plug.url or plug[1]) 166 | plug.name = get_name_from_url(plug.url) 167 | plug.path = get_base_path(plug.theme) .. '/' .. plug.name 168 | end 169 | 170 | -- checkout specific commit, branch or tag 171 | local checkout = function(plug) 172 | if plug.ref then 173 | vis:info('Checking out ' .. plug.ref .. ' for ' .. plug.name) 174 | os.execute('git -C ' .. plug.path .. ' checkout --quiet ' .. plug.ref) 175 | end 176 | -- If no ref is specified, do nothing and keep current state 177 | end 178 | 179 | local plug_require = function(plug, args) 180 | if not file_exists(plug.path) then 181 | return 182 | end 183 | if plug.theme then 184 | return 185 | end 186 | local name = 'plugins/' .. plug.name .. '/' .. plug.file 187 | local plugin = require(name) 188 | if plug.alias then 189 | M.plugins[plug.alias] = plugin 190 | end 191 | end 192 | 193 | local count_themes = function() 194 | local themes = 0 195 | for _, plug in ipairs(plugins_conf) do 196 | if plug.theme then 197 | themes = themes + 1 198 | end 199 | end 200 | return themes 201 | end 202 | 203 | local is_empty = function(str) 204 | return str == nil or str == '' 205 | end 206 | 207 | local get_file_display_name = function(plug) 208 | if is_empty(plug.file) then 209 | return '' 210 | end 211 | return ' (' .. plug.file .. ')' 212 | end 213 | 214 | local plug_list = function(plug, theme) 215 | if (theme and not plug.theme) or (not theme and plug.theme) then 216 | return 217 | end 218 | local short_url = get_short_url(plug.url) 219 | if file_exists(plug.path) then 220 | vis:message(short_url .. get_file_display_name(plug)) 221 | else 222 | vis:message(short_url .. get_file_display_name(plug) .. ' NOT INSTALLED') 223 | end 224 | vis:redraw() 225 | end 226 | 227 | -- run a set of bash commands given a table 228 | local execute_commands_in_background = function(commands) 229 | table.insert(commands, 'wait') 230 | os.execute(string.format('sh -c \'(\n%s\n)\'', table.concat(commands, '\n'))) 231 | end 232 | 233 | local install_plugins = function(silent) 234 | -- create folders 235 | os.execute('mkdir -p ' .. plugins_path .. '/plugins') 236 | os.execute('mkdir -p ' .. plugins_path .. '/themes') 237 | 238 | -- build shell commands which run in the background and wait 239 | local commands = {} 240 | for i, plug in ipairs(plugins_conf) do 241 | if not file_exists(plug.path) then 242 | local path = get_base_path(plug.theme) 243 | local clone_command = string.format('git -C %s clone %s --recurse-submodules --quiet 2> /dev/null &', path, 244 | plug.url) 245 | table.insert(commands, clone_command) 246 | end 247 | end 248 | 249 | -- execute commands and wait 250 | if #commands > 0 then 251 | vis:info('Installing..') 252 | vis:redraw() 253 | execute_commands_in_background(commands) 254 | end 255 | 256 | -- checkout git repo 257 | for_each_plugin(checkout) 258 | 259 | -- print result 260 | if #commands > 0 then 261 | vis:info('' .. #commands - 1 .. ' plugin(s) installed') 262 | elseif not silent then 263 | vis:info('Nothing to install') 264 | end 265 | end 266 | 267 | local check_updates_parallel = function() 268 | local commands = {} 269 | local plugin_status = {} 270 | 271 | -- Build commands to check updates for all plugins in parallel 272 | for _, plug in ipairs(plugins_conf) do 273 | if file_exists(plug.path) then 274 | -- Fetch updates and compare local and remote hashes 275 | local cmd = string.format( 276 | 'git -C %s fetch --quiet && ' .. 277 | 'echo "%s:$(git -C %s rev-parse HEAD):$(git -C %s rev-parse @{u})" &', 278 | plug.path, plug.name, plug.path, plug.path 279 | ) 280 | table.insert(commands, cmd) 281 | end 282 | end 283 | 284 | -- Run all check commands in parallel 285 | if #commands > 0 then 286 | local result = execute(string.format('sh -c \'(\n%s\nwait)\n\'', table.concat(commands, '\n'))) 287 | 288 | -- Process results 289 | if result and result ~= "" then 290 | for line in result:gmatch("[^\n]+") do 291 | local name, local_hash, remote_hash = line:match("^(.-):(.+):(.+)$") 292 | if name and local_hash and remote_hash then 293 | local plug = get_plug_by_name(name) 294 | if plug then 295 | local short_url = get_short_url(plug.url) 296 | local status = { 297 | plugin = plug, 298 | needs_update = local_hash ~= remote_hash, 299 | message = plug.name .. ' (' .. short_url .. ') ' 300 | } 301 | table.insert(plugin_status, status) 302 | end 303 | end 304 | end 305 | end 306 | end 307 | 308 | return plugin_status 309 | end 310 | 311 | local plug_outdated = function(plug, args) 312 | vis:info('Checking for outdated plugins..') 313 | vis:redraw() 314 | local status = check_updates_parallel() 315 | local outdated = {} 316 | 317 | -- Collect only outdated plugins 318 | for _, stat in ipairs(status) do 319 | if stat.needs_update then 320 | table.insert(outdated, stat.message) 321 | end 322 | end 323 | 324 | -- Show message based on whether there are outdated plugins 325 | if #outdated > 0 then 326 | local messages = { 327 | string.format('Found %d outdated plugin(s):', #outdated) 328 | } 329 | for _, msg in ipairs(outdated) do 330 | table.insert(messages, msg) 331 | end 332 | vis:message(table.concat(messages, '\n')) 333 | else 334 | vis:message('All plugins and themes are up to date') 335 | end 336 | vis:redraw() 337 | end 338 | 339 | local update_plugins = function() 340 | vis:info('Updating plugins..') 341 | vis:redraw() 342 | 343 | local commands = {} 344 | local updates = {} 345 | 346 | -- Prepare pull commands to run in parallel 347 | for _, plug in ipairs(plugins_conf) do 348 | if file_exists(plug.path) then 349 | -- Store plugin name and git pull output together, get last line 350 | local cmd = string.format( 351 | 'echo "%s:$(git -C %s pull --recurse-submodules 2>&1 | tail -n1)" &', 352 | plug.name, 353 | plug.path 354 | ) 355 | table.insert(commands, cmd) 356 | end 357 | end 358 | 359 | -- Execute pulls in parallel and capture results 360 | if #commands > 0 then 361 | local result = execute(string.format('sh -c \'(\n%s\nwait)\n\'', table.concat(commands, '\n'))) 362 | 363 | -- Process results 364 | if result and result ~= "" then 365 | for line in result:gmatch("[^\n]+") do 366 | local name, output = line:match("^(.-):(.*)") 367 | if name and output and not output:match("Already up to date") then 368 | local plug = get_plug_by_name(name) 369 | if plug then 370 | table.insert(updates, plug) 371 | checkout(plug) 372 | end 373 | end 374 | end 375 | end 376 | end 377 | 378 | -- Show results 379 | if #updates > 0 then 380 | local update_messages = { string.format('Updated %d plugin(s):', #updates) } 381 | for _, plug in ipairs(updates) do 382 | local short_url = get_short_url(plug.url) 383 | table.insert(update_messages, plug.name .. ' (' .. short_url .. ')') 384 | end 385 | vis:message(table.concat(update_messages, '\n')) 386 | else 387 | vis:message('All plugins and themes are up to date') 388 | end 389 | end 390 | 391 | -- require plugins (and optionally install and checkout) 392 | M.init = function(plugins, install_on_init) 393 | plugins_conf = plugins or {} 394 | for_each_plugin(plug_init) 395 | if install_on_init then 396 | install_plugins(true) 397 | end 398 | for_each_plugin(plug_require) 399 | return M 400 | end 401 | 402 | local command_install = function(argv, force, win, selection, range) 403 | install_plugins(false) 404 | return true 405 | end 406 | 407 | local command_rm = function(argv, force, win, selection, range) 408 | local name = argv[1] 409 | local plug = get_plug_by_name(name) 410 | if not plug then 411 | vis:info('\'' .. name .. '\' not found') 412 | return true 413 | end 414 | if file_exists(plug.path) then 415 | os.execute('rm -rf ' .. plug.path) 416 | vis:info(plug.name .. ' (' .. plug.path .. ') deleted') 417 | else 418 | vis:info(plug.name .. ' is not installed') 419 | end 420 | return true 421 | end 422 | 423 | local command_checkout = function(argv, force, win, selection, range) 424 | local name = argv[1] 425 | local ref = argv[2] 426 | if name == nil or ref == nil then 427 | vis:info('Missing {name} or {commit|branch|tag}') 428 | return true 429 | end 430 | local plug = get_plug_by_name(name) 431 | if not plug then 432 | vis:info('\'' .. name .. '\' not found') 433 | return true 434 | end 435 | plug.ref = ref 436 | checkout(plug) 437 | vis:info('Checked out \'' .. ref .. '\'') 438 | return true 439 | end 440 | 441 | local command_clean = function(argv, force, win, selection, range) 442 | local deleted = 0 443 | for _, plug in ipairs(plugins_conf) do 444 | if file_exists(plug.path) then 445 | os.execute('rm -rf ' .. plug.path) 446 | deleted = deleted + 1 447 | end 448 | end 449 | if deleted == 0 then 450 | vis:info('Nothing to delete') 451 | else 452 | vis:info('' .. deleted .. ' packages deleted') 453 | end 454 | return true 455 | end 456 | 457 | local command_update = function(argv, force, win, selection, range) 458 | update_plugins() 459 | return true 460 | end 461 | 462 | -- look for vis-plug path in package.path because it is NOT necessarily in the 463 | -- `plugins_path` but could rather have been required from some other path E.g. 464 | -- the `visrc` config path 465 | local look_for_vis_plug_path = function() 466 | local plug_path = package.searchpath('plugins/vis-plug', package.path) 467 | if plug_path ~= nil then 468 | return plug_path 469 | end 470 | return package.searchpath('vis-plug', package.path) 471 | end 472 | 473 | -- upgrade vis-plug by doing a git pull 474 | local command_upgrade = function(argv, force, win, selection, range) 475 | vis:info('Upgrading vis-plug..') 476 | vis:redraw() 477 | local plug_path = look_for_vis_plug_path() 478 | if plug_path == nil then 479 | vis:info('Could not find vis-plug path') 480 | return 481 | end 482 | 483 | local plug_dir = get_dir_from_file(plug_path) 484 | local upgrade_command = string.format('git -C %s pull --quiet 2> /dev/null', plug_dir) 485 | local result, success, message, code = execute(upgrade_command) 486 | if success then 487 | vis:info('vis-plug is up-to-date - restart for latest') 488 | else 489 | vis:info('Upgrade failed with code: ' .. tostring(code)) 490 | end 491 | return true 492 | end 493 | 494 | local command_ls = function(argv, force, win, selection, range) 495 | local num_themes = count_themes() 496 | local num_plugins = #plugins_conf - num_themes 497 | 498 | vis:message('Plugins (' .. num_plugins .. ')') 499 | vis:redraw() 500 | for_each_plugin(plug_list, false) 501 | 502 | vis:message('\nThemes (' .. num_themes .. ')') 503 | vis:redraw() 504 | for_each_plugin(plug_list, true) 505 | 506 | return true 507 | end 508 | 509 | local command_outdated = function(argv, force, win, selection, range) 510 | plug_outdated() 511 | return true 512 | end 513 | 514 | local command_list_commands = function(argv, force, win, selection, range) 515 | local arr = {} 516 | table.insert(arr, 'vis-plug commands') 517 | for _, command in ipairs(command_list) do 518 | table.insert(arr, ':' .. command.name .. ' - ' .. command.desc) 519 | end 520 | local str = table.concat(arr, '\n') 521 | vis:message(str) 522 | return true 523 | end 524 | 525 | -- we store commands in a list of tables {name, func, desc} 526 | command_list = { { 527 | name = 'plug-list', 528 | desc = 'list plugins and themes', 529 | func = command_ls 530 | }, { 531 | name = 'plug-install', 532 | desc = 'install plugins (git clone)', 533 | func = command_install 534 | }, { 535 | name = 'plug-update', 536 | desc = 'update plugins (git pull)', 537 | func = command_update 538 | }, { 539 | name = 'plug-outdated', 540 | desc = 'check if plugins are up-to-date', 541 | func = command_outdated 542 | }, { 543 | name = 'plug-upgrade', 544 | desc = 'upgrade to latest vis-plug version', 545 | func = command_upgrade 546 | }, { 547 | name = 'plug-remove', 548 | desc = 'delete plugin by {name} (:plug-list for names)', 549 | func = command_rm 550 | }, { 551 | name = 'plug-clean', 552 | desc = 'delete all plugins from disk', 553 | func = command_clean 554 | }, { 555 | name = 'plug-checkout', 556 | desc = 'checkout {name} {commit|branch|tag}', 557 | func = command_checkout 558 | }, { 559 | name = 'plug-commands', 560 | desc = 'list commands (these)', 561 | func = command_list_commands 562 | } } 563 | 564 | -- initialize commands 565 | for _, command in ipairs(command_list) do 566 | vis:command_register(command.name, command.func, command.desc) 567 | end 568 | 569 | -- set theme on INIT event 570 | vis.events.subscribe(vis.events.INIT, function() 571 | for _, plug in ipairs(plugins_conf) do 572 | if plug.theme and file_exists(get_file_path(plug)) then 573 | vis:command('set theme ' .. plug.name .. '/' .. plug.file) 574 | return -- set first theme and return 575 | end 576 | end 577 | end) 578 | 579 | return M 580 | --------------------------------------------------------------------------------