|
@@ -8,6 +8,14 @@ if not unpack then unpack = table.unpack end
|
|
|
|
|
|
|
|
local setup = function()
|
|
local setup = function()
|
|
|
local maps = require("status-beast.maps")
|
|
local maps = require("status-beast.maps")
|
|
|
|
|
+
|
|
|
|
|
+ local claude_usage_cache = {
|
|
|
|
|
+ data = nil,
|
|
|
|
|
+ last_update = 0,
|
|
|
|
|
+ update_interval = 45,
|
|
|
|
|
+ updating = false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
-- Gutter options
|
|
-- Gutter options
|
|
|
vim.opt.number = true
|
|
vim.opt.number = true
|
|
|
vim.opt.relativenumber = true
|
|
vim.opt.relativenumber = true
|
|
@@ -74,6 +82,85 @@ local setup = function()
|
|
|
return maps.mode_map[mode_code] == nil and "Other" or
|
|
return maps.mode_map[mode_code] == nil and "Other" or
|
|
|
maps.mode_map[mode_code]
|
|
maps.mode_map[mode_code]
|
|
|
end
|
|
end
|
|
|
|
|
+
|
|
|
|
|
+ local update_claude_usage_async = function()
|
|
|
|
|
+ if claude_usage_cache.updating then return end
|
|
|
|
|
+
|
|
|
|
|
+ local claude_dir = vim.fn.getcwd() .. "/.claude"
|
|
|
|
|
+ if vim.fn.isdirectory(claude_dir) == 0 or vim.fn.executable("ccusage") == 0 then
|
|
|
|
|
+ claude_usage_cache.data = nil
|
|
|
|
|
+ claude_usage_cache.last_update = os.time()
|
|
|
|
|
+ return
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ local ok, Job = pcall(require, "plenary.job")
|
|
|
|
|
+ if not ok then return end
|
|
|
|
|
+
|
|
|
|
|
+ claude_usage_cache.updating = true
|
|
|
|
|
+
|
|
|
|
|
+ local usage = {}
|
|
|
|
|
+ local completed = 0
|
|
|
|
|
+
|
|
|
|
|
+ local on_complete = function()
|
|
|
|
|
+ completed = completed + 1
|
|
|
|
|
+ if completed == 3 then
|
|
|
|
|
+ claude_usage_cache.data = usage
|
|
|
|
|
+ claude_usage_cache.last_update = os.time()
|
|
|
|
|
+ claude_usage_cache.updating = false
|
|
|
|
|
+ vim.schedule(function() vim.cmd("redrawtabline") end)
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ local parse_and_store = function(j, return_val, key, data_key, index_key)
|
|
|
|
|
+ if return_val == 0 then
|
|
|
|
|
+ local ok_parse, data = pcall(vim.json.decode,
|
|
|
|
|
+ table.concat(j:result(), "\n"))
|
|
|
|
|
+ if ok_parse and data[data_key] and #data[data_key] > 0 then
|
|
|
|
|
+ if index_key then
|
|
|
|
|
+ usage[key] = data[data_key][#data[data_key]][index_key]
|
|
|
|
|
+ else
|
|
|
|
|
+ local total = 0
|
|
|
|
|
+ for _, item in ipairs(data[data_key]) do
|
|
|
|
|
+ total = total + item.totalCost
|
|
|
|
|
+ end
|
|
|
|
|
+ usage[key] = total / #data[data_key]
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ on_complete()
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ Job:new({
|
|
|
|
|
+ command = "ccusage",
|
|
|
|
|
+ args = { "monthly", "--json" },
|
|
|
|
|
+ on_exit = vim.schedule_wrap(function(j, ret)
|
|
|
|
|
+ parse_and_store(j, ret, "month", "monthly", "totalCost")
|
|
|
|
|
+ end),
|
|
|
|
|
+ }):start()
|
|
|
|
|
+
|
|
|
|
|
+ Job:new({
|
|
|
|
|
+ command = "ccusage",
|
|
|
|
|
+ args = { "weekly", "--json" },
|
|
|
|
|
+ on_exit = vim.schedule_wrap(function(j, ret)
|
|
|
|
|
+ parse_and_store(j, ret, "week", "weekly", "totalCost")
|
|
|
|
|
+ end),
|
|
|
|
|
+ }):start()
|
|
|
|
|
+
|
|
|
|
|
+ Job:new({
|
|
|
|
|
+ command = "ccusage",
|
|
|
|
|
+ args = { "daily", "--json", "--since", os.date("%Y%m%d", os.time() - 30 * 24 * 60 * 60) },
|
|
|
|
|
+ on_exit = vim.schedule_wrap(function(j, ret)
|
|
|
|
|
+ parse_and_store(j, ret, "avg_day", "daily", nil)
|
|
|
|
|
+ end),
|
|
|
|
|
+ }):start()
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ local get_claude_usage = function()
|
|
|
|
|
+ if os.time() - claude_usage_cache.last_update >= claude_usage_cache.update_interval then
|
|
|
|
|
+ update_claude_usage_async()
|
|
|
|
|
+ end
|
|
|
|
|
+ return claude_usage_cache.data
|
|
|
|
|
+ end
|
|
|
_G.StatusBeast = {
|
|
_G.StatusBeast = {
|
|
|
column = function()
|
|
column = function()
|
|
|
local gitsign = get_gitsigns()
|
|
local gitsign = get_gitsigns()
|
|
@@ -169,6 +256,25 @@ local setup = function()
|
|
|
v["name"])
|
|
v["name"])
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
|
|
|
|
+ -- Claude usage
|
|
|
|
|
+ local usage = get_claude_usage()
|
|
|
|
|
+ if usage then
|
|
|
|
|
+ local parts = {}
|
|
|
|
|
+ if usage.month then
|
|
|
|
|
+ table.insert(parts, string.format("M%.0f", usage.month))
|
|
|
|
|
+ end
|
|
|
|
|
+ if usage.week then
|
|
|
|
|
+ table.insert(parts, string.format("W%.0f", usage.week))
|
|
|
|
|
+ end
|
|
|
|
|
+ if usage.avg_day then
|
|
|
|
|
+ table.insert(parts, string.format("D̄%.0f", usage.avg_day))
|
|
|
|
|
+ end
|
|
|
|
|
+ if #parts > 0 then
|
|
|
|
|
+ table.insert(s,
|
|
|
|
|
+ "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
|
|
|
|
|
+ table.concat(parts, " "))
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
-- Git
|
|
-- Git
|
|
|
local status_dict = vim.b.gitsigns_status_dict;
|
|
local status_dict = vim.b.gitsigns_status_dict;
|
|
|
if (status_dict ~= nil) then
|
|
if (status_dict ~= nil) then
|