@@ -10,11 +10,12 @@ local state = {
1010---- ----------------------------------------------------------------------------
1111
1212--- @param mode " stage-all-and-commit" | " commit"
13- --- @param statsWidth number
13+ --- @param width number
1414--- @return string[] cleanedOutput
1515--- @return string summary
16+ --- @return number stagedLinesCount
1617--- @nodiscard
17- function M .getDiffStats (mode , statsWidth )
18+ function M .getDiffStats (mode , width )
1819 --- @type fun ( args : string[] ): string[] , string
1920 local function runGitStatsAndCleanUp (args )
2021 local output = vim .split (u .syncShellCmd (args ), " \n " )
@@ -39,34 +40,59 @@ function M.getDiffStats(mode, statsWidth)
3940 return cleanedOutput , summary
4041 end
4142
42- local gitStatsArgs = { " git" , " diff" , " --compact-summary" , " --stat=" .. statsWidth }
43+ local gitStatsArgs = { " git" , " diff" , " --compact-summary" , " --stat=" .. width }
4344
4445 if mode == " stage-all-and-commit" then
4546 u .intentToAddUntrackedFiles () -- include new files in diff stats
46- return runGitStatsAndCleanUp (gitStatsArgs )
47+ local staged , summary = runGitStatsAndCleanUp (gitStatsArgs )
48+ return staged , summary , # staged
4749 end
4850
4951 local notStaged , _ = runGitStatsAndCleanUp (gitStatsArgs )
5052 local staged , summary = runGitStatsAndCleanUp (vim .list_extend (gitStatsArgs , { " --staged" }))
51- if # notStaged > 0 then notStaged = vim . list_extend ({ " " , " not staged: " }, notStaged ) end
52- return vim .list_extend (staged , notStaged ), summary
53+ local stagedLinesCount = # staged -- save, since `list_extend` mutates
54+ return vim .list_extend (staged , notStaged ), summary , stagedLinesCount
5355end
5456
55- function M .diffStatsHighlights ()
56- local hlGroups = require (" tinygit.config" ).config .appearance .hlGroups
57- vim .fn .matchadd (hlGroups .addedText , [[ \zs+\+]] ) -- color the plus/minus like in the terminal
58- vim .fn .matchadd (hlGroups .removedText , [[ -\+\ze\s*$]] )
59-
60- vim .fn .matchadd (" Keyword" , [[ (new.*)]] )
61- vim .fn .matchadd (" Keyword" , [[ (gone.*)]] )
57+ --- @param width number
58+ --- @return string[] logLines
59+ function M .getGitLog (width )
60+ local args = { " git" , " log" , " --max-count=3" , " --format=%s (%cr)" }
61+ local lines = vim .split (u .syncShellCmd (args ), " \n " )
62+ return vim .tbl_map (function (line )
63+ if # line > width then return line :sub (1 , width - 1 ) .. " …" end
64+ return line
65+ end , lines )
66+ end
6267
63- vim .fn .matchadd (" Function" , " .*/" ) -- directory of a file
64- vim .fn .matchadd (" WarningMsg" , " /" ) -- path separator
68+ --- @param bufnr number
69+ --- @param stagedLines number
70+ --- @param diffstatLines number
71+ local function highlightPreviewWin (bufnr , stagedLines , diffstatLines )
72+ -- highlight diffstat for staged lines
73+ local hlGroups = require (" tinygit.config" ).config .appearance .hlGroups
74+ local highlights = {
75+ { hlGroups .addedText , [[ \zs+\+]] }, -- added lines
76+ { hlGroups .removedText , [[ -\+\ze *]] }, -- removed lines
77+ { " Keyword" , [[ (new.*)]] },
78+ { " Keyword" , [[ (gone.*)]] },
79+ { " Function" , " .*/" }, -- directory of a file
80+ { " WarningMsg" , " /" }, -- path separator
81+ { " Comment" , " │" }, -- path separator
82+ }
83+ local endToken = " \\ %<" .. stagedLines + 1 .. " l" -- limit pattern to range, see :help \%<l
84+ for _ , hl in ipairs (highlights ) do
85+ local pattern = hl [2 ] .. endToken
86+ vim .fn .matchadd (hl [1 ], pattern )
87+ end
6588
66- vim .fn .matchadd (" Comment" , " │" ) -- vertical separator
89+ -- highlight diffstat for UNstaged lines
90+ local ns = vim .api .nvim_create_namespace (" tinygit.commitPreview" )
91+ vim .hl .range (bufnr , ns , " Comment" , { stagedLines , 0 }, { diffstatLines , 0 }, { priority = 1000 })
6792
68- -- starting with "not staged", color rest of buffer (`\_.` matches any char, inc. \n)
69- vim .fn .matchadd (" Comment" , [[ ^not staged:\_.*]] )
93+ -- highlight log lines
94+ require (" tinygit.shared.highlights" ).commitType (stagedLines ) -- subject
95+ vim .fn .matchadd (" Comment" , [[ (.*)$]] ) -- date at the end via `git log --format="%s (%cr)"`
7096end
7197
7298---- ----------------------------------------------------------------------------
75101--- @param inputWinid number
76102function M .createWin (mode , inputWinid )
77103 local inputWin = vim .api .nvim_win_get_config (inputWinid )
78- local diffStats , summary = M .getDiffStats (mode , inputWin .width - 2 )
104+ local textWidth = inputWin .width - 2
105+ local diffStatLines , summary , stagedLinesCount = M .getDiffStats (mode , textWidth )
106+ local diffstatLineCount = # diffStatLines -- save, since `list_extend` mutates
107+ table.insert (diffStatLines , " " ) -- line break
108+ local logLines = M .getGitLog (textWidth )
109+ local previewLines = vim .list_extend (diffStatLines , logLines )
79110
80111 -- CREATE WINDOW
81112 local bufnr = vim .api .nvim_create_buf (false , true )
82- vim .api .nvim_buf_set_lines (bufnr , 0 , - 1 , false , diffStats )
113+ vim .api .nvim_buf_set_lines (bufnr , 0 , - 1 , false , previewLines )
83114 local winid = vim .api .nvim_open_win (bufnr , false , {
84115 relative = " win" ,
85116 win = inputWinid ,
@@ -90,19 +121,22 @@ function M.createWin(mode, inputWinid)
90121 border = inputWin .border ,
91122 style = " minimal" ,
92123 focusable = false ,
93- footer = # diffStats > 1 and " " .. summary .. " " or " " ,
124+ footer = # diffStatLines > 1 and " " .. summary .. " " or " " ,
94125 footer_pos = " right" ,
95126 })
96127 state .bufnr = bufnr
97128 state .winid = winid
98- state .diffHeight = # diffStats
129+ state .diffHeight = # previewLines
99130 M .adaptWinPosition (inputWin )
100131
101132 vim .bo [bufnr ].filetype = " tinygit.diffstats"
102133 vim .wo [winid ].statuscolumn = " " -- = left-padding
103134
104135 vim .wo [winid ].winhighlight = " FloatFooter:NonText,FloatBorder:Comment,Normal:Normal"
105- vim .api .nvim_win_call (winid , M .diffStatsHighlights )
136+ vim .api .nvim_win_call (
137+ winid ,
138+ function () highlightPreviewWin (bufnr , stagedLinesCount , diffstatLineCount ) end
139+ )
106140end
107141
108142--- @param inputWin vim.api.keyset.win_config
0 commit comments