1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-04 19:00:07 +08:00
SpaceVim/bundle/gina.vim/autoload/gina/command/blame/pipe.vim

108 lines
3.0 KiB
VimL

let s:KEYWORDS = [
\ 'author-mail',
\ 'author-time',
\ 'author-tz',
\ 'author',
\ 'committer-mail',
\ 'committer-time',
\ 'committer-tz',
\ 'committer',
\ 'summary',
\ 'previous',
\ 'filename',
\ 'boundary',
\]
call map(
\ s:KEYWORDS,
\ '[v:val, len(v:val), substitute(v:val, ''-'', ''_'', ''g'')]',
\)
function! gina#command#blame#pipe#incremental() abort
let parser_pipe = deepcopy(s:parser_pipe)
let parser_pipe.revisions = {}
let parser_pipe.chunks = []
let parser_pipe._stdout = ['']
let parser_pipe._stderr = ['']
let parser_pipe._chunk = {}
return parser_pipe
endfunction
" Parser pipe ----------------------------------------------------------------
function! s:_parser_pipe_on_stdout(data) abort dict
let self._stdout[-1] .= a:data[0]
call extend(self._stdout, a:data[1:])
endfunction
function! s:_parser_pipe_on_stderr(data) abort dict
let self._stderr[-1] .= a:data[0]
call extend(self._stderr, a:data[1:])
endfunction
function! s:_parser_pipe_on_exit(exitval) abort dict
call call(s:original_pipe.on_exit, [a:exitval], self)
if a:exitval
throw gina#process#errormsg({
\ 'args': self.args,
\ 'content': self._stderr,
\})
endif
" Parse records to create chunks
call map(filter(self._stdout, '!empty(v:val)'), 's:parse(self, v:val)')
" Sort chunks and assign indices
call sort(self.chunks, { a, b -> a.lnum - b.lnum })
call map(self.chunks, 'extend(v:val, {''index'': v:key})')
endfunction
let s:original_pipe = gina#process#pipe#default()
let s:parser_pipe = extend(deepcopy(s:original_pipe), {
\ 'on_stdout': function('s:_parser_pipe_on_stdout'),
\ 'on_stderr': function('s:_parser_pipe_on_stderr'),
\ 'on_exit': function('s:_parser_pipe_on_exit'),
\})
" Private --------------------------------------------------------
function! s:parse(pipe, record) abort
let chunk = a:pipe._chunk
let revisions = a:pipe.revisions
call extend(chunk, s:parse_record(a:record))
if !has_key(chunk, 'filename')
return
endif
if !has_key(revisions, chunk.revision)
let revisions[chunk.revision] = chunk
let chunk = {
\ 'filename': chunk.filename,
\ 'revision': chunk.revision,
\ 'lnum_from': chunk.lnum_from,
\ 'lnum': chunk.lnum,
\ 'nlines': chunk.nlines,
\}
endif
call add(a:pipe.chunks, chunk)
let a:pipe._chunk = {}
endfunction
function! s:parse_record(record) abort
for [prefix, length, vname] in s:KEYWORDS
if a:record[:length-1] ==# prefix
return {vname : a:record[length+1:]}
endif
endfor
let terms = split(a:record)
let nterms = len(terms)
if nterms >= 3
return {
\ 'revision': terms[0],
\ 'lnum_from': terms[1] + 0,
\ 'lnum': terms[2] + 0,
\ 'nlines': nterms == 3 ? 1 : (terms[3] + 0),
\}
endif
throw gina#core#revelator#critical(printf(
\ 'Failed to parse a record "%s"',
\ a:record,
\))
endfunction