From fa71704a9471c05d8c9b50a04eff6a9e170313bd Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Fri, 13 Feb 2026 12:22:52 +0100 Subject: [PATCH] feat: add commit age to git blame info --- build.zig | 5 +++++ src/config.zig | 6 ++++++ src/time_fmt.zig | 43 +++++++++++++++++++++++++++++++++++++++++++ src/tui/editor.zig | 16 ++++++++++++---- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/time_fmt.zig diff --git a/build.zig b/build.zig index 7406171..ab94684 100644 --- a/build.zig +++ b/build.zig @@ -353,6 +353,10 @@ pub fn build_exe( .imports = &.{}, }); + const time_fmt_mod = b.createModule(.{ + .root_source_file = b.path("src/time_fmt.zig"), + }); + const config_mod = b.createModule(.{ .root_source_file = b.path("src/config.zig"), .imports = &.{ @@ -668,6 +672,7 @@ pub fn build_exe( .{ .name = "bin_path", .module = bin_path_mod }, .{ .name = "snippet", .module = snippet_mod }, .{ .name = "lsp_types", .module = lsp_types_mod }, + .{ .name = "time_fmt", .module = time_fmt_mod }, }, }); diff --git a/src/config.zig b/src/config.zig index ef08b64..8cc7cd6 100644 --- a/src/config.zig +++ b/src/config.zig @@ -24,6 +24,7 @@ inline_diagnostics: bool = true, inline_diagnostics_alignment: Alignment = .right, inline_vcs_blame: bool = false, inline_vcs_blame_alignment: Alignment = .right, +inline_vcs_blame_age: AgeFormat = .short, animation_min_lag: usize = 0, //milliseconds animation_max_lag: usize = 50, //milliseconds hover_time_ms: usize = 500, //milliseconds @@ -240,3 +241,8 @@ pub const Alignment = enum { left, right, }; + +pub const AgeFormat = enum { + short, + long, +}; diff --git a/src/time_fmt.zig b/src/time_fmt.zig new file mode 100644 index 0000000..d3df3d6 --- /dev/null +++ b/src/time_fmt.zig @@ -0,0 +1,43 @@ +pub fn age_short(timestamp: i64) struct { + timestamp: i64, + pub fn format(self: @This(), writer: anytype) std.Io.Writer.Error!void { + const age = std.time.timestamp() -| self.timestamp; + return if (age < 60) + writer.writeAll("now") + else if (age < 3600) + writer.print("{d}m", .{@divTrunc(age, 60)}) + else if (age < 86400) + writer.print("{d}h", .{@divTrunc(age, 3600)}) + else if (age < 2592000) + writer.print("{d}d", .{@divTrunc(age, 86400)}) + else if (age < 31536000) + writer.print("{d}mo", .{@divTrunc(age, 2592000)}) + else + writer.print("{d}y", .{@divTrunc(age, 31536000)}); + } +} { + return .{ .timestamp = timestamp }; +} + +pub fn age_long(timestamp: i64) struct { + timestamp: i64, + pub fn format(self: @This(), writer: anytype) std.Io.Writer.Error!void { + const age = std.time.timestamp() -| self.timestamp; + return if (age < 60) + writer.writeAll("just now") + else if (age < 3600) + writer.print("{d} minutes ago", .{@divTrunc(age, 60)}) + else if (age < 86400) + writer.print("{d} hours ago", .{@divTrunc(age, 3600)}) + else if (age < 2592000) + writer.print("{d} days ago", .{@divTrunc(age, 86400)}) + else if (age < 31536000) + writer.print("{d} months ago", .{@divTrunc(age, 2592000)}) + else + writer.print("{d} years ago", .{@divTrunc(age, 31536000)}); + } +} { + return .{ .timestamp = timestamp }; +} + +const std = @import("std"); diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 287bcd1..dc6e089 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -1560,18 +1560,26 @@ pub const Editor = struct { .bg = if (hl_row) |_| theme.editor_line_highlight.bg else theme.editor_hint.bg, }); + var age_buf: [32]u8 = undefined; + var age_stream: std.Io.Writer = .fixed(&age_buf); + switch (tui.config().inline_vcs_blame_age) { + .short => age_stream.print(" ({f})", .{@import("time_fmt").age_short(commit.@"author-time")}) catch {}, + .long => age_stream.print(", {f}", .{@import("time_fmt").age_long(commit.@"author-time")}) catch {}, + } + const age = age_stream.buffered(); + const static_text = "  , "; - const summary_freespace = screen_width -| (space_begin + static_text.len + commit.author.len); + const summary_freespace = screen_width -| (space_begin + static_text.len + commit.author.len + age.len); var buf: std.Io.Writer.Allocating = .init(self.allocator); defer buf.deinit(); if (summary_freespace >= commit.summary.len) { - _ = buf.writer.print("  {s}, {s}", .{ commit.summary, commit.author }) catch 0; + _ = buf.writer.print("  {s}, {s}{s}", .{ commit.summary, commit.author, age }) catch 0; } else if (summary_freespace <= 3) { - _ = buf.writer.print("  {s}", .{commit.author}) catch 0; + _ = buf.writer.print("  {s}{s}", .{ commit.author, age }) catch 0; } else { - _ = buf.writer.print("  {s}..., {s}", .{ commit.summary[0..summary_freespace -| 3], commit.author }) catch 0; + _ = buf.writer.print("  {s}..., {s}{s}", .{ commit.summary[0..summary_freespace -| 3], commit.author, age }) catch 0; } const msg = buf.written();