Skip to content

Commit a4df783

Browse files
committed
Use gitsigns.nvim to display inline diffs in the "diff1_inline" layout.
1 parent dc77f48 commit a4df783

File tree

8 files changed

+109
-17
lines changed

8 files changed

+109
-17
lines changed

lua/diffview/actions.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ local utils = lazy.require("diffview.utils") ---@module "diffview.utils"
99
local vcs_utils = lazy.require("diffview.vcs.utils") ---@module "diffview.vcs.utils"
1010

1111
local Diff1 = lazy.access("diffview.scene.layouts.diff_1", "Diff1") ---@type Diff1|LazyModule
12+
local Diff1Inline = lazy.access("diffview.scene.layouts.diff_1_inline", "Diff1Inline") ---@type Diff1Inline|LazyModule
1213
local Diff2Hor = lazy.access("diffview.scene.layouts.diff_2_hor", "Diff2Hor") ---@type Diff2Hor|LazyModule
1314
local Diff2Ver = lazy.access("diffview.scene.layouts.diff_2_ver", "Diff2Ver") ---@type Diff2Ver|LazyModule
1415
local Diff3 = lazy.access("diffview.scene.layouts.diff_3", "Diff3") ---@type Diff3|LazyModule
@@ -418,6 +419,7 @@ function M.cycle_layout()
418419
standard = {
419420
Diff2Hor.__get(),
420421
Diff2Ver.__get(),
422+
Diff1Inline.__get(),
421423
},
422424
merge_tool = {
423425
Diff3Hor.__get(),

lua/diffview/config.lua

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local actions = require("diffview.actions")
44
local lazy = require("diffview.lazy")
55

66
local Diff1 = lazy.access("diffview.scene.layouts.diff_1", "Diff1") ---@type Diff1|LazyModule
7+
local Diff1Inline = lazy.access("diffview.scene.layouts.diff_1_inline", "Diff1Inline") ---@type Diff1Inline|LazyModule
78
local Diff2 = lazy.access("diffview.scene.layouts.diff_2", "Diff2") ---@type Diff2|LazyModule
89
local Diff2Hor = lazy.access("diffview.scene.layouts.diff_2_hor", "Diff2Hor") ---@type Diff2Hor|LazyModule
910
local Diff2Ver = lazy.access("diffview.scene.layouts.diff_2_ver", "Diff2Ver") ---@type Diff2Ver|LazyModule
@@ -312,6 +313,7 @@ function M.get_log_options(single_file, t, vcs)
312313
end
313314

314315
---@alias LayoutName "diff1_plain"
316+
--- | "diff1_inline"
315317
--- | "diff2_horizontal"
316318
--- | "diff2_vertical"
317319
--- | "diff3_horizontal"
@@ -321,6 +323,7 @@ end
321323

322324
local layout_map = {
323325
diff1_plain = Diff1,
326+
diff1_inline = Diff1Inline,
324327
diff2_horizontal = Diff2Hor,
325328
diff2_vertical = Diff2Ver,
326329
diff3_horizontal = Diff3Hor,
@@ -510,7 +513,7 @@ function M.setup(user_config)
510513
do
511514
-- Validate layouts
512515
local view = M._config.view
513-
local standard_layouts = { "diff2_horizontal", "diff2_vertical", -1 }
516+
local standard_layouts = { "diff2_horizontal", "diff2_vertical", "diff1_inline", -1 }
514517
local merge_layuots = {
515518
"diff1_plain",
516519
"diff3_horizontal",

lua/diffview/scene/file_entry.lua

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ function FileEntry:convert_layout(target_layout)
123123
end
124124

125125
self.layout = target_layout({
126+
parent = self,
126127
a = utils.tbl_access(self.layout, "a.file") or create_file(self.revs.a, "a"),
127128
b = utils.tbl_access(self.layout, "b.file") or create_file(self.revs.b, "b"),
128129
c = utils.tbl_access(self.layout, "c.file") or create_file(self.revs.c, "c"),
@@ -243,7 +244,7 @@ function FileEntry.with_layout(layout_class, opt)
243244
}) --[[@as vcs.File ]]
244245
end
245246

246-
return FileEntry({
247+
local entry = FileEntry({
247248
adapter = opt.adapter,
248249
path = opt.path,
249250
oldpath = opt.oldpath,
@@ -252,13 +253,17 @@ function FileEntry.with_layout(layout_class, opt)
252253
kind = opt.kind,
253254
commit = opt.commit,
254255
revs = opt.revs,
255-
layout = layout_class({
256-
a = create_file(opt.revs.a, "a"),
257-
b = create_file(opt.revs.b, "b"),
258-
c = create_file(opt.revs.c, "c"),
259-
d = create_file(opt.revs.d, "d"),
260-
}),
261256
})
257+
258+
entry.layout = layout_class({
259+
parent = entry,
260+
a = create_file(opt.revs.a, "a"),
261+
b = create_file(opt.revs.b, "b"),
262+
c = create_file(opt.revs.c, "c"),
263+
d = create_file(opt.revs.d, "d"),
264+
})
265+
266+
return entry
262267
end
263268

264269
M.FileEntry = FileEntry

lua/diffview/scene/layout.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ local api = vim.api
88
local M = {}
99

1010
---@class Layout : diffview.Object
11+
---@field parent FileEntry
1112
---@field windows Window[]
1213
---@field emitter EventEmitter
1314
---@field pivot_producer fun(): integer?
1415
local Layout = oop.create_class("Layout")
1516

1617
function Layout:init(opt)
1718
opt = opt or {}
19+
self.parent = opt.parent
1820
self.windows = opt.windows or {}
1921
self.emitter = opt.emitter or EventEmitter()
2022

lua/diffview/scene/layouts/diff_1.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
local lazy = require("diffview.lazy")
21
local Layout = require("diffview.scene.layout").Layout
2+
local lazy = require("diffview.lazy")
33
local oop = require("diffview.oop")
44

55
local Diff3 = lazy.access("diffview.scene.layouts.diff_3", "Diff3") ---@type Diff3|LazyModule
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
local Diff1 = require("diffview.scene.layouts.diff_1").Diff1
2+
local lazy = require("diffview.lazy")
3+
local oop = require("diffview.oop")
4+
5+
local M = {}
6+
7+
---@class Diff1Inline : Diff1
8+
local Diff1Inline = oop.create_class("Diff1Inline", Diff1)
9+
10+
---@param opt Diff1.init.Opt
11+
function Diff1Inline:init(opt)
12+
Diff1Inline:super().init(self, opt)
13+
end
14+
15+
M.Diff1Inline = Diff1Inline
16+
return M

lua/diffview/scene/window.lua

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
local lazy = require("diffview.lazy")
22
local oop = require("diffview.oop")
33

4+
local Diff1 = lazy.access("diffview.scene.layouts.diff_1", "Diff1") ---@type Diff1|LazyModule
45
local File = lazy.access("diffview.vcs.file", "File") ---@type vcs.File|LazyModule
56
local FileHistoryView = lazy.access("diffview.scene.views.file_history.file_history_view", "FileHistoryView") ---@type FileHistoryView|LazyModule
7+
local GitAdapter = lazy.access("diffview.vcs.adapters.git", "GitAdapter") ---@type GitAdapter|LazyModule
68
local RevType = lazy.access("diffview.vcs.rev", "RevType") ---@type RevType|LazyModule
79
local config = lazy.require("diffview.config") ---@module "diffview.config"
810
local lib = lazy.require("diffview.lib") ---@module "diffview.lib"
@@ -69,6 +71,12 @@ function Window:pre_open()
6971
end
7072
end
7173

74+
function Window:is_file_open()
75+
return self:is_valid()
76+
and self.file:is_valid()
77+
and api.nvim_win_get_buf(self.id) == self.file.bufnr
78+
end
79+
7280
---@param callback fun(file: vcs.File)
7381
function Window:load_file(callback)
7482
assert(self.file)
@@ -95,11 +103,25 @@ function Window:open_file(callback)
95103
self:_save_winopts()
96104
end
97105

98-
self:apply_file_winopts()
106+
local winopt_overrides
107+
local base_rev = utils.tbl_access(self, "parent.parent.revs.a") --[[@as Rev? ]]
108+
local use_inline_diff = self.file.kind ~= "conflicting"
109+
and self.parent:instanceof(Diff1.__get())
110+
and self.file.adapter:instanceof(GitAdapter.__get())
111+
112+
if use_inline_diff then
113+
winopt_overrides = { foldmethod = "manual", diff = false }
114+
end
115+
116+
self:apply_file_winopts(winopt_overrides)
99117
self.file:attach_buffer(false, {
100118
keymaps = config.get_layout_keymaps(self.parent),
101119
disable_diagnostics = self.file.kind == "conflicting"
102120
and conf.view.merge_tool.disable_diagnostics,
121+
inline_diff = {
122+
enabled = use_inline_diff,
123+
base = base_rev and base_rev:object_name(),
124+
}
103125
})
104126

105127
if self:show_winbar_info() then
@@ -198,11 +220,16 @@ function Window:_restore_winopts()
198220
end
199221
end
200222

201-
function Window:apply_file_winopts()
223+
---@param overrides WindowOptions?
224+
function Window:apply_file_winopts(overrides)
202225
assert(self.file)
203226
if self.file.winopts then
227+
if overrides then
228+
utils.set_local(self.id, vim.tbl_extend("force", self.file.winopts, overrides))
229+
else
204230
utils.set_local(self.id, self.file.winopts)
205231
end
232+
end
206233
end
207234

208235
function Window:apply_null_winopts()

lua/diffview/vcs/file.lua

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,18 @@ local GitRev = lazy.access("diffview.vcs.adapters.git.rev", "GitRev") ---@type G
55
local RevType = lazy.access("diffview.vcs.rev", "RevType") ---@type RevType|LazyModule
66
local async = lazy.require("plenary.async") ---@module "plenary.async"
77
local config = lazy.require("diffview.config") ---@module "diffview.config"
8+
local debounce = lazy.require("diffview.debounce") ---@module "diffview.debounce"
9+
local gs_actions = lazy.require("gitsigns.actions") ---@module "gitsigns.actions"
810
local lib = lazy.require("diffview.lib") ---@module "diffview.lib"
911
local utils = lazy.require("diffview.utils") ---@module "diffview.utils"
1012

1113
local pl = lazy.access(utils, "path") ---@type PathLib|LazyModule
1214

15+
local gs_refresh = debounce.debounce_trailing(20, false, vim.schedule_wrap(function(callback)
16+
gs_actions.refresh()
17+
if vim.is_callable(callback) then callback() end
18+
end))
19+
1320
local api = vim.api
1421
local M = {}
1522

@@ -279,10 +286,18 @@ end
279286
---@param t2 table
280287
---@return vcs.File.AttachState
281288
local function prepare_attach_opt(t1, t2)
282-
local res = vim.tbl_extend("keep", t1, {
289+
---@class vcs.File.AttachState
290+
local default_opt = {
283291
keymaps = {},
284292
disable_diagnostics = false,
285-
})
293+
inline_diff = {
294+
enabled = false,
295+
base = nil --[[@as string? ]],
296+
update = nil --[[@as function? ]],
297+
}
298+
}
299+
300+
local res = vim.tbl_extend("force", default_opt, t1)
286301

287302
for k, v in pairs(t2) do
288303
local t = type(res[k])
@@ -299,10 +314,6 @@ local function prepare_attach_opt(t1, t2)
299314
return res
300315
end
301316

302-
---@class vcs.File.AttachState
303-
---@field keymaps table
304-
---@field disable_diagnostics boolean
305-
306317
---@param force? boolean
307318
---@param opt? vcs.File.AttachState
308319
function File:attach_buffer(force, opt)
@@ -332,6 +343,23 @@ function File:attach_buffer(force, opt)
332343
vim.diagnostic.disable(self.bufnr)
333344
end
334345

346+
-- Inline diff
347+
if state.inline_diff.enabled then
348+
local gitsigns = require("gitsigns")
349+
local gs_config = require("gitsigns.config").config
350+
gitsigns.attach(self.bufnr, {
351+
file = self.path,
352+
toplevel = self.adapter.ctx.toplevel,
353+
gitdir = self.adapter.ctx.dir,
354+
commit = self.rev.type ~= RevType.LOCAL and self.rev:object_name() or nil,
355+
base = utils.sate(state.inline_diff.base, self.rev.type == RevType.STAGE and "HEAD"),
356+
})
357+
gs_config.linehl = true
358+
gs_config.show_deleted = true
359+
gs_config.word_diff = true
360+
gs_refresh(state.inline_diff.update)
361+
end
362+
335363
File.attached[self.bufnr] = state
336364
end
337365
end
@@ -359,6 +387,15 @@ function File:detach_buffer()
359387
vim.diagnostic.enable(self.bufnr)
360388
end
361389

390+
-- Inline diff
391+
if state.inline_diff.enabled then
392+
local gs_config = require("gitsigns.config").config
393+
gs_config.linehl = false
394+
gs_config.show_deleted = false
395+
gs_config.word_diff = false
396+
gs_refresh(state.inline_diff.update)
397+
end
398+
362399
File.attached[self.bufnr] = nil
363400
end
364401
end

0 commit comments

Comments
 (0)