feat(diffthis): various improvements

- When running diffthis (or vim-fugitive's Gdiffsplit), hunk operations
  to the index will now update the diff buffer.

- Similar to vim-fugitive's Gdiffsplit, buffers of a file in the git
  index can now be edited. When the buffer is written, it updates the
  git index accordingly. Likewise the index buffer can also be reloaded
  (via 'edit').

- Moved all diffthis code to a separate module.

Fixes #501
This commit is contained in:
Lewis Russell 2022-04-01 12:26:19 +01:00 committed by Lewis Russell
parent 83ab3ca26f
commit acdd74bc6c
19 changed files with 499 additions and 178 deletions

View File

@ -182,6 +182,9 @@ diffthis({base}) *gitsigns.diffthis()*
Perform a |vimdiff| on the given file with {base} if it is
given, or with the currently set base (index by default).
If {base} is the index, then the opened diff buffer is editable
and any written changes will update the index accordingly.
Examples: >
" Diff against the index
:Gitsigns diffthis

View File

@ -40,6 +40,7 @@ build = {
['gitsigns.current_line_blame'] = 'lua/gitsigns/current_line_blame.lua',
['gitsigns.debounce'] = 'lua/gitsigns/debounce.lua',
['gitsigns.debug'] = 'lua/gitsigns/debug.lua',
['gitsigns.diffthis'] = 'lua/gitsigns/diffthis.lua',
['gitsigns.diff_ext'] = 'lua/gitsigns/diff_ext.lua',
['gitsigns.diff_int'] = 'lua/gitsigns/diff_int.lua',
['gitsigns.diff_int.xdl_diff_ffi'] = 'lua/gitsigns/diff_int/xdl_diff_ffi.lua',

100
lua/gitsigns/actions.lua generated
View File

@ -115,6 +115,13 @@ local function get_cursor_hunk(bufnr, hunks)
return gs_hunks.find_hunk(lnum, hunks)
end
local function update(bufnr)
manager.update(bufnr)
if vim.wo.diff then
require('gitsigns.diffthis').update(bufnr)
end
end
@ -165,7 +172,7 @@ M.stage_hunk = mk_repeatable(void(function(range)
table.insert(bcache.staged_diffs, hunk)
bcache.compare_text = nil
manager.update(bufnr)
update(bufnr)
end))
@ -249,7 +256,7 @@ M.undo_stage_hunk = void(function()
bcache.git_obj:stage_hunks({ hunk }, true)
bcache.compare_text = nil
manager.update(bufnr)
update(bufnr)
end)
@ -283,7 +290,7 @@ M.stage_buffer = void(function()
end
bcache.compare_text = nil
manager.update(bufnr)
update(bufnr)
end)
@ -311,7 +318,7 @@ M.reset_buffer_index = void(function()
bcache.compare_text = nil
scheduler()
manager.update(bufnr)
update(bufnr)
end)
local function process_nav_opts(opts)
@ -452,22 +459,6 @@ local function noautocmd(f)
end
local function strip_cr(xs0)
for i = 1, #xs0 do
if xs0[i]:sub(-1) ~= '\r' then
return xs0
end
end
local xs = vim.deepcopy(xs0)
for i = 1, #xs do
xs[i] = xs[i]:sub(1, -2)
end
return xs
end
M.preview_hunk = noautocmd(function()
@ -479,7 +470,7 @@ M.preview_hunk = noautocmd(function()
local hlines = gs_hunks.patch_lines(hunk)
if vim.bo[cbuf].fileformat == 'dos' then
hlines = strip_cr(hlines)
hlines = util.strip_cr(hlines)
end
local lines = {
@ -677,17 +668,10 @@ M.blame_line = void(function(opts)
end
end)
local function calc_base(base)
if base and base:sub(1, 1):match('[~\\^]') then
base = 'HEAD' .. base
end
return base
end
local function update_buf_base(buf, bcache, base)
bcache.base = base
bcache.compare_text = nil
manager.update(buf, bcache)
update(buf)
end
@ -724,7 +708,7 @@ end
M.change_base = void(function(base, global)
base = calc_base(base)
base = util.calc_base(base)
if global then
config.base = base
@ -765,61 +749,13 @@ end
M.diffthis = void(function(base)
local bufnr = current_buf()
local bcache = cache[bufnr]
if not bcache then return end
if api.nvim_win_get_option(0, 'diff') then return end
local ff = vim.bo[bufnr].fileformat
local text
local err
local comp_rev = bcache:get_compare_rev(calc_base(base))
if base then
text, err = bcache.git_obj:get_show_text(comp_rev)
if ff == 'dos' then
text = strip_cr(text)
end
if err then
print(err)
return
end
scheduler()
else
text = bcache:get_compare_text()
end
local ft = api.nvim_buf_get_option(bufnr, 'filetype')
local bufname = string.format(
'gitsigns://%s/%s',
bcache.git_obj.repo.gitdir,
comp_rev .. ':' .. bcache.git_obj.relpath)
vim.cmd('diffthis')
vim.cmd(table.concat({
'keepalt', 'aboveleft',
config.diff_opts.vertical and 'vertical' or '',
'split', bufname,
}, ' '))
local dbuf = current_buf()
api.nvim_buf_set_option(dbuf, 'modifiable', true)
util.set_lines(dbuf, 0, -1, text)
api.nvim_buf_set_option(dbuf, 'modifiable', false)
api.nvim_buf_set_option(dbuf, 'filetype', ft)
api.nvim_buf_set_option(dbuf, 'buftype', 'nowrite')
api.nvim_buf_set_option(dbuf, 'bufhidden', 'wipe')
vim.cmd('diffthis')
end)
M.diffthis = function(base)
local diffthis = require('gitsigns.diffthis')
diffthis.run(base, config.diff_opts.vertical)
end
local function hunks_to_qflist(buf_or_filename, hunks, qflist)
for i, hunk in ipairs(hunks) do

View File

@ -5,6 +5,7 @@ local fun1 = {}
local fun2 = {}
local fun2_2 = {}
local fun3 = {}
local fun4 = {}
local Async = {}
@ -18,6 +19,7 @@ local Async = {}
local async_thread = {
threads = {},
}

10
lua/gitsigns/cache.lua generated
View File

@ -29,6 +29,7 @@ local M = {CacheEntry = {}, CacheObj = {}, }
local CacheEntry = M.CacheEntry
@ -48,6 +49,15 @@ CacheEntry.get_compare_rev = function(self, base)
return string.format(':%d', stage)
end
CacheEntry.get_diffthis_bufname = function(self, rev)
rev = rev or self:get_compare_rev()
return string.format(
'gitsigns://%s/%s',
self.git_obj.repo.gitdir,
rev .. ':' .. self.git_obj.relpath)
end
CacheEntry.get_compare_text = function(self)
if self.compare_text then
return self.compare_text

View File

@ -51,7 +51,7 @@ end
function M.throttle_by_id(fn)
function M.throttle_by_id(fn, schedule)
local scheduled = {}
local running = {}
return function(id, ...)
@ -59,7 +59,9 @@ function M.throttle_by_id(fn)
return
end
scheduled[id] = true
if not running[id] or schedule then
scheduled[id] = true
end
if running[id] then
return
end

162
lua/gitsigns/diffthis.lua generated Normal file
View File

@ -0,0 +1,162 @@
local api = vim.api
local void = require('gitsigns.async').void
local scheduler = require('gitsigns.async').scheduler
local awrap = require('gitsigns.async').wrap
local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache
local CacheEntry = gs_cache.CacheEntry
local nvim = require('gitsigns.nvim')
local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local throttle_by_id = require('gitsigns.debounce').throttle_by_id
local input = awrap(vim.ui.input, 2)
local M = {}
local bufread = void(function(bufnr, dbufnr, base, bcache)
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
local text
if util.calc_base(base) == util.calc_base(bcache.base) then
text = bcache:get_compare_text()
else
local err
text, err = bcache.git_obj:get_show_text(comp_rev)
if err then
print(err)
return
end
if vim.bo[bufnr].fileformat == 'dos' then
text = util.strip_cr(text)
end
scheduler()
end
local modifiable = vim.bo[dbufnr].modifiable
vim.bo[dbufnr].modifiable = true
util.set_lines(dbufnr, 0, -1, text)
vim.bo[dbufnr].modifiable = modifiable
vim.bo[dbufnr].modified = false
vim.bo[dbufnr].filetype = vim.bo[bufnr].filetype
vim.bo[dbufnr].bufhidden = 'wipe'
vim.cmd('diffthis')
end)
local bufwrite = void(function(bufnr, dbufnr, base, bcache)
local buftext = util.buf_lines(dbufnr)
bcache.git_obj:stage_lines(buftext)
vim.bo[dbufnr].modified = false
if util.calc_base(base) == util.calc_base(bcache.base) then
bcache.compare_text = buftext
manager.update(bufnr, bcache)
end
end)
M.run = void(function(base, vertical)
local bufnr = vim.api.nvim_get_current_buf()
local bcache = cache[bufnr]
if not bcache then
return
end
if vim.wo.diff then
return
end
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
local bufname = bcache:get_diffthis_bufname(comp_rev)
vim.cmd('diffthis')
vim.cmd(table.concat({
'keepalt', 'aboveleft',
vertical and 'vertical' or '',
'split', bufname,
}, ' '))
local dbuf = vim.api.nvim_get_current_buf()
bufread(bufnr, dbuf, base, bcache)
if comp_rev == ':0' then
vim.bo[dbuf].buftype = 'acwrite'
nvim.autocmd('BufReadCmd', {
group = 'gitsigns',
buffer = dbuf,
callback = function()
bufread(bufnr, dbuf, base, bcache)
end,
})
nvim.autocmd('BufWriteCmd', {
group = 'gitsigns',
buffer = dbuf,
callback = function()
bufwrite(bufnr, dbuf, base, bcache)
end,
})
else
vim.bo[dbuf].buftype = 'nowrite'
vim.bo[dbuf].modifiable = false
end
end)
local function should_reload(bufnr)
if not vim.bo[bufnr].modified then
return true
end
local response
while not vim.tbl_contains({ 'O', 'L' }, response) do
response = input({
prompt = 'Warning: The git index has changed and the buffer was changed as well. [O]K, (L)oad File:',
})
end
return response == 'L'
end
M.update = throttle_by_id(void(function(bufnr)
if not vim.wo.diff then
return
end
local bcache = cache[bufnr]
local bufname = bcache:get_diffthis_bufname()
for _, w in ipairs(api.nvim_list_wins()) do
if api.nvim_win_is_valid(w) then
local b = api.nvim_win_get_buf(w)
local bname = api.nvim_buf_get_name(b)
if bname == bufname or vim.startswith(bname, 'fugitive://') then
if should_reload(b) then
api.nvim_buf_call(b, function()
vim.cmd('doautocmd BufReadCmd')
vim.cmd('diffthis')
end)
end
end
end
end
end))
return M

15
lua/gitsigns/git.lua generated
View File

@ -107,6 +107,7 @@ local M = {BlameInfo = {}, Version = {}, Repo = {}, FileProps = {}, Obj = {}, }
local in_git_dir = function(file)
@ -451,7 +452,7 @@ Obj.ensure_file_in_index = function(self)
else
local info = table.concat({ self.mode_bits, self.object_name, self.relpath }, ',')
local info = string.format('%s,%s,%s', self.mode_bits, self.object_name, self.relpath)
self:command({ 'update-index', '--add', '--cacheinfo', info })
end
@ -459,6 +460,18 @@ Obj.ensure_file_in_index = function(self)
end
end
Obj.stage_lines = function(self, lines)
local stdout = self:command({
'hash-object', '-w', '--path', self.relpath, '--stdin',
}, { writer = lines })
local new_object = stdout[1]
self:command({
'update-index', '--cacheinfo', string.format('%s,%s,%s', self.mode_bits, new_object, self.relpath),
})
end
Obj.stage_hunks = function(self, hunks, invert)
self:ensure_file_in_index()
self:command({

View File

@ -328,7 +328,7 @@ end
M.update = throttle_by_id(update0)
M.update = throttle_by_id(update0, true)
M.setup = function()
M.update_debounced = debounce_trailing(config.update_debounce, void(M.update))

24
lua/gitsigns/util.lua generated
View File

@ -107,4 +107,28 @@ function M.copy_array(x)
return r
end
function M.strip_cr(xs0)
for i = 1, #xs0 do
if xs0[i]:sub(-1) ~= '\r' then
return xs0
end
end
local xs = vim.deepcopy(xs0)
for i = 1, #xs do
xs[i] = xs[i]:sub(1, -2)
end
return xs
end
function M.calc_base(base)
if base and base:sub(1, 1):match('[~\\^]') then
base = 'HEAD' .. base
end
return base
end
return M

View File

@ -47,7 +47,7 @@ local record M
blame_line : function -- function()
change_base : function(base: string, global: boolean)
reset_base : function(global: boolean)
diffthis : function -- function(base: string)
diffthis : function(base: string)
record QFListOpts
use_location_list: boolean
@ -115,6 +115,13 @@ local function get_cursor_hunk(bufnr: integer, hunks: {Hunk}): Hunk, integer
return gs_hunks.find_hunk(lnum, hunks)
end
local function update(bufnr: integer)
manager.update(bufnr)
if vim.wo.diff then
require('gitsigns.diffthis').update(bufnr)
end
end
--- Stage the hunk at the cursor position, or all lines in the
--- given range. If {range} is provided, all lines in the given
--- range are staged. This supports partial-hunks, meaning if a
@ -165,7 +172,7 @@ M.stage_hunk = mk_repeatable(void(function(range: {integer, integer})
table.insert(bcache.staged_diffs, hunk)
bcache.compare_text = nil -- Invalidate
manager.update(bufnr)
update(bufnr)
end))
--- Reset the lines of the hunk at the cursor position, or all
@ -249,7 +256,7 @@ M.undo_stage_hunk = void(function()
bcache.git_obj:stage_hunks({hunk}, true)
bcache.compare_text = nil -- Invalidate
manager.update(bufnr)
update(bufnr)
end)
--- Stage all hunks in current buffer.
@ -283,7 +290,7 @@ M.stage_buffer = void(function()
end
bcache.compare_text = nil -- Invalidate
manager.update(bufnr)
update(bufnr)
end)
--- Unstage all hunks for current buffer in the index. Note:
@ -311,7 +318,7 @@ M.reset_buffer_index = void(function()
bcache.compare_text = nil -- Invalidate
scheduler()
manager.update(bufnr)
update(bufnr)
end)
local function process_nav_opts(opts: NavHunkOpts)
@ -451,22 +458,6 @@ local function noautocmd(f: function()): function()
end
end
-- Strip '\r' from the EOL of each line only if all lines end with '\r'
local function strip_cr(xs0: {string}): {string}
for i = 1, #xs0 do
if xs0[i]:sub(-1) ~= '\r' then
-- don't strip, return early
return xs0
end
end
-- all lines end with '\r', need to strip
local xs = vim.deepcopy(xs0)
for i = 1, #xs do
xs[i] = xs[i]:sub(1, -2)
end
return xs
end
--- Preview the hunk at the cursor position in a floating
--- window.
M.preview_hunk = noautocmd(function()
@ -479,7 +470,7 @@ M.preview_hunk = noautocmd(function()
local hlines = gs_hunks.patch_lines(hunk)
if vim.bo[cbuf].fileformat == 'dos' then
hlines = strip_cr(hlines)
hlines = util.strip_cr(hlines)
end
local lines = {
@ -677,17 +668,10 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
end
end)
local function calc_base(base: string): string
if base and base:sub(1, 1):match('[~\\^]') then
base = 'HEAD'..base
end
return base
end
local function update_buf_base(buf: integer, bcache: CacheEntry, base: string)
bcache.base = base
bcache.compare_text = nil
manager.update(buf, bcache)
update(buf)
end
--- Change the base revision to diff against. If {base} is not
@ -724,7 +708,7 @@ end
--- For a more complete list of ways to specify bases, see
--- |gitsigns-revision|.
M.change_base = void(function(base: string, global: boolean)
base = calc_base(base)
base = util.calc_base(base)
if global then
config.base = base
@ -752,6 +736,9 @@ end
--- Perform a |vimdiff| on the given file with {base} if it is
--- given, or with the currently set base (index by default).
---
--- If {base} is the index, then the opened diff buffer is editable
--- and any written changes will update the index accordingly.
---
--- Examples: >
--- " Diff against the index
--- :Gitsigns diffthis
@ -765,61 +752,10 @@ end
---
--- Attributes: ~
--- {async}
M.diffthis = void(function(base: string)
local bufnr = current_buf()
local bcache = cache[bufnr]
if not bcache then return end
if api.nvim_win_get_option(0, 'diff') then return end
local ff = vim.bo[bufnr].fileformat
local text: {string}
local err: string
local comp_rev = bcache:get_compare_rev(calc_base(base))
if base then
text, err = bcache.git_obj:get_show_text(comp_rev)
if ff == 'dos' then
text = strip_cr(text)
end
if err then
print(err)
return
end
scheduler()
else
text = bcache:get_compare_text()
end
local ft = api.nvim_buf_get_option(bufnr, 'filetype')
local bufname = string.format(
'gitsigns://%s/%s',
bcache.git_obj.repo.gitdir,
comp_rev..':'..bcache.git_obj.relpath
)
vim.cmd'diffthis'
vim.cmd(table.concat({
'keepalt', 'aboveleft',
config.diff_opts.vertical and 'vertical' or '',
'split', bufname
}, ' '))
local dbuf = current_buf()
api.nvim_buf_set_option(dbuf, 'modifiable', true)
util.set_lines(dbuf, 0, -1, text)
api.nvim_buf_set_option(dbuf, 'modifiable', false)
api.nvim_buf_set_option(dbuf, 'filetype', ft)
api.nvim_buf_set_option(dbuf, 'buftype', 'nowrite')
api.nvim_buf_set_option(dbuf, 'bufhidden', 'wipe')
vim.cmd'diffthis'
end)
M.diffthis = function(base: string)
local diffthis = require('gitsigns.diffthis')
diffthis.run(base, config.diff_opts.vertical)
end
local function hunks_to_qflist(buf_or_filename: number|string, hunks: {Hunk}, qflist: {vim.fn.QFItem})
for i, hunk in ipairs(hunks) do

View File

@ -5,11 +5,13 @@ local type fun1 = function <A1> (A1)
local type fun2 = function <A1,A2> (A1,A2)
local type fun2_2 = function <A1,A2,R1,R2> (A1,A2) : R1,R2
local type fun3 = function <A1,A2,A3> (A1,A2,A3)
local type fun4 = function <A1,A2,A3,A4> (A1,A2,A3,A4)
local record Async
void: function (fun0 ): fun0
void: function<A1> (fun1<A1> ): fun1<A1>
void: function<A1,A2>(fun2<A1,A2>): fun2<A1,A2>
void: function<A1,A2,A3,A4>(fun4<A1,A2,A3,A4>): fun4<A1,A2,A3,A4>
wrap: function<A1,A2,R1,R2>(function(A1,A2, function(R1,R2)), integer): fun2_2 <A1,A2,R1,R2>
wrap: function<A1,A2,A3> (function(A1,A2,A3,function()) , integer): fun3 <A1,A2,A3>

View File

@ -18,6 +18,7 @@ local record M
get_compare_rev: function(CacheEntry, base: string): string
get_compare_text: function(self: CacheEntry): {string}
get_diffthis_bufname: function(self: CacheEntry, rev: string): string
new: function(CacheEntry): CacheEntry
destroy: function(CacheEntry)
end
@ -48,6 +49,15 @@ CacheEntry.get_compare_rev = function(self: CacheEntry, base: string): string
return string.format(':%d', stage)
end
CacheEntry.get_diffthis_bufname = function(self: CacheEntry, rev: string): string
rev = rev or self:get_compare_rev()
return string.format(
'gitsigns://%s/%s',
self.git_obj.repo.gitdir,
rev..':'..self.git_obj.relpath
)
end
CacheEntry.get_compare_text = function(self: CacheEntry): {string}
if self.compare_text then
return self.compare_text

View File

@ -51,7 +51,7 @@ end
--
--@param fn (function) Function to throttle
--@returns (function) throttled function.
function M.throttle_by_id(fn: function): function
function M.throttle_by_id(fn: function, schedule: boolean): function
local scheduled: {any:boolean} = {}
local running: {any:boolean} = {}
return function(id: any, ...)
@ -59,7 +59,9 @@ function M.throttle_by_id(fn: function): function
-- If fn is already scheduled, then drop
return
end
scheduled[id] = true
if not running[id] or schedule then
scheduled[id] = true
end
if running[id] then
return
end

162
teal/gitsigns/diffthis.tl Normal file
View File

@ -0,0 +1,162 @@
local api = vim.api
local void = require('gitsigns.async').void
local scheduler = require('gitsigns.async').scheduler
local awrap = require('gitsigns.async').wrap
local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache
local CacheEntry = gs_cache.CacheEntry
local nvim = require('gitsigns.nvim')
local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local throttle_by_id = require('gitsigns.debounce').throttle_by_id
local input = awrap(vim.ui.input, 2)
local record M
run: function
update: function
end
local bufread = void(function(bufnr: integer, dbufnr: integer, base: string, bcache: CacheEntry)
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
local text: {string}
if util.calc_base(base) == util.calc_base(bcache.base) then
text = bcache:get_compare_text()
else
local err: string
text, err = bcache.git_obj:get_show_text(comp_rev)
if err then
print(err)
return
end
if vim.bo[bufnr].fileformat == 'dos' then
text = util.strip_cr(text)
end
scheduler()
end
local modifiable = vim.bo[dbufnr].modifiable
vim.bo[dbufnr].modifiable = true
util.set_lines(dbufnr, 0, -1, text)
vim.bo[dbufnr].modifiable = modifiable
vim.bo[dbufnr].modified = false
vim.bo[dbufnr].filetype = vim.bo[bufnr].filetype
vim.bo[dbufnr].bufhidden = 'wipe'
vim.cmd'diffthis'
end)
local bufwrite = void(function(bufnr: integer, dbufnr: integer, base: string, bcache: CacheEntry)
local buftext = util.buf_lines(dbufnr)
bcache.git_obj:stage_lines(buftext)
vim.bo[dbufnr].modified = false
-- If diff buffer base matches the bcache base then also update the
-- signs.
if util.calc_base(base) == util.calc_base(bcache.base) then
bcache.compare_text = buftext
manager.update(bufnr, bcache)
end
end)
M.run = void(function(base: string, vertical: boolean)
local bufnr = vim.api.nvim_get_current_buf()
local bcache = cache[bufnr]
if not bcache then
return
end
if vim.wo.diff then
return
end
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
local bufname = bcache:get_diffthis_bufname(comp_rev)
vim.cmd'diffthis'
vim.cmd(table.concat({
'keepalt', 'aboveleft',
vertical and 'vertical' or '',
'split', bufname
}, ' '))
local dbuf = vim.api.nvim_get_current_buf()
bufread(bufnr, dbuf, base, bcache)
if comp_rev == ':0' then
vim.bo[dbuf].buftype = 'acwrite'
nvim.autocmd('BufReadCmd', {
group = 'gitsigns',
buffer = dbuf,
callback = function()
bufread(bufnr, dbuf, base, bcache)
end
})
nvim.autocmd('BufWriteCmd', {
group = 'gitsigns',
buffer = dbuf,
callback = function()
bufwrite(bufnr, dbuf, base, bcache)
end
})
else
vim.bo[dbuf].buftype = 'nowrite'
vim.bo[dbuf].modifiable = false
end
end)
local function should_reload(bufnr: integer): boolean
if not vim.bo[bufnr].modified then
return true
end
local response: string
while not vim.tbl_contains({'O', 'L'}, response) do
response = input{
prompt = 'Warning: The git index has changed and the buffer was changed as well. [O]K, (L)oad File:'
}
end
return response == 'L'
end
-- This function needs to be throttled as there is a call to vim.ui.input
M.update = throttle_by_id(void(function(bufnr: integer)
if not vim.wo.diff then
return
end
local bcache = cache[bufnr]
-- Note this will be the bufname for the currently set base
-- which are the only ones we want to update
local bufname = bcache:get_diffthis_bufname()
for _, w in ipairs(api.nvim_list_wins()) do
if api.nvim_win_is_valid(w) then
local b = api.nvim_win_get_buf(w)
local bname = api.nvim_buf_get_name(b)
if bname == bufname or vim.startswith(bname, 'fugitive://') then
if should_reload(b) then
api.nvim_buf_call(b, function(): nil
vim.cmd('doautocmd BufReadCmd')
vim.cmd('diffthis')
end)
end
end
end
end
end))
return M

View File

@ -103,6 +103,7 @@ local record M
get_show_text : function(Obj, string): {string}, string
ensure_file_in_index : function(Obj)
stage_hunks : function(Obj, {Hunk}, boolean)
stage_lines : function(Obj, {string})
has_moved : function(Obj): string
new : function(string): Obj
end
@ -451,7 +452,7 @@ Obj.ensure_file_in_index = function(self: Obj)
else
-- Update the index with the common ancestor (stage 1) which is what bcache
-- stores
local info = table.concat({self.mode_bits, self.object_name, self.relpath}, ',')
local info = string.format('%s,%s,%s', self.mode_bits, self.object_name, self.relpath)
self:command{'update-index', '--add', '--cacheinfo', info}
end
@ -459,6 +460,18 @@ Obj.ensure_file_in_index = function(self: Obj)
end
end
Obj.stage_lines = function(self: Obj, lines: {string})
local stdout = self:command({
'hash-object', '-w', '--path', self.relpath, '--stdin'
}, { writer = lines })
local new_object = stdout[1]
self:command{
'update-index', '--cacheinfo', string.format('%s,%s,%s', self.mode_bits, new_object, self.relpath)
}
end
Obj.stage_hunks = function(self: Obj, hunks: {Hunk}, invert: boolean)
self:ensure_file_in_index()
self:command({

View File

@ -328,7 +328,7 @@ end
-- Since updates are asynchronous we need to make sure an update isn't performed
-- whilst another one is in progress. If this happens then schedule another
-- update after the current one has completed.
M.update = throttle_by_id(update0) as function(integer, CacheEntry)
M.update = throttle_by_id(update0, true) as function(integer, CacheEntry)
M.setup = function()
M.update_debounced = debounce_trailing(config.update_debounce, void(M.update)) as function(integer)

View File

@ -107,4 +107,28 @@ function M.copy_array<T>(x: {T}): {T}
return r
end
-- Strip '\r' from the EOL of each line only if all lines end with '\r'
function M.strip_cr(xs0: {string}): {string}
for i = 1, #xs0 do
if xs0[i]:sub(-1) ~= '\r' then
-- don't strip, return early
return xs0
end
end
-- all lines end with '\r', need to strip
local xs = vim.deepcopy(xs0)
for i = 1, #xs do
xs[i] = xs[i]:sub(1, -2)
end
return xs
end
function M.calc_base(base: string): string
if base and base:sub(1, 1):match('[~\\^]') then
base = 'HEAD'..base
end
return base
end
return M

View File

@ -137,7 +137,7 @@ local record api
nvim_list_runtime_paths: function(): {string}
nvim_list_tabpages: function(): {any}
nvim_list_uis: function(): any
nvim_list_wins: function(): {number}
nvim_list_wins: function(): {integer}
nvim_load_context: function({string:any}): any
nvim_open_win: function(number, boolean, {string:any}): integer
nvim_out_write: function(string)
@ -178,7 +178,7 @@ local record api
nvim_win_call: function<T>(number, (function(): T)): T
nvim_win_close: function(number, boolean)
nvim_win_del_var: function(number, string)
nvim_win_get_buf: function(number): number
nvim_win_get_buf: function(integer): integer
nvim_win_get_config: function(number): {string:any}
nvim_win_get_cursor: function(number): {integer}
nvim_win_get_height: function(integer): integer
@ -209,6 +209,7 @@ global record vim
executable: function(string): integer
expand: function(string): string
getcwd: function(): string
input: function(string, string): string
record QFItem
bufnr: integer
@ -290,6 +291,20 @@ global record vim
record BufOption
{BufOption}
fileformat: string
filetype: string
modifiable: boolean
modified: boolean
enum BufHidden
'' 'hide' 'unload' 'delete' 'wipe'
end
bufhidden: BufHidden
enum BufType
'' 'acwrite' 'help' 'nofile' 'nowrite' 'quickfix' 'terminal' 'prompt'
end
buftype: BufType
end
bo: BufOption
@ -489,6 +504,10 @@ global record vim
wait: function(number, function, number, boolean)
record ui
input: function({string:any}, function(string))
end
record VersionDetails
api_compatible: integer
api_level: integer