diff --git a/README.md b/README.md index 992ef3e..b5ac578 100644 --- a/README.md +++ b/README.md @@ -153,8 +153,9 @@ endif " Define user commands for updating/cleaning the plugins. " Each of them loads minpac, reloads .vimrc to register the " information of plugins, then performs the task. -command! PackUpdate packadd minpac | source $MYVIMRC | call minpac#update() +command! PackUpdate packadd minpac | source $MYVIMRC | call minpac#update() | call minpac#status() command! PackClean packadd minpac | source $MYVIMRC | call minpac#clean() +command! PackStatus packadd minpac | source $MYVIMRC | call minpac#status() ``` Note that your .vimrc must be reloadable to use this. E.g.: @@ -179,6 +180,9 @@ call minpac#update() " To uninstall unused plugins: call minpac#clean() + +" To see plugins status: +call minpac#status() ``` @@ -307,6 +311,13 @@ echo minpac#getpackages("minpac", "", "", 1) echo minpac#getpackages("", "NAME", "", 1) ``` +#### minpac#status() + +Print status of plugins in vertical split. + +When ran after `minpac#update()`, shows only installed and updated plugins. + +Otherwise, shows the status of the plugin and commits of last update (if any). ### Hooks diff --git a/autoload/minpac/impl.vim b/autoload/minpac/impl.vim index 9e841a4..6c2eacf 100644 --- a/autoload/minpac/impl.vim +++ b/autoload/minpac/impl.vim @@ -67,7 +67,7 @@ endfunction " Replacement for system(). " This doesn't open an extra window on MS-Windows. -function! s:system(cmds) abort +function! minpac#impl#system(cmds) abort let l:opt = { \ 'on_stdout': function('s:system_out_cb'), \ 'out': [] @@ -82,10 +82,10 @@ function! s:system(cmds) abort endfunction " Get the revision of the specified plugin. -function! s:get_plugin_revision(name) abort +function! minpac#impl#get_plugin_revision(name) abort let l:pluginfo = g:minpac#pluglist[a:name] let l:dir = l:pluginfo.dir - let l:res = s:system([g:minpac#opt.git, '-C', l:dir, 'rev-parse', 'HEAD']) + let l:res = minpac#impl#system([g:minpac#opt.git, '-C', l:dir, 'rev-parse', 'HEAD']) if l:res[0] == 0 && len(l:res[1]) > 0 return l:res[1][0] else @@ -177,7 +177,7 @@ function! s:job_exit_cb(id, errcode, event) dict abort " Check if it is actually updated (or installed). let l:updated = 1 if l:pluginfo.revision != '' - if l:pluginfo.revision ==# s:get_plugin_revision(self.name) + if l:pluginfo.revision ==# minpac#impl#get_plugin_revision(self.name) let l:updated = 0 endif endif @@ -316,7 +316,7 @@ function! s:update_single_plugin(name, force) abort endif call s:echo_verbose(3, 'Updating ' . a:name) - let l:pluginfo.revision = s:get_plugin_revision(a:name) + let l:pluginfo.revision = minpac#impl#get_plugin_revision(a:name) let l:cmd = [g:minpac#opt.git, '-C', l:dir, 'pull', '--quiet', '--ff-only'] endif return s:start_job(l:cmd, a:name, 0) @@ -442,4 +442,8 @@ function! minpac#impl#clean(args) abort endif endfunction +function! minpac#impl#is_update_ran() abort + return exists('s:installed_plugins') +endfunction + " vim: set ts=8 sw=2 et: diff --git a/autoload/minpac/status.vim b/autoload/minpac/status.vim new file mode 100644 index 0000000..1132abb --- /dev/null +++ b/autoload/minpac/status.vim @@ -0,0 +1,138 @@ +let s:results = [] + +function! minpac#status#get() abort + let l:is_update_ran = minpac#impl#is_update_ran() + let l:update_count = 0 + let l:install_count = 0 + let l:result = [] + for l:name in keys(g:minpac#pluglist) + let l:pluginfo = g:minpac#pluglist[l:name] + let l:dir = l:pluginfo.dir + let l:plugin = { 'name': l:name, 'lines': [], 'status': '' } + + if !isdirectory(l:dir) + let l:plugin.status = 'Not installed' + else + let l:commits = minpac#impl#system([g:minpac#opt.git, '-C', l:dir, 'log', + \ '--color=never', '--pretty=format:%h %s (%cr)', '--no-show-signature', 'HEAD...HEAD@{1}' + \ ]) + + let l:plugin.lines = filter(l:commits[1], {-> v:val !=? '' }) + + if !l:is_update_ran + let l:plugin.status = 'OK' + elseif get(l:pluginfo, 'revision') !=? '' && l:pluginfo.revision !=# minpac#impl#get_plugin_revision(l:name) + let l:update_count += 1 + let l:plugin.status = 'Updated' + elseif has_key(l:pluginfo, 'installed') && l:pluginfo.installed ==? 0 + let l:install_count += 1 + let l:plugin.status = 'Installed' + endif + endif + + call add(l:result, l:plugin) + endfor + + " Show items with most lines (commits) first. + call sort(l:result, { first, second -> len(second.lines) - len(first.lines) }) + let s:results = l:result + + let l:content = [] + + if l:is_update_ran + call add(l:content, l:update_count.' updated. '.l:install_count.' installed.') + endif + + for l:item in l:result + if l:item.status ==? '' + continue + endif + + call add(l:content, '- '.l:item.name.' - '.l:item.status) + for l:line in l:item.lines + call add(l:content, ' * '.l:line) + endfor + endfor + + let l:content = join(l:content, "\") + silent exe 'vertical topleft new' + setf minpac + silent exe 'put! =l:content|norm!gg' + call s:syntax() + call s:mappings() + setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nomodifiable nospell +endfunction + + +function! s:syntax() abort + syntax clear + syn match minpacDash /^-/ + syn match minpacName /\(^- \)\@<=.*/ contains=minpacStatus + syn match minpacStatus /\(-.*\)\@<=-\s.*$/ contained + syn match minpacStar /^\s\*/ contained + syn match minpacCommit /^\s\*\s[0-9a-f]\{7,9} .*/ contains=minpacRelDate,minpacSha,minpacStar + syn match minpacSha /\(\s\*\s\)\@<=[0-9a-f]\{4,}/ contained + syn match minpacRelDate /([^)]*)$/ contained + + hi def link minpacDash Special + hi def link minpacStar Boolean + hi def link minpacName Function + hi def link minpacSha Identifier + hi def link minpacRelDate Comment + hi def link minpacStatus Constant +endfunction + +function! s:mappings() abort + nnoremap :call openSha() + nnoremap q :q + nnoremap :call nextPackage() + nnoremap :call prevPackage() +endfunction + +function! s:nextPackage() + return search('^-\s.*$') +endfunction + +function! s:prevPackage() + return search('^-\s.*$', 'b') +endfunction + +function s:openSha() abort + let l:sha = matchstr(getline('.'), '^\s\*\s\zs[0-9a-f]\{7,9}') + if empty(l:sha) + return + endif + + let l:name = s:find_name_by_sha(l:sha) + + if empty(l:name) + return + endif + + let l:pluginfo = g:minpac#pluglist[l:name] + exe 'pedit' l:sha + wincmd p + setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable + let l:sha_content = minpac#impl#system([g:minpac#opt.git, '-C', l:pluginfo.dir, 'show', + \ '--no-color', '--pretty=medium', l:sha + \ ]) + let l:sha_content = join(l:sha_content[1], "\") + + silent exe 'put! =l:sha_content|norm!gg' + setlocal nomodifiable + nnoremap q :q +endfunction + +function! s:find_name_by_sha(sha) abort + for l:result in s:results + for l:commit in l:result.lines + if l:commit =~? '^'.a:sha + return l:result.name + endif + endfor + endfor + + return '' +endfunction + +" vim: set ts=8 sw=2 et: diff --git a/doc/minpac.txt b/doc/minpac.txt index 9a76b14..e6d58c2 100644 --- a/doc/minpac.txt +++ b/doc/minpac.txt @@ -17,6 +17,7 @@ USAGE |minpac-usage| COMMANDS |minpac-commands| FUNCTIONS |minpac-functions| HOOKS |minpac-hooks| + MAPPINGS |minpac-mappings| ============================================================================== @@ -166,7 +167,7 @@ Load minpac on demand " Define user commands for updating/cleaning the plugins. " Each of them loads minpac, reloads .vimrc to register the " information of plugins, then performs the task. - command! PackUpdate packadd minpac | source $MYVIMRC | call minpac#update() + command! PackUpdate packadd minpac | source $MYVIMRC | call minpac#update() | call minpac#status() command! PackClean packadd minpac | source $MYVIMRC | call minpac#clean() < Note that your .vimrc must be reloadable to use this. E.g.: @@ -191,6 +192,9 @@ functions. E.g.: > " To uninstall unused plugins: call minpac#clean() + + " To see plugins status: + call minpac#status() < ------------------------------------------------------------------------------ @@ -350,6 +354,12 @@ minpac#getpackages([{packname}[, {packtype}[, {plugname}[, {nameonly}]]]]) " List package names. echo minpac#getpackages("", "NAME", "", 1) < +minpac#status() *minpac#status()* + Print status of plugins in vertical split. + When ran after `minpac#update()`, shows only installed and updated + plugins. Otherwise, shows the status of the plugin and commits of last + update (if any) + ------------------------------------------------------------------------------ HOOKS *minpac-hooks* @@ -425,5 +435,22 @@ E.g.: > " Quit Vim immediately after all updates are finished. call minpac#update('', {'do': 'quit'}) < +------------------------------------------------------------------------------ +MAPPINGS *minpac-mappings* + +List of mappings available only in status window. + + *minpac-* + Preview the commit under the cursor. + + *minpac-CTRL-j* + Jump to next package in list. + + *minpac-CTRL-k* + Jump to previous package in list. + + *minpac-q* +q Exit the status window. + (Also works for commit preview window) ============================================================================== vim:tw=78:ts=8:ft=help:norl: diff --git a/plugin/minpac.vim b/plugin/minpac.vim index cfa1f8a..ca1d39a 100644 --- a/plugin/minpac.vim +++ b/plugin/minpac.vim @@ -109,6 +109,11 @@ function! minpac#clean(...) return minpac#impl#clean(a:000) endfunction +function! minpac#status() + call s:ensure_initialization() + return minpac#status#get() +endfunction + " Get information of specified plugin. Mainly for debugging. function! minpac#getpluginfo(name)