1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-14 15:19:12 +08:00

Improve Git branch manager (#4058)

This commit is contained in:
Wang Shidong 2021-01-23 22:16:59 +08:00 committed by GitHub
parent 25005c4a72
commit a279122e0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 273 additions and 240 deletions

View File

@ -1,72 +1,73 @@
let s:JOB = SpaceVim#api#import('job')
let s:STR = SpaceVim#api#import('data#string')
function! git#branch#run(args)
if len(a:args) == 0
call git#branch#manager#open()
return
else
let cmd = ['git', 'branch'] + a:args
endif
call git#logger#info('git-branch cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
function! git#branch#run(args) abort
if len(a:args) == 0
call git#branch#manager#open()
return
else
let cmd = ['git', 'branch'] + a:args
endif
call git#logger#info('git-branch cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
endfunction
function! s:on_stdout(id, data, event) abort
for line in filter(a:data, '!empty(v:val)')
exe 'Echo ' . line
endfor
for line in filter(a:data, '!empty(v:val)')
exe 'Echo ' . line
endfor
endfunction
function! s:on_stderr(id, data, event) abort
for line in filter(a:data, '!empty(v:val)')
exe 'Echoerr ' . line
endfor
for line in filter(a:data, '!empty(v:val)')
exe 'Echoerr ' . line
endfor
endfunction
function! s:on_exit(id, data, event) abort
call git#logger#info('git-branch exit data:' . string(a:data))
if a:data ==# 0
echo 'done!'
else
echo 'failed!'
endif
call git#logger#info('git-branch exit data:' . string(a:data))
if a:data ==# 0
call git#branch#manager#update()
echo 'done!'
else
echo 'failed!'
endif
endfunction
function! git#branch#complete(ArgLead, CmdLine, CursorPos)
function! git#branch#complete(ArgLead, CmdLine, CursorPos) abort
return "%\n" . join(getcompletion(a:ArgLead, 'file'), "\n")
return "%\n" . join(getcompletion(a:ArgLead, 'file'), "\n")
endfunction
let s:branch = ''
function! s:update_branch_name() abort
let cmd = 'git rev-parse --abbrev-ref HEAD'
call s:JOB.start(cmd,
\ {
\ 'on_stdout' : function('s:on_stdout_show_branch'),
\ }
\ )
let cmd = 'git rev-parse --abbrev-ref HEAD'
call s:JOB.start(cmd,
\ {
\ 'on_stdout' : function('s:on_stdout_show_branch'),
\ }
\ )
endfunction
function! s:on_stdout_show_branch(id, data, event) abort
let b = s:STR.trim(join(a:data, ""))
if !empty(b)
let s:branch = b
endif
let b = s:STR.trim(join(a:data, ''))
if !empty(b)
let s:branch = b
endif
endfunction
function! git#branch#current()
if empty(s:branch)
call s:update_branch_name()
endif
return s:branch
function! git#branch#current() abort
if empty(s:branch)
call s:update_branch_name()
endif
return s:branch
endfunction
function! git#branch#detect()
call s:update_branch_name()
function! git#branch#detect() abort
call s:update_branch_name()
endfunction

View File

@ -1,97 +1,115 @@
"=============================================================================
" manager.vim --- Git branch manager
" Copyright (c) 2016-2019 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
scriptencoding utf-8
let s:JOB = SpaceVim#api#import('job')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
function! git#branch#manager#open()
call s:open_win()
endfunction
let s:branch_manager_bufnr = 0
let s:bufnr = 0
function! s:open_win() abort
if s:bufnr != 0 && bufexists(s:bufnr)
exe 'bd ' . s:bufnr
endif
topleft vsplit __git_branch_manager__
" @todo add win_getid api
let s:winid = win_getid(winnr('#'))
let lines = &columns * 30 / 100
exe 'vertical resize ' . lines
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber winfixheight nomodifiable
set filetype=SpaceVimGitBranchManager
let s:bufnr = bufnr('%')
call s:update()
augroup git_branch_manager
autocmd! * <buffer>
autocmd WinEnter <buffer> call s:WinEnter()
augroup END
nnoremap <buffer><silent> <Enter> :call <SID>checkout_branch()<cr>
function! git#branch#manager#open() abort
if s:branch_manager_bufnr != 0 && bufexists(s:branch_manager_bufnr)
exe 'bd ' . s:branch_manager_bufnr
endif
topleft vsplit __git_branch_manager__
let s:winid = win_getid(winnr('#'))
let lines = &columns * 30 / 100
exe 'vertical resize ' . lines
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber winfixheight nomodifiable
set filetype=SpaceVimGitBranchManager
let s:branch_manager_bufnr = bufnr('%')
call s:update()
augroup git_branch_manager
autocmd! * <buffer>
autocmd WinEnter <buffer> call s:WinEnter()
augroup END
nnoremap <buffer><silent> <Enter> :call <SID>checkout_branch()<cr>
nnoremap <buffer><silent> dd :call <SID>delete_branch()<cr>
endfunction
function! s:WinEnter() abort
let s:winid = win_getid(winnr('#'))
let s:winid = win_getid(winnr('#'))
endfunction
function! s:checkout_branch() abort
let line = getline('.')
if line =~# '^\s\+\S\+'
let branch = split(line)[0]
exe 'Git checkout ' . branch
endif
let line = getline('.')
if line =~# '^\s\+\S\+'
let branch = split(line)[0]
exe 'Git checkout ' . branch
endif
endfunction
function! git#branch#manager#update() abort
call s:update()
endfunction
function! s:delete_branch() abort
let line = getline('.')
if line =~# '^\s\+\S\+'
let branch = split(line)[0]
exe 'Git branch -d ' . branch
endif
endfunction
function! s:update() abort
let s:branchs = []
let cmd = ['git', 'branch', '--all']
call git#logger#info('git-branch cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
let s:branchs = []
let cmd = ['git', 'branch', '--all']
call git#logger#info('git-branch cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
endfunction
function! s:update_buffer_context() abort
let lines = []
call add(lines, 'local')
let remote = ''
for branch in s:branchs
if branch.remote != remote
call add(lines, 'r:' . branch.remote)
let remote = branch.remote
endif
call add(lines, ' ' . branch.name)
endfor
call s:BUFFER.buf_set_lines(s:bufnr, 0 , -1, 0, lines)
let lines = []
call add(lines, 'local')
let remote = ''
for branch in s:branchs
if branch.remote != remote
call add(lines, 'r:' . branch.remote)
let remote = branch.remote
endif
call add(lines, ' ' . branch.name)
endfor
call s:BUFFER.buf_set_lines(s:branch_manager_bufnr, 0 , -1, 0, lines)
endfunction
function! s:on_stdout(id, data, event) abort
for line in filter(a:data, '!empty(v:val)')
call SpaceVim#logger#info('>>' . line)
if stridx(line, 'remotes/') == -1
let branch = {
for line in filter(a:data, '!empty(v:val)')
call SpaceVim#logger#info('>>' . line)
if stridx(line, 'remotes/') == -1
let branch = {
\ 'name': trim(line),
\ 'remote': '',
\ 'islocal': 1,
\ }
else
let branch = {
else
let branch = {
\ 'name': line[stridx(line, '/', 10) + 1 :],
\ 'remote': split(line, '/')[1],
\ 'islocal': 0,
\ }
endif
call add(s:branchs, branch)
endfor
endif
call add(s:branchs, branch)
endfor
endfunction
function! s:on_stderr(id, data, event) abort
for line in filter(a:data, '!empty(v:val)')
exe 'Echoerr ' . line
endfor
for line in filter(a:data, '!empty(v:val)')
exe 'Echoerr ' . line
endfor
endfunction
function! s:on_exit(id, data, event) abort
call git#logger#info('git-branch exit data:' . string(a:data))
if a:data ==# 0
call s:update_buffer_context()
endif
call git#logger#info('git-branch exit data:' . string(a:data))
if a:data ==# 0
call s:update_buffer_context()
endif
endfunction

View File

@ -1,90 +1,97 @@
let s:JOB = SpaceVim#api#import('job')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
function! git#commit#run(...)
if index(a:1, '-m') ==# -1
let s:bufnr = s:openCommitBuffer()
let s:commit_bufnr = -1
function! git#commit#run(...) abort
if index(a:1, '-m') ==# -1
if bufexists(s:commit_bufnr) && index(tabpagebuflist(), s:commit_bufnr) !=# -1
let winnr = bufwinnr(s:commit_bufnr)
exe winnr . 'wincmd w'
else
let s:bufnr = -1
let s:commit_bufnr = s:openCommitBuffer()
endif
let s:lines = []
if empty(a:1)
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit', '--edit']
elseif index(a:1, '-m') != -1
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit'] + a:1
else
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit',] + a:1
endif
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
else
let s:commit_bufnr = -1
endif
let s:lines = []
if empty(a:1)
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit', '--edit']
elseif index(a:1, '-m') != -1
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit'] + a:1
else
let cmd = ['git', '--no-pager', '-c',
\ 'core.editor=cat', '-c',
\ 'color.status=always',
\ '-C',
\ expand(getcwd(), ':p'),
\ 'commit',] + a:1
endif
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
endfunction
function! s:on_stdout(id, data, event) abort
for data in a:data
call git#logger#info('git-commit stdout:' . data)
endfor
let s:lines += a:data
for data in a:data
call git#logger#info('git-commit stdout:' . data)
endfor
let s:lines += a:data
endfunction
function! s:on_stderr(id, data, event) abort
for data in a:data
call git#logger#info('git-commit stderr:' . data)
endfor
" stderr should not be added to commit buffer
" let s:lines += a:data
for data in a:data
call git#logger#info('git-commit stderr:' . data)
endfor
" stderr should not be added to commit buffer
" let s:lines += a:data
endfunction
function! s:on_exit(id, data, event) abort
call git#logger#info('git-exit exit data:' . string(a:data))
if s:bufnr == -1
if a:data ==# 0
echo 'commit done!'
else
echo 'commit failed!'
endif
call git#logger#info('git-exit exit data:' . string(a:data))
if s:commit_bufnr == -1
if a:data ==# 0
echo 'commit done!'
else
call s:BUFFER.buf_set_lines(s:bufnr, 0 , -1, 0, s:lines)
echo 'commit failed!'
endif
else
call s:BUFFER.buf_set_lines(s:commit_bufnr, 0 , -1, 0, s:lines)
endif
endfunction
function! s:openCommitBuffer() abort
10split git://commit
normal! "_dd
setlocal nobuflisted
setlocal buftype=acwrite
setlocal bufhidden=wipe
setlocal noswapfile
setlocal modifiable
setf git-commit
nnoremap <buffer><silent> q :bd!<CR>
let b:git_commit_quitpre = 0
10split git://commit
normal! "_dd
setlocal nobuflisted
setlocal buftype=acwrite
setlocal bufhidden=wipe
setlocal noswapfile
setlocal modifiable
setf git-commit
nnoremap <buffer><silent> q :bd!<CR>
let b:git_commit_quitpre = 0
augroup git_commit_buffer
autocmd! * <buffer>
autocmd BufWriteCmd <buffer> call s:BufWriteCmd()
autocmd QuitPre <buffer> call s:QuitPre()
autocmd WinLeave <buffer> call s:WinLeave()
autocmd WinEnter <buffer> let b:git_commit_quitpre = 0
augroup END
return bufnr('%')
augroup git_commit_buffer
autocmd! * <buffer>
autocmd BufWriteCmd <buffer> call s:BufWriteCmd()
autocmd QuitPre <buffer> call s:QuitPre()
autocmd WinLeave <buffer> call s:WinLeave()
autocmd WinEnter <buffer> let b:git_commit_quitpre = 0
augroup END
return bufnr('%')
endfunction
" NOTE:
@ -95,34 +102,34 @@ endfunction
" @fixme what the fuck
" :q -- QuitPre -> WinLeave
function! s:BufWriteCmd() abort
let commit_file = '.git\COMMIT_EDITMSG'
call writefile(getline(1, '$'), commit_file)
setlocal nomodified
let commit_file = '.git\COMMIT_EDITMSG'
call writefile(getline(1, '$'), commit_file)
setlocal nomodified
endfunction
function! s:QuitPre() abort
let b:git_commit_quitpre = 1
let b:git_commit_quitpre = 1
endfunction
function! s:WinLeave() abort
if b:git_commit_quitpre == 1
let cmd = ['git', 'commit', '-F', '-']
let id = s:JOB.start(cmd,
\ {
\ 'on_exit' : function('s:on_commit_exit'),
\ }
\ )
" line start with # should be ignored
call s:JOB.send(id, filter(readfile('.git\COMMIT_EDITMSG'), 'v:val !~ "^\s*#"'))
call s:JOB.chanclose(id, 'stdin')
endif
if b:git_commit_quitpre == 1
let cmd = ['git', 'commit', '-F', '-']
let id = s:JOB.start(cmd,
\ {
\ 'on_exit' : function('s:on_commit_exit'),
\ }
\ )
" line start with # should be ignored
call s:JOB.send(id, filter(readfile('.git\COMMIT_EDITMSG'), 'v:val !~# "^\s*#"'))
call s:JOB.chanclose(id, 'stdin')
endif
endfunction
function! s:on_commit_exit(id, data, event) abort
call git#logger#info('git-commit exit data:' . string(a:data))
if a:data ==# 0
echo 'done!'
else
echo 'failed!'
endif
call git#logger#info('git-commit exit data:' . string(a:data))
if a:data ==# 0
echo 'done!'
else
echo 'failed!'
endif
endfunction

View File

@ -1,56 +1,63 @@
let s:JOB = SpaceVim#api#import('job')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
function! git#status#run(...)
let s:bufnr = s:openStatusBuffer()
let cmd = ['git', 'status', '.']
let s:lines = []
call git#logger#info('git-status cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
let s:status_bufnr = -1
function! git#status#run(...) abort
if bufexists(s:status_bufnr) && index(tabpagebuflist(), s:status_bufnr) !=# -1
let winnr = bufwinnr(s:status_bufnr)
exe winnr . 'wincmd w'
else
let s:status_bufnr = s:openStatusBuffer()
endif
let cmd = ['git', 'status', '.']
let s:lines = []
call git#logger#info('git-status cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
endfunction
function! s:on_stdout(id, data, event) abort
for data in a:data
call git#logger#info('git-status stdout:' . data)
endfor
let s:lines += a:data
for data in a:data
call git#logger#info('git-status stdout:' . data)
endfor
let s:lines += a:data
endfunction
function! s:on_stderr(id, data, event) abort
for data in a:data
call git#logger#info('git-status stderr:' . data)
endfor
let s:lines += a:data
for data in a:data
call git#logger#info('git-status stderr:' . data)
endfor
let s:lines += a:data
endfunction
function! s:on_exit(id, data, event) abort
call git#logger#info('git-status exit data:' . string(a:data))
call s:BUFFER.buf_set_lines(s:bufnr, 0 , -1, 0, s:lines)
call git#logger#info('git-status exit data:' . string(a:data))
call s:BUFFER.buf_set_lines(s:status_bufnr, 0 , -1, 0, s:lines)
endfunction
function! s:openStatusBuffer() abort
10split git://status
normal! "_dd
setl nobuflisted
setl nomodifiable
setl nonumber norelativenumber
setl buftype=nofile
setl bufhidden=wipe
setf git-status
nnoremap <buffer><silent> q :call <SID>close_status_window()<CR>
" https://github.com/vim/vim/commit/a8eee21e75324d199acb1663cb5009e03014a13a
return bufnr('%')
10split git://status
normal! "_dd
setl nobuflisted
setl nomodifiable
setl nonumber norelativenumber
setl buftype=nofile
setl bufhidden=wipe
setf git-status
nnoremap <buffer><silent> q :call <SID>close_status_window()<CR>
" https://github.com/vim/vim/commit/a8eee21e75324d199acb1663cb5009e03014a13a
return bufnr('%')
endfunction
function! s:close_status_window() abort
if winnr('$') > 1
close
else
bd!
endif
if winnr('$') > 1
close
else
bd!
endif
endfunction