mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 07:20:04 +08:00
feat(git): add git remote manager
This commit is contained in:
parent
5e6065380f
commit
44f0cea649
@ -579,6 +579,8 @@ function! SpaceVim#layers#core#statusline#get(...) abort
|
||||
return '%#SpaceVim_statusline_a# Tasks manager %#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep
|
||||
elseif &filetype ==# 'SpaceVimGitBranchManager'
|
||||
return '%#SpaceVim_statusline_a# Branch manager %#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep
|
||||
elseif &filetype ==# 'SpaceVimGitRemoteManager'
|
||||
return '%#SpaceVim_statusline_a# Remote manager %#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep
|
||||
elseif &filetype ==# 'SpaceVimPlugManager'
|
||||
return '%#SpaceVim_statusline_a#' . s:winnr(1) . '%#SpaceVim_statusline_a_SpaceVim_statusline_b#' . s:lsep
|
||||
\ . '%#SpaceVim_statusline_b# PlugManager %#SpaceVim_statusline_b_SpaceVim_statusline_c#' . s:lsep
|
||||
|
@ -129,6 +129,7 @@ function! SpaceVim#layers#git#config() abort
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['g', 'V'], 'Git log %', 'git-log-of-current-file', 1)
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['g', 'v'], 'Git log', 'git-log-of-current-repo', 1)
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['g', 'm'], 'Git branch', 'branch-manager', 1)
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['g', 'r'], 'Git remote', 'remote-manager', 1)
|
||||
endif
|
||||
augroup spacevim_layer_git
|
||||
autocmd!
|
||||
|
@ -38,6 +38,10 @@ local function on_exit(id, code, single)
|
||||
end
|
||||
|
||||
function M.run(argv)
|
||||
if #argv == 0 then
|
||||
require('git.ui.remote').open()
|
||||
return
|
||||
end
|
||||
local cmd = { 'git', 'remote' }
|
||||
for _, v in ipairs(argv) do
|
||||
table.insert(cmd, v)
|
||||
|
300
bundle/git.vim/lua/git/ui/remote.lua
Normal file
300
bundle/git.vim/lua/git/ui/remote.lua
Normal file
@ -0,0 +1,300 @@
|
||||
--=============================================================================
|
||||
-- remote.lua --- remote manager
|
||||
-- Copyright (c) 2016-2024 Wang Shidong & Contributors
|
||||
-- Author: Wang Shidong < wsdjeg@outlook.com >
|
||||
-- URL: https://spacevim.org
|
||||
-- License: GPLv3
|
||||
--=============================================================================
|
||||
|
||||
local M = {}
|
||||
|
||||
local job = require('spacevim.api.job')
|
||||
local log = require('git.log')
|
||||
|
||||
-- script local valuables
|
||||
|
||||
local show_help_infoo = false
|
||||
local update_branch_list_jobid = -1
|
||||
local update_branch_list_name = ''
|
||||
local update_branch_list_branches = {}
|
||||
local update_branch_remote_list = {}
|
||||
local updating_extra_text = ' (updating)'
|
||||
|
||||
-- fetch remote:
|
||||
|
||||
local fetch_remote_jobid = -1
|
||||
local fetch_remote_name = ''
|
||||
|
||||
local help_info = {
|
||||
'" Git remote manager quickhelp',
|
||||
'" ============================',
|
||||
'" <CR>: checkout branch',
|
||||
'" f: fetch remote under cursor',
|
||||
'" o: toggle display of branchs',
|
||||
}
|
||||
|
||||
local bufnr = -1
|
||||
local winid = -1
|
||||
|
||||
local bufname = ''
|
||||
|
||||
-- This should not be a list of string. it should be a list of remote object.
|
||||
--
|
||||
-- {
|
||||
-- opened = boolean, default false
|
||||
-- name = string, the remote name
|
||||
-- url = ''
|
||||
-- branches = {}, list of string
|
||||
-- updating = boolean
|
||||
-- }
|
||||
local remotes = {}
|
||||
|
||||
-- the job to update remote list.
|
||||
local list_remote_job_id = -1
|
||||
|
||||
local function on_stdout(id, data)
|
||||
if id ~= list_remote_job_id then
|
||||
return
|
||||
end
|
||||
|
||||
for _, v in ipairs(data) do
|
||||
table.insert(remotes, {
|
||||
opened = false,
|
||||
name = v,
|
||||
url = '',
|
||||
branches = {},
|
||||
})
|
||||
table.insert(update_branch_remote_list, v)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_stderr(id, data) end
|
||||
|
||||
local function update_buf_context()
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
local context = {}
|
||||
if show_help_infoo then
|
||||
for _, v in ipairs(help_info) do
|
||||
table.insert(context, v)
|
||||
end
|
||||
end
|
||||
table.insert(context, 'Git Remotes:')
|
||||
for _, v in ipairs(remotes) do
|
||||
local extra_text = ''
|
||||
if v.updating then
|
||||
extra_text = updating_extra_text
|
||||
end
|
||||
if v.opened then
|
||||
table.insert(context, ' ▼ ' .. v.name .. extra_text)
|
||||
for _, b in ipairs(v.branches) do
|
||||
table.insert(context, ' ' .. b)
|
||||
end
|
||||
else
|
||||
table.insert(context, ' ▷ ' .. v.name .. extra_text)
|
||||
end
|
||||
end
|
||||
vim.api.nvim_buf_set_option(bufnr, 'modifiable', true)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, context)
|
||||
vim.api.nvim_buf_set_option(bufnr, 'modifiable', false)
|
||||
end
|
||||
|
||||
local function on_exit(id, code, signal)
|
||||
if code == 0 and signal == 0 and vim.api.nvim_buf_is_valid(bufnr) then
|
||||
update_buf_context()
|
||||
end
|
||||
if #update_branch_remote_list > 0 then
|
||||
log.debug('update_branch_remote_list is:' .. vim.inspect(update_branch_remote_list))
|
||||
M.update_branch_list(table.remove(update_branch_remote_list))
|
||||
end
|
||||
end
|
||||
|
||||
local function update()
|
||||
remotes = {}
|
||||
local cmd = { 'git', 'remote' }
|
||||
list_remote_job_id = job.start(cmd, {
|
||||
on_stdout = on_stdout,
|
||||
on_stderr = on_stderr,
|
||||
on_exit = on_exit,
|
||||
})
|
||||
end
|
||||
|
||||
local function enter_win() end
|
||||
|
||||
local function checkout_branch() end
|
||||
|
||||
local function get_cursor_info()
|
||||
local l = vim.fn.getline('.')
|
||||
local c = {}
|
||||
if vim.startswith(l, ' ▼ ') then
|
||||
c.remote = string.sub(l, 7)
|
||||
elseif vim.startswith(l, ' ▷ ') then
|
||||
c.remote = string.sub(l, 7)
|
||||
end
|
||||
|
||||
if c.remote then
|
||||
c.remote = string.gsub(c.remote, updating_extra_text, '')
|
||||
end
|
||||
|
||||
return c
|
||||
end
|
||||
|
||||
local function update_branch_stdout(id, data)
|
||||
-- stdout example:
|
||||
-- d89ff7896994692e7bcc6a53095c7ec2e2d780aa<Tab>refs/heads/dein-lua-job
|
||||
if id ~= update_branch_list_jobid then
|
||||
return
|
||||
end
|
||||
|
||||
for _, v in ipairs(data) do
|
||||
table.insert(update_branch_list_branches, string.sub(v, 53))
|
||||
end
|
||||
end
|
||||
|
||||
local function update_branch_exit(id, code, signal)
|
||||
if id ~= update_branch_list_jobid then
|
||||
return
|
||||
end
|
||||
update_branch_list_jobid = -1
|
||||
if code == 0 and signal == 0 then
|
||||
for _, v in ipairs(remotes) do
|
||||
if v.name == update_branch_list_name then
|
||||
v.branches = update_branch_list_branches
|
||||
v.updating = false
|
||||
update_buf_context()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if #update_branch_remote_list > 0 then
|
||||
M.update_branch_list(table.remove(update_branch_remote_list))
|
||||
end
|
||||
end
|
||||
|
||||
local function is_in_list(t, s)
|
||||
for _, v in ipairs(t) do
|
||||
if t == s then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function M.update_branch_list(name)
|
||||
if update_branch_list_jobid ~= -1 then
|
||||
-- jobid is not -1 means job is running, check if the name same as current job, if it is not same as current job, insert to list.
|
||||
if name ~= update_branch_list_name and not is_in_list(update_branch_remote_list, name) then
|
||||
-- 此处应该检查list里是否包含name
|
||||
table.insert(update_branch_remote_list, name)
|
||||
end
|
||||
return
|
||||
end
|
||||
update_branch_list_branches = {}
|
||||
log.debug('start to update branch list for remote:' .. name)
|
||||
update_branch_list_name = name
|
||||
|
||||
update_branch_list_jobid = job.start({ 'git', 'ls-remote', '-h', update_branch_list_name }, {
|
||||
on_stdout = update_branch_stdout,
|
||||
on_exit = update_branch_exit,
|
||||
})
|
||||
|
||||
log.debug('update_branch_list_jobid is:' .. update_branch_list_jobid)
|
||||
end
|
||||
|
||||
local function toggle_remote_branch()
|
||||
local cursor_info = get_cursor_info()
|
||||
if cursor_info.remote then
|
||||
for _, v in ipairs(remotes) do
|
||||
if v.name == cursor_info.remote then
|
||||
v.opened = not v.opened
|
||||
if v.opened and #v.branches == 0 then
|
||||
-- remote tree is opened, but branch list is empty, the update the branch list.
|
||||
--
|
||||
M.update_branch_list(v.name)
|
||||
end
|
||||
update_buf_context()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function toggle_help()
|
||||
if show_help_infoo then
|
||||
show_help_infoo = false
|
||||
else
|
||||
show_help_infoo = true
|
||||
end
|
||||
update_buf_context()
|
||||
end
|
||||
|
||||
-- functions to fetch remote:
|
||||
|
||||
local function on_fetch_exit(id, code, signal)
|
||||
if id == fetch_remote_jobid and code == 0 and signal == 0 then
|
||||
M.update_branch_list(fetch_remote_name)
|
||||
end
|
||||
fetch_remote_name = ''
|
||||
fetch_remote_jobid = -1
|
||||
end
|
||||
|
||||
local function fetch_remote()
|
||||
local cursor_info = get_cursor_info()
|
||||
if cursor_info.remote then
|
||||
fetch_remote_name = cursor_info.remote
|
||||
fetch_remote_jobid = job.start({ 'git', 'fetch', cursor_info.remote }, {
|
||||
on_exit = on_fetch_exit,
|
||||
})
|
||||
if fetch_remote_jobid > 0 then
|
||||
for _, v in ipairs(remotes) do
|
||||
if v.name == fetch_remote_name then
|
||||
v.updating = true
|
||||
update_buf_context()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.open()
|
||||
if bufnr ~= -1 and vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.api.nvim_buf_delete(bufnr, {
|
||||
force = true,
|
||||
unload = false,
|
||||
})
|
||||
end
|
||||
vim.api.nvim_command('topleft vsplit __git_remote_manager__')
|
||||
winid = vim.api.nvim_get_current_win()
|
||||
local lines = vim.o.columns * 20 / 100
|
||||
vim.api.nvim_command('vertical resize ' .. tostring(lines))
|
||||
vim.api.nvim_command(
|
||||
'setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber winfixheight nomodifiable winfixwidth'
|
||||
)
|
||||
vim.api.nvim_command('set filetype=SpaceVimGitRemoteManager')
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
update()
|
||||
local id = vim.api.nvim_create_augroup('spc_git_remote_manager', {
|
||||
clear = true,
|
||||
})
|
||||
vim.api.nvim_create_autocmd({ 'BufWipeout' }, {
|
||||
group = id,
|
||||
buffer = bufnr,
|
||||
callback = enter_win,
|
||||
})
|
||||
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<Enter>', '', {
|
||||
callback = checkout_branch,
|
||||
})
|
||||
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'o', '', {
|
||||
callback = toggle_remote_branch,
|
||||
})
|
||||
vim.api.nvim_buf_set_keymap(bufnr, 'n', '?', '', {
|
||||
callback = toggle_help,
|
||||
})
|
||||
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'f', '', {
|
||||
callback = fetch_remote,
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
@ -50,6 +50,7 @@ lang: zh
|
||||
| `SPC g c` | 打开 git commit 窗口 |
|
||||
| `SPC g p` | 执行 git push |
|
||||
| `SPC g m` | git 分支管理 |
|
||||
| `SPC g r` | git remote 管理 |
|
||||
| `SPC g d` | 打开 git diff 窗口 |
|
||||
| `SPC g A` | git add 所有文件 |
|
||||
| `SPC g b` | 打开 git blame 窗口 |
|
||||
|
@ -49,6 +49,7 @@ if you want to use `fugitive` instead:
|
||||
| `SPC g c` | edit git commit |
|
||||
| `SPC g p` | git push |
|
||||
| `SPC g m` | git branch manager |
|
||||
| `SPC g r` | git remote manager |
|
||||
| `SPC g d` | view git diff |
|
||||
| `SPC g A` | stage all files |
|
||||
| `SPC g b` | open git blame windows |
|
||||
|
13
syntax/SpaceVimGitRemoteManager.vim
Normal file
13
syntax/SpaceVimGitRemoteManager.vim
Normal file
@ -0,0 +1,13 @@
|
||||
scriptencoding utf-8
|
||||
sy match SPCGitRemoteName '^\s*[▷▼]\s.*'
|
||||
sy match SPCGitRemoteTitle '^Git Remotes:'
|
||||
sy match SPCGitRemoteHelpKey '" \zs[^:]*\ze[:]'
|
||||
sy match SPCGitRemoteHelpTitle 'Git remote manager quickhelp'
|
||||
sy match SPCGitRemoteHelp '^".*' contains=SPCGitRemoteHelpTitle,SPCGitRemoteHelpKey
|
||||
|
||||
hi def link SPCGitRemoteName Directory
|
||||
hi def link SPCGitRemoteHelpKey Identifier
|
||||
hi def link SPCGitRemoteTitle Title
|
||||
hi def link SPCGitRemoteHelpTitle Title
|
||||
hi def link SPCGitRemoteHelp String
|
||||
"
|
Loading…
Reference in New Issue
Block a user