1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 23:40:05 +08:00
SpaceVim/bundle/gina.vim/autoload/gina/component/status.vim

148 lines
3.9 KiB
VimL
Raw Normal View History

scriptencoding utf-8
let s:Git = vital#gina#import('Git')
let s:Path = vital#gina#import('System.Filepath')
let s:Store = vital#gina#import('System.Store')
let s:SLUG = eval(s:Store.get_slug_expr())
function! gina#component#status#staged() abort
let git = gina#core#get()
if empty(git)
return ''
endif
let c = get(s:status_count(git), 'staged', 0)
return c == 0 ? '' : (c . '')
endfunction
function! gina#component#status#unstaged() abort
let git = gina#core#get()
if empty(git)
return ''
endif
let c = get(s:status_count(git), 'unstaged', 0)
return c == 0 ? '' : (c . '')
endfunction
function! gina#component#status#conflicted() abort
let git = gina#core#get()
if empty(git)
return ''
endif
let c = get(s:status_count(git), 'conflicted', 0)
return c == 0 ? '' : (c . '')
endfunction
function! gina#component#status#preset(...) abort
let git = gina#core#get()
if empty(git)
return ''
endif
let kind = get(a:000, 0, 'ascii')
return call('s:preset_' . kind, [])
endfunction
" Private --------------------------------------------------------------------
function! s:get_store(git) abort
let ref = get(s:Git.ref(a:git, 'HEAD'), 'path', 'HEAD')
let store = s:Store.of([
\ s:Git.resolve(a:git, 'index'),
\ s:Git.resolve(a:git, ref),
\])
return store
endfunction
function! s:status_count(git) abort
let store = s:get_store(a:git)
let status_count = store.get(s:SLUG, {})
if !empty(status_count)
return status_count
endif
if !exists('s:status_job')
let pipe = gina#process#pipe#store()
let pipe.__on_exit = pipe.on_exit
let pipe.on_exit = funcref('s:status_on_exit', [store])
let s:status_job = gina#process#open(a:git, [
\ 'status',
\ '--porcelain',
\ '--ignore-submodules',
\], pipe)
endif
return {
\ 'staged': 0,
\ 'unstaged': 0,
\ 'conflicted': 0,
\}
endfunction
function! s:status_on_exit(store, exitval) abort dict
call self.__on_exit(a:exitval)
silent! unlet! s:status_job
if a:exitval
return
endif
let status_count = {
\ 'staged': 0,
\ 'unstaged': 0,
\ 'conflicted': 0,
\}
for record in self.stdout
let sign = record[:1]
if sign =~# '^\%(DD\|AU\|UD\|UA\|DU\|AA\|UU\)$'
let status_count.conflicted += 1
elseif sign ==# '??' || sign ==# '!!'
continue
else
if sign =~# '^\S.$'
let status_count.staged += 1
endif
if sign =~# '^.\S$'
let status_count.unstaged += 1
endif
endif
endfor
call a:store.set(s:SLUG, status_count)
endfunction
function! s:preset_ascii() abort
let staged = gina#component#status#staged()
let unstaged = gina#component#status#unstaged()
let conflicted = gina#component#status#conflicted()
let staged = empty(staged) ? '' : ('<' . staged)
let unstaged = empty(unstaged) ? '' : ('>' . unstaged)
let conflicted = empty(conflicted) ? '' : ('x' . conflicted)
return join(filter([staged, unstaged, conflicted], '!empty(v:val)'))
endfunction
function! s:preset_fancy() abort
let staged = gina#component#status#staged()
let unstaged = gina#component#status#unstaged()
let conflicted = gina#component#status#conflicted()
let staged = empty(staged) ? '' : ('«' . staged)
let unstaged = empty(unstaged) ? '' : ('»' . unstaged)
let conflicted = empty(conflicted) ? '' : ('×' . conflicted)
return join(filter([staged, unstaged, conflicted], '!empty(v:val)'))
endfunction
" NOTE:
" Tracked files might be changed (unstaged) so remove cache when 'modified'
" event has called.
function! s:on_modified(...) abort
let git = gina#core#get()
if empty(git)
return
endif
let store = s:get_store(git)
call store.remove(s:SLUG)
endfunction
if !exists('s:subscribed')
let s:subscribed = 1
call gina#core#emitter#subscribe(
\ 'modified',
\ function('s:on_modified')
\)
endif