From 2083a13ad60a9ea43b87dbf925fc60b3e0090c71 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 23 Mar 2024 23:18:05 +0800 Subject: [PATCH] feat(git): rewrite `:Git rebase` in lua --- bundle/git.vim/lua/git/command/commit.lua | 1 + bundle/git.vim/lua/git/command/rebase.lua | 139 ++++++++++++++++++++++ bundle/git.vim/lua/git/init.lua | 1 + bundle/git.vim/syntax/git-commit.vim | 9 -- bundle/git.vim/syntax/git-rebase.vim | 11 -- docs/cn/roadmap.md | 4 +- docs/roadmap.md | 2 +- 7 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 bundle/git.vim/lua/git/command/rebase.lua delete mode 100644 bundle/git.vim/syntax/git-commit.vim delete mode 100644 bundle/git.vim/syntax/git-rebase.vim diff --git a/bundle/git.vim/lua/git/command/commit.lua b/bundle/git.vim/lua/git/command/commit.lua index 3717815b2..798760b34 100644 --- a/bundle/git.vim/lua/git/command/commit.lua +++ b/bundle/git.vim/lua/git/command/commit.lua @@ -97,6 +97,7 @@ local function openCommitBuffer() setlocal noswapfile setlocal modifiable setf git-commit + set syntax=gitcommit nnoremap q :bd! let b:git_commit_quitpre = 0 ]]) diff --git a/bundle/git.vim/lua/git/command/rebase.lua b/bundle/git.vim/lua/git/command/rebase.lua new file mode 100644 index 000000000..cd69b0976 --- /dev/null +++ b/bundle/git.vim/lua/git/command/rebase.lua @@ -0,0 +1,139 @@ +local m = {} + +local job = require('spacevim.api.job') +local nt = require('spacevim.api.notify') +local log = require('git.log') +local std_data = {} +local rebase_todo_bufnr = -1 +local rebase_nvim_channal = '' + +local function BufWriteCmd() + vim.bo.modified = false +end + +local function QuitPre() + vim.b.git_rebase_quitpre = true +end + +local function WinLeave() + if vim.b.git_rebase_quitpre then + local text = vim.fn.getline(1, '$') + vim.fn.rpcrequest(rebase_nvim_channal, 'nvim_buf_set_lines', 0, 0, -1, false, text) + vim.fn.rpcnotify(rebase_nvim_channal, 'nvim_command', 'wq') + end +end +local function open_rebase() + vim.cmd([[ + 10split git://rebase + normal! "_dd + setlocal nobuflisted + setlocal buftype=acwrite + setlocal bufhidden=wipe + setlocal noswapfile + setlocal modifiable + setf git-rebase + set syntax=gitrebase + nnoremap q :bd! + let b:git_commit_quitpre = 0 + ]]) +end + +local function open_commit() + vim.cmd([[ + 10split git://commit + normal! "_dd + setlocal nobuflisted + setlocal buftype=acwrite + setlocal bufhidden=wipe + setlocal noswapfile + setlocal modifiable + setf git-commit + set syntax=gitcommit + nnoremap q :bd! + let b:git_commit_quitpre = 0 + ]]) +end +local function create_autocmd_return_bufnr() + local bufid = vim.fn.bufnr('%') + local id = vim.api.nvim_create_augroup('git_rebase_todo_buffer', { clear = true }) + vim.api.nvim_create_autocmd({ 'BufWriteCmd' }, { + group = id, + buffer = bufid, + callback = BufWriteCmd, + }) + vim.api.nvim_create_autocmd({ 'QuitPre' }, { + group = id, + buffer = bufid, + callback = QuitPre, + }) + vim.api.nvim_create_autocmd({ 'WinLeave' }, { + group = id, + buffer = bufid, + callback = WinLeave, + }) + vim.api.nvim_create_autocmd({ 'WinEnter' }, { + group = id, + buffer = bufid, + callback = function() + vim.b.git_rebase_quitpre = false + end, + }) + return bufid +end + +local function on_exit(id, code, single) + log.debug('git-rebase exit code:' .. code .. ' single:' .. single) + if code == 0 and single == 0 then + nt.notify('git rebase successfully') + else + nt.notify(table.concat(std_data, "\n"), "WarningMsg") + end +end + +local function on_std(id, data) + for _, v in ipairs(data) do + if vim.startswith(v, 'git-rebase-nvim-serverlist:') then + local address = string.sub(v, 28) + rebase_nvim_channal = vim.fn.sockconnect('pipe', address, { rpc = true }) + local bufname = vim.fn.rpcrequest(rebase_nvim_channal, 'nvim_buf_get_name', 0) + log.debug(bufname) + if vim.fn.fnamemodify(bufname, ':t') == 'git-rebase-todo' then + open_rebase() + else + open_commit() + end + rebase_todo_bufnr = create_autocmd_return_bufnr() + local text = vim.fn.rpcrequest(rebase_nvim_channal, 'nvim_buf_get_lines', 0, 0, -1, false) + vim.api.nvim_buf_set_lines(rebase_todo_bufnr, 0, -1, false, text) + vim.bo.modified = false + else + table.insert(std_data, v) + end + end +end + +function m.run(argv) + local cmd = { + 'git', + '--no-pager', + '-c', + [[core.editor=nvim -u NONE --headless -n --cmd "call chansend(v:stderr, ['', 'git-rebase-nvim-serverlist:' . serverlist()[0], ''])"]], + '-c', + 'color.status=always', + '-C', + vim.fn.expand(vim.fn.getcwd(), ':p'), + 'rebase', + } + for _, v in ipairs(argv) do + table.insert(cmd, v) + end + log.debug('git-rebase cmd:' .. vim.inspect(cmd)) + std_data = {} + job.start(cmd, { + on_exit = on_exit, + on_stdout = on_std, + on_stderr = on_std, + }) +end + +return m diff --git a/bundle/git.vim/lua/git/init.lua b/bundle/git.vim/lua/git/init.lua index 3b37677b1..1bd0c0b16 100644 --- a/bundle/git.vim/lua/git/init.lua +++ b/bundle/git.vim/lua/git/init.lua @@ -26,6 +26,7 @@ local cmds = { 'shortlog', 'status', 'grep', + 'rebase', 'tag', } local supported_commands = {} diff --git a/bundle/git.vim/syntax/git-commit.vim b/bundle/git.vim/syntax/git-commit.vim deleted file mode 100644 index ae46ea551..000000000 --- a/bundle/git.vim/syntax/git-commit.vim +++ /dev/null @@ -1,9 +0,0 @@ -if exists('b:current_syntax') - finish -endif -let b:current_syntax = 'git-commit' -syntax case ignore -syn match GitCommitIgnore /^\s*#.*/ - -hi def link GitCommitIgnore Comment - diff --git a/bundle/git.vim/syntax/git-rebase.vim b/bundle/git.vim/syntax/git-rebase.vim deleted file mode 100644 index b4c6989d5..000000000 --- a/bundle/git.vim/syntax/git-rebase.vim +++ /dev/null @@ -1,11 +0,0 @@ -if exists('b:current_syntax') - finish -endif -let b:current_syntax = 'git-rebase' -syntax case ignore -syn match GitRebaseIgnore /^\s*#.*/ -syn match GitRebaseKeyword /^pick\s/ - -hi def link GitRebaseIgnore Comment -hi def link GitRebaseKeyword Statement - diff --git a/docs/cn/roadmap.md b/docs/cn/roadmap.md index 38e62a192..864b9a74b 100644 --- a/docs/cn/roadmap.md +++ b/docs/cn/roadmap.md @@ -36,8 +36,8 @@ lang: zh - [x] `:Git mv` - [x] `:Git pull` - [x] `:Git push` - - [ ] `:Git rebase` - - [ ] `:Git reflog` + - [x] `:Git rebase` + - [x] `:Git reflog` - [x] `:Git remote` - [x] `:Git reset` - [x] `:Git rm` diff --git a/docs/roadmap.md b/docs/roadmap.md index 16346f5e3..3529164d8 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -36,7 +36,7 @@ If you have any suggestions , please checkout feedback section on [community](.. - [x] `:Git mv` - [x] `:Git pull` - [x] `:Git push` - - [ ] `:Git rebase` + - [x] `:Git rebase` - [x] `:Git reflog` - [x] `:Git remote` - [x] `:Git reset`