Skip to content

Add log margin popup #1715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
10 changes: 10 additions & 0 deletions lua/neogit/buffers/status/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ M.v_log_popup = function(_self)
return popups.open("log")
end

---@param _self StatusBuffer
M.v_margin_popup = function(_self)
return popups.open("margin")
end

---@param _self StatusBuffer
M.v_worktree_popup = function(_self)
return popups.open("worktree")
Expand Down Expand Up @@ -1408,6 +1413,11 @@ M.n_log_popup = function(_self)
return popups.open("log")
end

---@param _self StatusBuffer
M.n_margin_popup = function(_self)
return popups.open("margin")
end

---@param _self StatusBuffer
M.n_worktree_popup = function(_self)
return popups.open("worktree")
Expand Down
2 changes: 2 additions & 0 deletions lua/neogit/buffers/status/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ function M:open(kind)
[popups.mapping_for("HelpPopup")] = self:_action("v_help_popup"),
[popups.mapping_for("IgnorePopup")] = self:_action("v_ignore_popup"),
[popups.mapping_for("LogPopup")] = self:_action("v_log_popup"),
[popups.mapping_for("MarginPopup")] = self:_action("v_margin_popup"),
[popups.mapping_for("MergePopup")] = self:_action("v_merge_popup"),
[popups.mapping_for("PullPopup")] = self:_action("v_pull_popup"),
[popups.mapping_for("PushPopup")] = self:_action("v_push_popup"),
Expand Down Expand Up @@ -182,6 +183,7 @@ function M:open(kind)
[popups.mapping_for("HelpPopup")] = self:_action("n_help_popup"),
[popups.mapping_for("IgnorePopup")] = self:_action("n_ignore_popup"),
[popups.mapping_for("LogPopup")] = self:_action("n_log_popup"),
[popups.mapping_for("MarginPopup")] = self:_action("n_margin_popup"),
[popups.mapping_for("MergePopup")] = self:_action("n_merge_popup"),
[popups.mapping_for("PullPopup")] = self:_action("n_pull_popup"),
[popups.mapping_for("PushPopup")] = self:_action("n_push_popup"),
Expand Down
81 changes: 80 additions & 1 deletion lua/neogit/buffers/status/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local Ui = require("neogit.lib.ui")
local Component = require("neogit.lib.ui.component")
local util = require("neogit.lib.util")
local common = require("neogit.buffers.common")
local config = require("neogit.config")
local a = require("plenary.async")

local col = Ui.col
Expand Down Expand Up @@ -359,6 +360,79 @@ local SectionItemCommit = Component.new(function(item)
end
end

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

-- Render author and date in margin
local state = require("neogit.lib.state")
local visibility = state.get({ "margin", "visibility" }, false)
local margin_date_style = state.get({ "margin", "date_style" }, 1)
local details = state.get({ "margin", "details" }, false)
local date
local author_table = { "" }
local date_table
local date_width = 10
local clamp_width = 30 -- to avoid having too much space when relative date is short

if margin_date_style == 1 then -- relative date (short)
local unpacked = vim.split(item.commit.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
-- 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 = item.commit.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_table = { util.str_min_width(date, date_width), "Special" }

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

local virt
if visibility then
virt = {
{ " ", "Constant" },
author_table,
date_table,
}
else
virt = {}
end

return row(
util.merge(
{ text.highlight("NeogitObjectId")(item.commit.abbreviated_commit) },
Expand All @@ -367,7 +441,12 @@ local SectionItemCommit = Component.new(function(item)
ref_last,
{ text(item.commit.subject) }
),
{ oid = item.commit.oid, yankable = item.commit.oid, item = item }
{
virtual_text = virt,
oid = item.commit.oid,
yankable = item.commit.oid,
item = item,
}
)
end)

Expand Down
2 changes: 2 additions & 0 deletions lua/neogit/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ end
---| "PushPopup"
---| "CommitPopup"
---| "LogPopup"
---| "MarginPopup"
---| "RevertPopup"
---| "StashPopup"
---| "IgnorePopup"
Expand Down Expand Up @@ -626,6 +627,7 @@ function M.get_default_values()
["c"] = "CommitPopup",
["f"] = "FetchPopup",
["l"] = "LogPopup",
["L"] = "MarginPopup",
["m"] = "MergePopup",
["p"] = "PullPopup",
["r"] = "RebasePopup",
Expand Down
2 changes: 2 additions & 0 deletions lua/neogit/lib/git/log.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local commit_header_pat = "([| ]*)(%*?)([| ]*)commit (%w+)"
---@field verification_flag string?
---@field rel_date string
---@field log_date string
---@field unix_date string

---Parses the provided list of lines into a CommitLogEntry
---@param raw string[]
Expand Down Expand Up @@ -340,6 +341,7 @@ local function format(show_signature)
committer_date = "%cD",
rel_date = "%cr",
log_date = "%cd",
unix_date = "%ct",
}

if show_signature then
Expand Down
3 changes: 3 additions & 0 deletions lua/neogit/popups/help/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ M.popups = function(env)
{ "LogPopup", "Log", popups.open("log", function(p)
p(env.log)
end) },
{ "MarginPopup", "Margin", popups.open("margin", function(p)
p(env.margin)
end) },
{
"CherryPickPopup",
"Cherry Pick",
Expand Down
25 changes: 25 additions & 0 deletions lua/neogit/popups/margin/actions.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
local M = {}

local state = require("neogit.lib.state")

function M.toggle_visibility()
local visibility = state.get({ "margin", "visibility" }, false)
local new_visibility = not visibility
state.set({ "margin", "visibility" }, new_visibility)
end

function M.cycle_date_style()
local styles = { "relative_short", "relative_long", "local_datetime" }
local current_index = state.get({ "margin", "date_style" }, #styles)
local next_index = (current_index % #styles) + 1 -- wrap around to the first style

state.set({ "margin", "date_style" }, next_index)
end

function M.toggle_details()
local details = state.get({ "margin", "details" }, false)
local new_details = not details
state.set({ "margin", "details" }, new_details)
end

return M
49 changes: 49 additions & 0 deletions lua/neogit/popups/margin/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
local popup = require("neogit.lib.popup")
local config = require("neogit.config")
local actions = require("neogit.popups.margin.actions")

local M = {}

function M.create()
local p = popup
.builder()
:name("NeogitMarginPopup")
:option("n", "max-count", "256", "Limit number of commits", { default = "256", key_prefix = "-" })
:switch("o", "topo", "Order commits by", {
cli_suffix = "-order",
options = {
{ display = "", value = "" },
{ display = "topo", value = "topo" },
{ display = "author-date", value = "author-date" },
{ display = "date", value = "date" },
},
})
:switch("g", "graph", "Show graph", {
enabled = true,
internal = true,
incompatible = { "reverse" },
dependent = { "color" },
})
:switch_if(
config.values.graph_style == "ascii" or config.values.graph_style == "kitty",
"c",
"color",
"Show graph in color",
{ internal = true, incompatible = { "reverse" } }
)
:switch("d", "decorate", "Show refnames", { enabled = true, internal = true })
:group_heading("Refresh")
:action("g", "buffer", actions.log_current)
:new_action_group("Margin")
:action("L", "toggle visibility", actions.toggle_visibility)
:action("l", "cycle style", actions.cycle_date_style)
:action("d", "toggle details", actions.toggle_details)
:action("x", "toggle shortstat", actions.log_current)
:build()

p:show()

return p
end

return M
14 changes: 7 additions & 7 deletions spec/popups/help_popup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
" Commands Applying changes Essential commands ",
" $ History M Remote <c-s> Stage all <c-r> Refresh ",
" A Cherry Pick m Merge K Untrack <cr> Go to file ",
" b Branch P Push s Stage <tab> Toggle ",
" B Bisect p Pull S Stage unstaged ",
" b Branch p Pull s Stage <tab> Toggle ",
" B Bisect P Push S Stage unstaged ",
" c Commit Q Command u Unstage ",
" d Diff r Rebase U Unstage all ",
" f Fetch t Tag x Discard ",
" I Init v Revert ",
" i Ignore w Worktree ",
" l Log X Reset ",
" Z Stash "
" i Ignore v Revert ",
" I Init w Worktree ",
" L Margin X Reset ",
" l Log Z Stash "
]
end

%w[$ A b B c d f i I l M m P p r t v w X Z].each { include_examples "interaction", _1 }
%w[$ A b B c d f i I l L M m P p r t v w X Z].each { include_examples "interaction", _1 }
end
26 changes: 26 additions & 0 deletions spec/popups/margin_popup_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe "Margin Popup", :git, :nvim, :popup do # rubocop:disable RSpec/EmptyExampleGroup
before { nvim.keys("L") }

let(:view) do
[
" Arguments ",
" -n Limit number of commits (--max-count=256) ",
" -o Order commits by (--[topo|author-date|date]-order) ",
" -g Show graph (--graph) ",
" -c Show graph in color (--color) ",
" -d Show refnames (--decorate) ",
" ",
" Refresh Margin ",
" g buffer L toggle visibility ",
" l cycle style ",
" d toggle details ",
" x toggle shortstat "
]
end

%w[L l d].each { include_examples "interaction", _1 }
end
Loading