Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 84 additions & 59 deletions lua/neogit/buffers/status/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -363,75 +363,100 @@ local SectionItemCommit = Component.new(function(item)

local virtual_text

-- Render author and date in margin, if visible
-- Render margin, if visible
if state.get({ "margin", "visibility" }, false) then
local margin_date_style = state.get({ "margin", "date_style" }, 1)
local details = state.get({ "margin", "details" }, false)

local date
local rel_date
local date_width = 10
local clamp_width = 30 -- to avoid having too much space when relative date is short

-- Render date
if item.commit.rel_date:match(" years?,") then
rel_date, _ = item.commit.rel_date:gsub(" years?,", "y")
rel_date = rel_date .. " "
elseif item.commit.rel_date:match("^%d ") then
rel_date = " " .. item.commit.rel_date
else
rel_date = item.commit.rel_date
end
local is_shortstat = state.get({ "margin", "shortstat" }, false)

if is_shortstat then
local cli_shortstat = item.shortstat
local files_changed
local insertions
local deletions

files_changed = cli_shortstat:match("^ (%d+) files?")
files_changed = util.str_min_width(files_changed, 3, nil, { mode = "insert" })
insertions = cli_shortstat:match("(%d+) insertions?")
insertions = util.str_min_width(insertions and insertions .. "+" or " ", 5, nil, { mode = "insert" })
deletions = cli_shortstat:match("(%d+) deletions?")
deletions = util.str_min_width(deletions and deletions .. "-" or " ", 5, nil, { mode = "insert" })

virtual_text = {
{ " ", "Constant" },
{ insertions, "NeogitDiffAdditions" },
{ " ", "Constant" },
{ deletions, "NeogitDiffDeletions" },
{ " ", "Constant" },
{ files_changed, "NeogitSubtleText" },
}
else -- Author & date margin
local margin_date_style = state.get({ "margin", "date_style" }, 1)
local details = state.get({ "margin", "details" }, false)

local date
local rel_date
local date_width = 10
local clamp_width = 30 -- to avoid having too much space when relative date is short

-- Render date
if item.commit.rel_date:match(" years?,") then
rel_date, _ = item.commit.rel_date:gsub(" years?,", "y")
rel_date = rel_date .. " "
elseif item.commit.rel_date:match("^%d ") then
rel_date = " " .. item.commit.rel_date
else
rel_date = item.commit.rel_date
end

if margin_date_style == 1 then -- relative date (short)
local unpacked = vim.split(rel_date, " ")
if margin_date_style == 1 then -- relative date (short)
local unpacked = vim.split(rel_date, " ")

-- above, we added a space if the rel_date started with a single number
-- we get the last two elements to deal with that
local date_number = unpacked[#unpacked - 1]
local date_quantifier = unpacked[#unpacked]
if date_quantifier:match("months?") then
date_quantifier = date_quantifier:gsub("m", "M") -- to distinguish from minutes
end
-- above, we added a space if the rel_date started with a single number
-- we get the last two elements to deal with that
local date_number = unpacked[#unpacked - 1]
local date_quantifier = unpacked[#unpacked]
if date_quantifier:match("months?") then
date_quantifier = date_quantifier:gsub("m", "M") -- to distinguish from minutes
end

-- add back the space if we have a single number
local left_pad
if #unpacked > 2 then
left_pad = " "
else
left_pad = ""
-- add back the space if we have a single number
local left_pad
if #unpacked > 2 then
left_pad = " "
else
left_pad = ""
end

date = left_pad .. date_number .. date_quantifier:sub(1, 1)
date_width = 3
clamp_width = 23
elseif margin_date_style == 2 then -- relative date (long)
date = rel_date
date_width = 10
else -- local iso date
if config.values.log_date_format == nil then
-- we get the unix date to be able to convert the date to the local timezone
date = os.date("%Y-%m-%d %H:%M", item.commit.unix_date)
date_width = 16 -- TODO: what should the width be here?
else
date = item.commit.log_date
date_width = 16
end
end

date = left_pad .. date_number .. date_quantifier:sub(1, 1)
date_width = 3
clamp_width = 23
elseif margin_date_style == 2 then -- relative date (long)
date = rel_date
date_width = 10
else -- local iso date
if config.values.log_date_format == nil then
-- we get the unix date to be able to convert the date to the local timezone
date = os.date("%Y-%m-%d %H:%M", item.commit.unix_date)
date_width = 16 -- TODO: what should the width be here?
else
date = item.commit.log_date
date_width = 16
local author_table = { "" }
if details then
author_table = {
util.str_clamp(item.commit.author_name, clamp_width - (#date > date_width and #date or date_width)),
"NeogitGraphAuthor",
}
end
end

local author_table = { "" }
if details then
author_table = {
util.str_clamp(item.commit.author_name, clamp_width - (#date > date_width and #date or date_width)),
"NeogitGraphAuthor",
virtual_text = {
{ " ", "Constant" },
author_table,
{ util.str_min_width(date, date_width), "Special" },
}
end

virtual_text = {
{ " ", "Constant" },
author_table,
{ util.str_min_width(date, date_width), "Special" },
}
end

return row(
Expand Down
2 changes: 2 additions & 0 deletions lua/neogit/lib/git/cli.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ local runner = require("neogit.runner")

---@class GitCommandShow: GitCommandBuilder
---@field stat self
---@field shortstat self
---@field oneline self
---@field no_patch self
---@field format fun(string): self
Expand Down Expand Up @@ -396,6 +397,7 @@ local configurations = {
show = config {
flags = {
stat = "--stat",
shortstat = "--shortstat",
oneline = "--oneline",
no_patch = "--no-patch",
},
Expand Down
7 changes: 7 additions & 0 deletions lua/neogit/lib/git/log.lua
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,18 @@ function M.present_commit(commit)
return
end

local is_shortstat = state.get({ "margin", "shortstat" }, false)
local shortstat
if is_shortstat then
shortstat = git.cli.show.format("").shortstat.args(commit.oid).call().stdout[1]
end

return {
name = string.format("%s %s", commit.abbreviated_commit, commit.subject or "<empty>"),
decoration = M.branch_info(commit.ref_name, git.remote.list()),
oid = commit.oid,
commit = commit,
shortstat = shortstat,
}
end

Expand Down
18 changes: 14 additions & 4 deletions lua/neogit/lib/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,21 @@ end
-- return res
-- end

function M.str_min_width(str, len, sep)
---@param opts table? If { mode = 'append' }, adds spaces to the end of `str`. If { mode = 'insert' }, adds spaces to the beginning.
function M.str_min_width(str, len, sep, opts)
local mode = (type(opts) == "table" and opts.mode) or "append"
local length = vim.fn.strdisplaywidth(str)
if length > len then
return str
end

return str .. string.rep(sep or " ", len - length)
if mode == "append" then
-- Add spaces to the right of str
return str .. string.rep(sep or " ", len - length)
else
-- Add spaces to the left of str
return string.rep(sep or " ", len - length) .. str
end
end

function M.slice(tbl, s, e)
Expand Down Expand Up @@ -255,8 +263,10 @@ function M.str_truncate(str, max_length, trailing)
return str
end

function M.str_clamp(str, len, sep)
return M.str_min_width(M.str_truncate(str, len - 1, ""), len, sep or " ")
---@param opts table? If { mode = 'append' }, adds spaces to the end of `str`. If { mode = 'insert' }, adds spaces to the beginning.
function M.str_clamp(str, len, sep, opts)
local opts = (type(opts) == "table" and opts.mode) or { mode = "append" }
return M.str_min_width(M.str_truncate(str, len - 1, ""), len, sep or " ", opts)
end

--- Splits a string every n characters, respecting word boundaries
Expand Down
6 changes: 6 additions & 0 deletions lua/neogit/popups/margin/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@ function M.toggle_details()
state.set({ "margin", "details" }, new_details)
end

function M.toggle_shortstat()
local shortstat = state.get({ "margin", "shortstat" }, false)
local new_shortstat = not shortstat
state.set({ "margin", "shortstat" }, new_shortstat)
end

return M
2 changes: 1 addition & 1 deletion lua/neogit/popups/margin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function M.create(env)
:action("L", "toggle visibility", actions.toggle_visibility, { persist_popup = true })
:action("l", "cycle style", actions.cycle_date_style, { persist_popup = true })
:action("d", "toggle details", actions.toggle_details, { persist_popup = true })
:action("x", "toggle shortstat", actions.log_current, { persist_popup = true })
:action("x", "toggle shortstat", actions.toggle_shortstat, { persist_popup = true })
:build()

p:show()
Expand Down
Loading