From fba69e62f11ea82cccd465897a69717e3233f461 Mon Sep 17 00:00:00 2001 From: Randy West Date: Thu, 3 Oct 2019 20:15:00 -0400 Subject: [PATCH 1/7] Use branch when checking for new commits --- plugin/vim-outdated-plugins.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index e7f34bd..3ec051f 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -13,7 +13,8 @@ function! s:CalculateUpdates(job_id, data, event) dict let l:command = "" for key in keys(g:plugs) - let l:command .= '(git -C ' . g:plugs[key].dir . ' rev-list HEAD..origin --count)' + let l:command .= '(git -C ' . g:plugs[key].dir . ' rev-list HEAD..' . + \ g:plugs[key].branch . ' --count)' let l:numberOfcheckedPlugins += 1 if l:numberOfcheckedPlugins != len(keys(g:plugs)) From 5037c9754d22f7c52daef2fd0078c657a15c0aed Mon Sep 17 00:00:00 2001 From: Randy West Date: Wed, 9 Oct 2019 22:17:28 -0400 Subject: [PATCH 2/7] - Added origin/[branch] to rev-list call - Check v:vim_did_enter and call for debugging convenience --- plugin/vim-outdated-plugins.vim | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index 3ec051f..7666bef 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -13,7 +13,7 @@ function! s:CalculateUpdates(job_id, data, event) dict let l:command = "" for key in keys(g:plugs) - let l:command .= '(git -C ' . g:plugs[key].dir . ' rev-list HEAD..' . + let l:command .= '(git -C ' . g:plugs[key].dir . ' rev-list HEAD..origin/' . \ g:plugs[key].branch . ' --count)' let l:numberOfcheckedPlugins += 1 @@ -47,7 +47,7 @@ let s:calculateCallbacks = { function! CheckForUpdates() let g:pluginsToUpdate = 0 - let l:command = "" + let l:command = "" " TODO check only activated plugins and not all downloaded let l:numberOfcheckedPlugins = 0 @@ -63,5 +63,9 @@ function! CheckForUpdates() call async#job#start([ 'bash', '-c', l:command], s:remoteUpdateCallbacks) endfunction -au VimEnter * call CheckForUpdates() +if v:vim_did_enter + call CheckForUpdates() +else + au VimEnter * call CheckForUpdates() +endif From 35198304e0b91a2af344f236661f4ede749956e8 Mon Sep 17 00:00:00 2001 From: Randy West Date: Thu, 10 Oct 2019 17:25:31 -0400 Subject: [PATCH 3/7] Added wait to the end of remote update chain --- plugin/vim-outdated-plugins.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index 7666bef..6cf4516 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -52,11 +52,11 @@ function! CheckForUpdates() " TODO check only activated plugins and not all downloaded let l:numberOfcheckedPlugins = 0 for key in keys(g:plugs) - let l:command .= 'git -C ' . g:plugs[key].dir . ' remote update > /dev/null' + let l:command .= 'git -C ' . g:plugs[key].dir . ' remote update > /dev/null & ' let l:numberOfcheckedPlugins += 1 - if l:numberOfcheckedPlugins != len(keys(g:plugs)) - let l:command .= ' &' + if l:numberOfcheckedPlugins == len(keys(g:plugs)) + let l:command .= 'wait' endif endfor From af6c0440129e6a7271738796b7c3f00071d9afb3 Mon Sep 17 00:00:00 2001 From: Randy West Date: Thu, 10 Oct 2019 17:46:56 -0400 Subject: [PATCH 4/7] No need to say len(keys(...)) (this matches other branches better) --- plugin/vim-outdated-plugins.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index 6cf4516..8b4c333 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -55,7 +55,7 @@ function! CheckForUpdates() let l:command .= 'git -C ' . g:plugs[key].dir . ' remote update > /dev/null & ' let l:numberOfcheckedPlugins += 1 - if l:numberOfcheckedPlugins == len(keys(g:plugs)) + if l:numberOfcheckedPlugins == len(g:plugs) let l:command .= 'wait' endif endfor From 72c9dcf54167936b324617fc46cee3bc49721d95 Mon Sep 17 00:00:00 2001 From: Randy West Date: Fri, 11 Oct 2019 00:32:44 -0400 Subject: [PATCH 5/7] Rewrite in python There was a lot of strange behavior in vimscript version of this plugin. The on_stdout callback appeared to be called a variable number of times before the on_exit callback, most likely indicating a race. I tried refactoring to call the rev-list command sequentially for each plugin in an async cascade, but for unknown reasons, stdout was blank for about half of the calls in my setup. In python, we can use a comparatively simple synchronous function wrapped in vim.async_call, so that's what I've done. The plugin now appears to finally work consistently and as expected. Since async/job.vim is no longer needed, I've removed that as well. --- autoload/async/job.vim | 295 -------------------------------- plugin/vim-outdated-plugins.vim | 77 ++------- python/outdatedplugins.py | 38 ++++ 3 files changed, 49 insertions(+), 361 deletions(-) delete mode 100644 autoload/async/job.vim create mode 100644 python/outdatedplugins.py diff --git a/autoload/async/job.vim b/autoload/async/job.vim deleted file mode 100644 index 7b90225..0000000 --- a/autoload/async/job.vim +++ /dev/null @@ -1,295 +0,0 @@ -" Author: Prabir Shrestha -" Website: https://github.com/prabirshrestha/async.vim -" License: The MIT License {{{ -" The MIT License (MIT) -" -" Copyright (c) 2016 Prabir Shrestha -" -" Permission is hereby granted, free of charge, to any person obtaining a copy -" of this software and associated documentation files (the "Software"), to deal -" in the Software without restriction, including without limitation the rights -" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -" copies of the Software, and to permit persons to whom the Software is -" furnished to do so, subject to the following conditions: -" -" The above copyright notice and this permission notice shall be included in all -" copies or substantial portions of the Software. -" -" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -" SOFTWARE. -" }}} - -let s:save_cpo = &cpo -set cpo&vim - -let s:jobidseq = 0 -let s:jobs = {} " { job, opts, type: 'vimjob|nvimjob'} -let s:job_type_nvimjob = 'nvimjob' -let s:job_type_vimjob = 'vimjob' -let s:job_error_unsupported_job_type = -2 " unsupported job type - -function! s:job_supported_types() abort - let l:supported_types = [] - if has('nvim') - let l:supported_types += [s:job_type_nvimjob] - endif - if !has('nvim') && has('job') && has('channel') && has('lambda') - let l:supported_types += [s:job_type_vimjob] - endif - return l:supported_types -endfunction - -function! s:job_supports_type(type) abort - return index(s:job_supported_types(), a:type) >= 0 -endfunction - -function! s:out_cb(jobid, opts, job, data) abort - if has_key(a:opts, 'on_stdout') - call a:opts.on_stdout(a:jobid, split(a:data, "\n", 1), 'stdout') - endif -endfunction - -function! s:err_cb(jobid, opts, job, data) abort - if has_key(a:opts, 'on_stderr') - call a:opts.on_stderr(a:jobid, split(a:data, "\n", 1), 'stderr') - endif -endfunction - -function! s:exit_cb(jobid, opts, job, status) abort - if has_key(a:opts, 'on_exit') - call a:opts.on_exit(a:jobid, a:status, 'exit') - endif - if has_key(s:jobs, a:jobid) - call remove(s:jobs, a:jobid) - endif -endfunction - -function! s:on_stdout(jobid, data, event) abort - if has_key(s:jobs, a:jobid) - let l:jobinfo = s:jobs[a:jobid] - if has_key(l:jobinfo.opts, 'on_stdout') - call l:jobinfo.opts.on_stdout(a:jobid, a:data, a:event) - endif - endif -endfunction - -function! s:on_stderr(jobid, data, event) abort - if has_key(s:jobs, a:jobid) - let l:jobinfo = s:jobs[a:jobid] - if has_key(l:jobinfo.opts, 'on_stderr') - call l:jobinfo.opts.on_stderr(a:jobid, a:data, a:event) - endif - endif -endfunction - -function! s:on_exit(jobid, status, event) abort - if has_key(s:jobs, a:jobid) - let l:jobinfo = s:jobs[a:jobid] - if has_key(l:jobinfo.opts, 'on_exit') - call l:jobinfo.opts.on_exit(a:jobid, a:status, a:event) - endif - endif -endfunction - -function! s:job_start(cmd, opts) abort - let l:jobtypes = s:job_supported_types() - let l:jobtype = '' - - if has_key(a:opts, 'type') - if type(a:opts.type) == type('') - if !s:job_supports_type(a:opts.type) - return s:job_error_unsupported_job_type - endif - let l:jobtype = a:opts.type - else - let l:jobtypes = a:opts.type - endif - endif - - if empty(l:jobtype) - " find the best jobtype - for l:jobtype2 in l:jobtypes - if s:job_supports_type(l:jobtype2) - let l:jobtype = l:jobtype2 - endif - endfor - endif - - if l:jobtype ==? '' - return s:job_error_unsupported_job_type - endif - - if l:jobtype == s:job_type_nvimjob - let l:job = jobstart(a:cmd, { - \ 'on_stdout': function('s:on_stdout'), - \ 'on_stderr': function('s:on_stderr'), - \ 'on_exit': function('s:on_exit'), - \}) - if l:job <= 0 - return l:job - endif - let l:jobid = l:job " nvimjobid and internal jobid is same - let s:jobs[l:jobid] = { - \ 'type': s:job_type_nvimjob, - \ 'opts': a:opts, - \ } - let s:jobs[l:jobid].job = l:job - elseif l:jobtype == s:job_type_vimjob - let s:jobidseq = s:jobidseq + 1 - let l:jobid = s:jobidseq - let l:jobopt = { - \ 'out_cb': function('s:out_cb', [l:jobid, a:opts]), - \ 'err_cb': function('s:err_cb', [l:jobid, a:opts]), - \ 'exit_cb': function('s:exit_cb', [l:jobid, a:opts]), - \ 'mode': 'raw', - \ } - if has('patch-8.1.889') - let l:jobopt['noblock'] = 1 - endif - let l:job = job_start(a:cmd, l:jobopt) - if job_status(l:job) !=? 'run' - return -1 - endif - let s:jobs[l:jobid] = { - \ 'type': s:job_type_vimjob, - \ 'opts': a:opts, - \ 'job': l:job, - \ 'channel': job_getchannel(l:job), - \ 'buffer': '' - \ } - else - return s:job_error_unsupported_job_type - endif - - return l:jobid -endfunction - -function! s:job_stop(jobid) abort - if has_key(s:jobs, a:jobid) - let l:jobinfo = s:jobs[a:jobid] - if l:jobinfo.type == s:job_type_nvimjob - call jobstop(a:jobid) - elseif l:jobinfo.type == s:job_type_vimjob - call job_stop(s:jobs[a:jobid].job) - endif - if has_key(s:jobs, a:jobid) - call remove(s:jobs, a:jobid) - endif - endif -endfunction - -function! s:job_send(jobid, data) abort - let l:jobinfo = s:jobs[a:jobid] - if l:jobinfo.type == s:job_type_nvimjob - call jobsend(a:jobid, a:data) - elseif l:jobinfo.type == s:job_type_vimjob - if has('patch-8.1.0818') - call ch_sendraw(l:jobinfo.channel, a:data) - else - let l:jobinfo.buffer .= a:data - call s:flush_vim_sendraw(a:jobid, v:null) - endif - endif -endfunction - -function! s:flush_vim_sendraw(jobid, timer) abort - " https://github.com/vim/vim/issues/2548 - " https://github.com/natebosch/vim-lsc/issues/67#issuecomment-357469091 - let l:jobinfo = s:jobs[a:jobid] - sleep 1m - if len(l:jobinfo.buffer) <= 4096 - call ch_sendraw(l:jobinfo.channel, l:jobinfo.buffer) - let l:jobinfo.buffer = '' - else - let l:to_send = l:jobinfo.buffer[:4095] - let l:jobinfo.buffer = l:jobinfo.buffer[4096:] - call ch_sendraw(l:jobinfo.channel, l:to_send) - call timer_start(1, function('s:flush_vim_sendraw', [a:jobid])) - endif -endfunction - -function! s:job_wait_single(jobid, timeout, start) abort - if !has_key(s:jobs, a:jobid) - return -3 - endif - - let l:jobinfo = s:jobs[a:jobid] - if l:jobinfo.type == s:job_type_nvimjob - let l:timeout = a:timeout - reltimefloat(reltime(a:start)) * 1000 - return jobwait([a:jobid], float2nr(l:timeout))[0] - elseif l:jobinfo.type == s:job_type_vimjob - let l:timeout = a:timeout / 1000.0 - try - while l:timeout < 0 || reltimefloat(reltime(a:start)) < l:timeout - let l:info = job_info(l:jobinfo.job) - if l:info.status ==# 'dead' - return l:info.exitval - elseif l:info.status ==# 'fail' - return -3 - endif - sleep 1m - endwhile - catch /^Vim:Interrupt$/ - return -2 - endtry - endif - return -1 -endfunction - -function! s:job_wait(jobids, timeout) abort - let l:start = reltime() - let l:exitcode = 0 - let l:ret = [] - for l:jobid in a:jobids - if l:exitcode != -2 " Not interrupted. - let l:exitcode = s:job_wait_single(l:jobid, a:timeout, l:start) - endif - let l:ret += [l:exitcode] - endfor - return l:ret -endfunction - -function! s:job_pid(jobid) abort - if !has_key(s:jobs, a:jobid) - return 0 - endif - - let l:jobinfo = s:jobs[a:jobid] - if l:jobinfo.type == s:job_type_nvimjob - return jobpid(a:jobid) - elseif l:jobinfo.type == s:job_type_vimjob - let l:vimjobinfo = job_info(a:jobid) - if type(l:vimjobinfo) == type({}) && has_key(l:vimjobinfo, 'process') - return l:vimjobinfo['process'] - endif - endif - return 0 -endfunction - -" public apis {{{ -function! async#job#start(cmd, opts) abort - return s:job_start(a:cmd, a:opts) -endfunction - -function! async#job#stop(jobid) abort - call s:job_stop(a:jobid) -endfunction - -function! async#job#send(jobid, data) abort - call s:job_send(a:jobid, a:data) -endfunction - -function! async#job#wait(jobids, ...) abort - let l:timeout = get(a:000, 0, -1) - return s:job_wait(a:jobids, l:timeout) -endfunction - -function! async#job#pid(jobid) abort - return s:job_pid(a:jobid) -endfunction -" }}} diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index 8b4c333..b6626f7 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -2,70 +2,15 @@ if !exists('g:outdated_plugins_silent_mode') let g:outdated_plugins_silent_mode = 0 endif -function! s:JobHandler(job_id, data, event) dict - if (str2nr(join(a:data)) != 0) - let g:pluginsToUpdate += 1 - endif -endfunction - -function! s:CalculateUpdates(job_id, data, event) dict - let l:numberOfcheckedPlugins = 0 - let l:command = "" - - for key in keys(g:plugs) - let l:command .= '(git -C ' . g:plugs[key].dir . ' rev-list HEAD..origin/' . - \ g:plugs[key].branch . ' --count)' - let l:numberOfcheckedPlugins += 1 - - if l:numberOfcheckedPlugins != len(keys(g:plugs)) - let l:command .= ' &&' - endif - endfor - - call async#job#start([ 'bash', '-c', l:command], s:calculateCallbacks) -endfunction - -function! s:DisplayResults(job_id, data, event) dict - if g:pluginsToUpdate > 0 - echom 'Plugins to update: ' . g:pluginsToUpdate - else - if !g:outdated_plugins_silent_mode - echom 'All plugins up-to-date' - endif - endif -endfunction - - -let s:remoteUpdateCallbacks = { - \ 'on_exit': function('s:CalculateUpdates') - \ } - -let s:calculateCallbacks = { - \ 'on_stdout': function('s:JobHandler'), - \ 'on_exit': function('s:DisplayResults') - \ } - -function! CheckForUpdates() - let g:pluginsToUpdate = 0 - let l:command = "" - - " TODO check only activated plugins and not all downloaded - let l:numberOfcheckedPlugins = 0 - for key in keys(g:plugs) - let l:command .= 'git -C ' . g:plugs[key].dir . ' remote update > /dev/null & ' - let l:numberOfcheckedPlugins += 1 - - if l:numberOfcheckedPlugins == len(g:plugs) - let l:command .= 'wait' - endif - endfor - - call async#job#start([ 'bash', '-c', l:command], s:remoteUpdateCallbacks) -endfunction - -if v:vim_did_enter - call CheckForUpdates() -else - au VimEnter * call CheckForUpdates() -endif +let s:plugin_root_dir = fnamemodify(resolve(expand(':p')), ':h') + +python3 << EOF +import sys +from os.path import normpath, join +import vim +plugin_root_dir = vim.eval('s:plugin_root_dir') +python_root_dir = normpath(join(plugin_root_dir, '..', 'python')) +sys.path.insert(0, python_root_dir) +import outdatedplugins +EOF diff --git a/python/outdatedplugins.py b/python/outdatedplugins.py new file mode 100644 index 0000000..89328e9 --- /dev/null +++ b/python/outdatedplugins.py @@ -0,0 +1,38 @@ +import vim +import subprocess + + +def check_for_updates(): + g_plugs = vim.eval("g:plugs") + + update_commands = [] + calculate_updates_commands = [] + + for plug in g_plugs.values(): + update_commands.append( + "git -C %s remote update > /dev/null" % plug["dir"]) + calculate_updates_commands.append( + "git -C %s rev-list HEAD..origin/%s --count" % (plug["dir"], plug["branch"])) + + update_commands.append("wait") + update_command = " & ".join(update_commands) + calculate_updates_command = " && ".join(calculate_updates_commands) + + updates_process = subprocess.Popen(["bash", "-c", update_command]) + updates_process.communicate() + + calculate_updates_process = subprocess.Popen( + ["bash", "-c", calculate_updates_command], + stdout=subprocess.PIPE, + text=True) + stdout, stderr = calculate_updates_process.communicate() + + plugs_to_update = sum(1 for i in stdout.split() if int(i) > 0) + g_outdated_plugins_silent_mode = vim.eval("g:outdated_plugins_silent_mode") + if plugs_to_update > 0: + print("Plugins to update: %d" % plugs_to_update) + elif not g_outdated_plugins_silent_mode: + print("All plugins up-to-date") + + +vim.async_call(check_for_updates) From bf43e03c2d47495ed5cfc20f812ab107795bb1e4 Mon Sep 17 00:00:00 2001 From: Randy West Date: Fri, 11 Oct 2019 00:48:34 -0400 Subject: [PATCH 6/7] Properly casts result of vim.eval to int vim.eval returns a string, whereas we need an int for boolean testing --- python/outdatedplugins.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/outdatedplugins.py b/python/outdatedplugins.py index 89328e9..eb22d28 100644 --- a/python/outdatedplugins.py +++ b/python/outdatedplugins.py @@ -28,7 +28,8 @@ def check_for_updates(): stdout, stderr = calculate_updates_process.communicate() plugs_to_update = sum(1 for i in stdout.split() if int(i) > 0) - g_outdated_plugins_silent_mode = vim.eval("g:outdated_plugins_silent_mode") + g_outdated_plugins_silent_mode = int( + vim.eval("g:outdated_plugins_silent_mode")) if plugs_to_update > 0: print("Plugins to update: %d" % plugs_to_update) elif not g_outdated_plugins_silent_mode: From 817220d3fe86e0ca080eb6a5ff03f75f4459244e Mon Sep 17 00:00:00 2001 From: Randy West Date: Fri, 11 Oct 2019 00:52:26 -0400 Subject: [PATCH 7/7] Adds g:outdated_plugins_trigger_mode --- README.md | 31 +++++++++++++++++++++---------- plugin/vim-outdated-plugins.vim | 4 ++++ python/outdatedplugins.py | 4 ++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d8abb35..fdc5d9f 100644 --- a/README.md +++ b/README.md @@ -3,43 +3,54 @@ ![GitHub release](https://img.shields.io/github/release/semanser/vim-outdated-plugins.svg?style=flat-square) # vim-outdated-plugins + Async plugin for showing number of your outdated plugins. ## What it does? + This plugin automatically checks if any of your plugins are outdated and display a message about that. To use this plugin make sure you have **git** installed. ## Installation + ```vim Plug 'semanser/vim-outdated-plugins' ``` ## Configuration + ```vim " Do not show any message if all plugins are up to date. 0 by default let g:outdated_plugins_silent_mode = 1 + +" Trigger :PlugUpdate as needed +let g:outdated_plugins_trigger_mode = 1 ``` ## Screenshots + Simple message text message under the status bar. ![alt text](https://raw.githubusercontent.com/semanser/vim-outdated-plugins/master/images/outdated.png) ![alt text](https://raw.githubusercontent.com/semanser/vim-outdated-plugins/master/images/updated.png) ### OS + - [x] macOS - [x] Linux - [ ] Windows ### Plugin Managers: - - [x] vim-plug - - [ ] Vundle - - [ ] Pathogen - - [ ] dein.vim - - [ ] NeoBundle - - [ ] VAM - - ### Notificatation methods - - [x] Basic echo - - [ ] Status line variable + +- [x] vim-plug +- [ ] Vundle +- [ ] Pathogen +- [ ] dein.vim +- [ ] NeoBundle +- [ ] VAM + +### Notificatation methods + +- [x] Basic echo +- [ ] Status line variable diff --git a/plugin/vim-outdated-plugins.vim b/plugin/vim-outdated-plugins.vim index b6626f7..f010ed0 100644 --- a/plugin/vim-outdated-plugins.vim +++ b/plugin/vim-outdated-plugins.vim @@ -2,6 +2,10 @@ if !exists('g:outdated_plugins_silent_mode') let g:outdated_plugins_silent_mode = 0 endif +if !exists('g:outdated_plugins_trigger_mode') + let g:outdated_plugins_trigger_mode = 0 +endif + let s:plugin_root_dir = fnamemodify(resolve(expand(':p')), ':h') python3 << EOF diff --git a/python/outdatedplugins.py b/python/outdatedplugins.py index eb22d28..cdec8d4 100644 --- a/python/outdatedplugins.py +++ b/python/outdatedplugins.py @@ -30,8 +30,12 @@ def check_for_updates(): plugs_to_update = sum(1 for i in stdout.split() if int(i) > 0) g_outdated_plugins_silent_mode = int( vim.eval("g:outdated_plugins_silent_mode")) + g_outdated_plugins_trigger_mode = int(vim.eval( + "g:outdated_plugins_trigger_mode")) if plugs_to_update > 0: print("Plugins to update: %d" % plugs_to_update) + if g_outdated_plugins_trigger_mode: + vim.command("PlugUpdate") elif not g_outdated_plugins_silent_mode: print("All plugins up-to-date")