Skip to content

Commit 7e7aded

Browse files
committed
feat: split profile into multiple files
1 parent 99fc01d commit 7e7aded

File tree

12 files changed

+1149
-1058
lines changed

12 files changed

+1149
-1058
lines changed

lua/codeme/profile.lua

Lines changed: 0 additions & 1058 deletions
This file was deleted.

lua/codeme/profile/formatters.lua

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
local M = {}
2+
3+
function M.fmt_time(s)
4+
if not s or s == 0 then
5+
return "0m"
6+
end
7+
if s < 60 then
8+
return s .. "s"
9+
end
10+
if s < 3600 then
11+
return math.floor(s / 60) .. "m"
12+
end
13+
local h, m = math.floor(s / 3600), math.floor((s % 3600) / 60)
14+
return m > 0 and (h .. "h " .. m .. "m") or (h .. "h")
15+
end
16+
17+
function M.fmt_num(n)
18+
if not n then
19+
return "0"
20+
end
21+
return tostring(n):reverse():gsub("(%d%d%d)", "%1,"):reverse():gsub("^,", "")
22+
end
23+
24+
function M.progress(pct, w)
25+
pct = math.max(0, math.min(100, pct or 0))
26+
local f = math.floor(pct / 100 * w)
27+
return string.rep("", f) .. string.rep("", w - f)
28+
end
29+
30+
function M.trend(cur, prev)
31+
if not cur or not prev or prev == 0 then
32+
return "", "commentfg"
33+
end
34+
local d = cur - prev
35+
local p = math.floor(math.abs(d) / prev * 100)
36+
if d > 0 then
37+
return "" .. p .. "%", "exgreen"
38+
end
39+
if d < 0 then
40+
return "" .. p .. "%", "exred"
41+
end
42+
return "", "commentfg"
43+
end
44+
45+
function M.get_streak_display(streak)
46+
if streak == 0 then
47+
return "", "commentfg"
48+
elseif streak < 3 then
49+
return string.rep("🔥", streak), "exred"
50+
elseif streak < 7 then
51+
return string.rep("🔥", 3) .. " +" .. (streak - 3), "exred"
52+
elseif streak < 30 then
53+
return "🔥🔥🔥 ⚡ +" .. (streak - 3), "exred"
54+
elseif streak < 100 then
55+
return "🔥🔥🔥 ⚡⚡ +" .. (streak - 3), "exred"
56+
else
57+
return "🔥🔥🔥 ⚡⚡⚡ +" .. (streak - 3), "exred"
58+
end
59+
end
60+
61+
return M

lua/codeme/profile/helpers.lua

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
local M = {}
2+
3+
-- Helper: Calculate hourly time distribution from sessions
4+
function M.calculate_hourly_time(sessions)
5+
local hourly_time = {}
6+
for i = 0, 23 do
7+
hourly_time[i] = 0
8+
end
9+
10+
if not sessions or #sessions == 0 then
11+
return hourly_time
12+
end
13+
14+
for _, session in ipairs(sessions) do
15+
local start_str = session.start or ""
16+
local end_str = session["end"] or ""
17+
local duration = session.duration or 0
18+
19+
if duration <= 0 then
20+
goto continue
21+
end
22+
23+
local start_hour = tonumber(start_str:match("T(%d%d):"))
24+
local end_hour = tonumber(end_str:match("T(%d%d):"))
25+
26+
if not start_hour or not end_hour then
27+
goto continue
28+
end
29+
30+
-- Same hour
31+
if start_hour == end_hour then
32+
hourly_time[start_hour] = hourly_time[start_hour] + duration
33+
else
34+
local start_min = tonumber(start_str:match("T%d%d:(%d%d):")) or 0
35+
local end_min = tonumber(end_str:match("T%d%d:(%d%d):")) or 0
36+
37+
-- First hour
38+
local first_hour = (60 - start_min) * 60
39+
hourly_time[start_hour] = hourly_time[start_hour] + math.min(first_hour, duration)
40+
41+
local remaining = duration - first_hour
42+
if remaining > 0 then
43+
-- Last hour
44+
local last_hour = end_min * 60
45+
hourly_time[end_hour] = hourly_time[end_hour] + math.min(last_hour, remaining)
46+
47+
remaining = remaining - last_hour
48+
49+
-- Full hours in between
50+
local h = (start_hour + 1) % 24
51+
while remaining > 0 and h ~= end_hour do
52+
local chunk = math.min(3600, remaining)
53+
hourly_time[h] = hourly_time[h] + chunk
54+
remaining = remaining - chunk
55+
h = (h + 1) % 24
56+
end
57+
end
58+
end
59+
60+
::continue::
61+
end
62+
63+
return hourly_time
64+
end
65+
66+
-- Helper: Pad string to right with spaces
67+
function M.pad_right(str, width)
68+
return str .. string.rep(" ", width - #str)
69+
end
70+
71+
return M

lua/codeme/profile/init.lua

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
local M = {}
2+
local state = require("codeme.profile.state")
3+
local renderer = require("codeme.profile.renderer")
4+
local api = vim.api
5+
6+
function M.open(stats)
7+
state.set_stats(stats)
8+
state.tab = 1
9+
state.width = math.min(110, math.floor(vim.o.columns * 0.85))
10+
state.ns = api.nvim_create_namespace("codeme")
11+
12+
-- Calculate height by rendering all tabs once
13+
local tab_modules = {
14+
require("codeme.profile.tabs.today"),
15+
require("codeme.profile.tabs.weekly"),
16+
require("codeme.profile.tabs.overview"),
17+
require("codeme.profile.tabs.insights"),
18+
require("codeme.profile.tabs.languages"),
19+
require("codeme.profile.tabs.projects"),
20+
}
21+
22+
local max_h = 0
23+
for i = 1, #state.TABS do
24+
state.tab = i
25+
local tab_lines = tab_modules[i].render()
26+
max_h = math.max(max_h, #tab_lines)
27+
end
28+
state.tab = 1
29+
local h = math.min(math.max(max_h + 6, 20), math.floor(vim.o.lines * 0.8))
30+
31+
-- Create buffer
32+
state.buf = api.nvim_create_buf(false, true)
33+
vim.bo[state.buf].buftype = "nofile"
34+
vim.bo[state.buf].bufhidden = "wipe"
35+
36+
-- Create window
37+
state.win = api.nvim_open_win(state.buf, true, {
38+
relative = "editor",
39+
width = state.width,
40+
height = h,
41+
row = math.floor((vim.o.lines - h) / 2),
42+
col = math.floor((vim.o.columns - state.width) / 2),
43+
border = "rounded",
44+
style = "minimal",
45+
})
46+
47+
-- Keymaps
48+
local o = { buffer = state.buf, silent = true, nowait = true }
49+
vim.keymap.set("n", "<Tab>", renderer.next_tab, o)
50+
vim.keymap.set("n", "L", renderer.next_tab, o)
51+
vim.keymap.set("n", "<S-Tab>", renderer.prev_tab, o)
52+
vim.keymap.set("n", "H", renderer.prev_tab, o)
53+
for i = 1, 6 do
54+
vim.keymap.set("n", tostring(i), function()
55+
renderer.goto_tab(i)
56+
end, o)
57+
end
58+
59+
local close = function()
60+
if state.win and api.nvim_win_is_valid(state.win) then
61+
api.nvim_win_close(state.win, true)
62+
end
63+
state.buf, state.win = nil, nil
64+
end
65+
vim.keymap.set("n", "q", close, o)
66+
vim.keymap.set("n", "<Esc>", close, o)
67+
68+
-- Auto-close when leaving the buffer
69+
vim.api.nvim_create_autocmd("BufLeave", {
70+
buffer = state.buf,
71+
once = true,
72+
callback = close,
73+
})
74+
75+
renderer.render()
76+
end
77+
78+
return M

lua/codeme/profile/renderer.lua

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
local state = require("codeme.profile.state")
2+
local ui = require("codeme.ui")
3+
local api = vim.api
4+
5+
local M = {}
6+
7+
-- Lazy load tab modules
8+
local function get_tab_modules()
9+
return {
10+
require("codeme.profile.tabs.today"),
11+
require("codeme.profile.tabs.weekly"),
12+
require("codeme.profile.tabs.overview"),
13+
require("codeme.profile.tabs.insights"),
14+
require("codeme.profile.tabs.languages"),
15+
require("codeme.profile.tabs.projects"),
16+
}
17+
end
18+
19+
function M.render()
20+
if not state.buf or not api.nvim_buf_is_valid(state.buf) then
21+
return
22+
end
23+
24+
local lines = {}
25+
26+
-- Tabs header
27+
for _, l in ipairs(ui.tabs(state.TABS, state.tab)) do
28+
table.insert(lines, l)
29+
end
30+
table.insert(lines, {})
31+
32+
-- Tab content
33+
local tab_modules = get_tab_modules()
34+
for _, l in ipairs(tab_modules[state.tab].render()) do
35+
table.insert(lines, l)
36+
end
37+
38+
-- Footer
39+
table.insert(lines, {})
40+
table.insert(lines, { { " <Tab>: Next │ <S-Tab>: Prev │ 1-6: Jump │ q: Close", "commentfg" } })
41+
42+
-- Render
43+
ui.render(state.buf, lines, state.ns, state.width)
44+
end
45+
46+
function M.next_tab()
47+
state.tab = state.tab % #state.TABS + 1
48+
M.render()
49+
end
50+
51+
function M.prev_tab()
52+
state.tab = state.tab == 1 and #state.TABS or state.tab - 1
53+
M.render()
54+
end
55+
56+
function M.goto_tab(n)
57+
if n >= 1 and n <= #state.TABS then
58+
state.tab = n
59+
M.render()
60+
end
61+
end
62+
63+
return M

lua/codeme/profile/state.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
local M = {}
2+
3+
-- Module state
4+
M.stats = {}
5+
M.tab = 1
6+
M.buf = nil
7+
M.win = nil
8+
M.ns = nil
9+
M.width = 100
10+
11+
-- Tab definitions
12+
M.TABS = { "☀️ Today", "📅 Weekly", "📊 Overview", "💡 Insights", "💻 Languages", "🔥 Projects" }
13+
14+
function M.reset()
15+
M.stats = {}
16+
M.tab = 1
17+
M.buf = nil
18+
M.win = nil
19+
M.ns = nil
20+
M.width = 100
21+
end
22+
23+
function M.get_stats()
24+
return M.stats
25+
end
26+
27+
function M.set_stats(stats)
28+
M.stats = stats or {}
29+
end
30+
31+
return M

0 commit comments

Comments
 (0)