@@ -5,13 +5,21 @@ local M = {}
55--- @field group ?boolean Group hunks by file
66--- @field diff ?string | number diff string or buffer number
77
8+ --- @class snacks.picker.diff.hunk.Pos
9+ --- @field line number
10+ --- @field count number
11+
12+ --- @class snacks.picker.Diff
13+ --- @field header string[]
14+ --- @field blocks snacks.picker.diff.Block[]
15+
816--- @class snacks.picker.diff.Hunk
917--- @field diff string[]
1018--- @field line number
1119--- @field context ?string
12- --- @field left { line : number , count : number } old (normal ) /ours (merge )
13- --- @field right { line : number , count : number } new (normal ) /working (merge )
14- --- @field parents ?{ line : number , count : number } [] theirs (merge )
20+ --- @field left snacks.picker.diff.hunk.Pos old (normal ) /ours (merge )
21+ --- @field right snacks.picker.diff.hunk.Pos new (normal ) /working (merge )
22+ --- @field parents ?snacks.picker.diff.hunk.Pos [] theirs (merge )
1523
1624--- @class snacks.picker.diff.Block
1725--- @field unmerged ?boolean
@@ -80,19 +88,19 @@ function M.diff(opts, ctx)
8088 })
8189end
8290
83- local blocks = M .parse (lines )
84- for _ ,block in ipairs (blocks )do
85- local diff = {}--- @type string[]
91+ local diff = M .parse (lines )
92+ for _ ,block in ipairs (diff . blocks )do
93+ local diffs = {}--- @type string[]
8694for _ ,h in ipairs (block .hunks )do
8795if opts .group then
88- vim .list_extend (diff ,h .diff )
96+ vim .list_extend (diffs ,h .diff )
8997else
9098add (block .file ,h .line ,vim .list_extend (vim .deepcopy (block .header ),h .diff ),block )
9199end
92100end
93101if opts .group or # block .hunks == 0 then
94102local line = block .hunks [1 ]and block .hunks [1 ].line or 1
95- add (block .file ,line ,vim .list_extend (vim .deepcopy (block .header ),diff ),block )
103+ add (block .file ,line ,vim .list_extend (vim .deepcopy (block .header ),diffs ),block )
96104end
97105end
98106end
@@ -103,6 +111,7 @@ function M.parse(lines)
103111local hunk --- @type snacks.picker.diff.Hunk ?
104112local block --- @type snacks.picker.diff.Block ?
105113local ret = {}--- @type snacks.picker.diff.Block[]
114+ local header = {}--- @type string[]
106115
107116--- @param file ? string
108117--- @param strip_prefix ? boolean
@@ -209,12 +218,13 @@ function M.parse(lines)
209218block = nil
210219end
211220
212- local with_diff_header = vim . trim ( table.concat ( lines , " \n " )): find ( " ^diff " ) ~= nil
221+ local with_diff_header = false
213222
214223for _ ,text in ipairs (lines )do
215224if not block and text :find (" ^%s*$" )then
216225-- Ignore empty lines before a diff block
217226elseif text :find (" ^diff" )or (not with_diff_header and text :find (" ^%-%-%-" )and (not block or hunk ))then
227+ with_diff_header = with_diff_header or text :find (" ^diff" )== 1
218228emit ()
219229block = {
220230file = " " ,-- file or "unknown",
@@ -235,12 +245,15 @@ function M.parse(lines)
235245hunk .diff [# hunk .diff + 1 ]= text
236246elseif block then
237247block .header [# block .header + 1 ]= text
248+ elseif # ret == 0 then
249+ header [# header + 1 ]= text
238250else
239251Snacks .notify .error (" Unexpected line:" .. text , {title = " Snacks Picker Diff" })
240252end
241253end
242254emit ()
243- return ret
255+ --- @type snacks.picker.Diff
256+ return {blocks = ret ,header = header }
244257end
245258
246259--- @param line string