wakatime / vim-wakatime

Vim plugin for automatic time tracking and metrics generated from your programming activity.
https://wakatime.com/vim
BSD 3-Clause "New" or "Revised" License
1.01k stars 69 forks source link

Show code stats in status bar #110

Open luizcorreia opened 2 years ago

luizcorreia commented 2 years ago

Hi, How I can put the value from :WakaTimeToday on my status line?

alanhamlett commented 2 years ago

This is for powerline or airline?

luizcorreia commented 2 years ago

This is for powerline or airline?

Hi, I use lualine, I think the config for vim-airline could work.

m4thewz commented 2 years ago

I did a function (in lua) to get this, but the delay is too long

local wakatime_cli = os.getenv("HOME") .. '/.wakatime/wakatime-cli-linux-amd64' -- Replace with your os name and architecture

local handle = io.popen(wakatime_cli .. ' --today')
local output = handle:read("*a")
handle:close()

print(output)
devkvlt commented 2 years ago

@m4thewz that's painfully blocking, this needs to be done asynchronously.

smezzy commented 1 year ago

I managed to do it with this code: you need wakatime cli for it to work

local uv = require("luv")

local current_time = ""
local function set_interval(interval, callback)
    local timer = uv.new_timer()
    local function ontimeout()
        callback(timer)
    end
    uv.timer_start(timer, interval, interval, ontimeout)
    return timer
end

local function update_wakatime()
    local stdin = uv.new_pipe()
    local stdout = uv.new_pipe()
    local stderr = uv.new_pipe()

    local handle, pid =
        uv.spawn(
        "wakatime",
        {
            args = {"--today"},
            stdio = {stdin, stdout, stderr}
        },
        function(code, signal) -- on exit
            stdin:close()
            stdout:close()
            stderr:close()
        end
    )

    uv.read_start(
        stdout,
        function(err, data)
            assert(not err, err)
            if data then
                current_time = "🅆 " .. data:sub(1, #data - 2) .. " "
            end
        end
    )
end

set_interval(5000, update_wakatime)

local function get_wakatime()
    return current_time
end

put it somewhere then you can use it in your status bar like:

require("lualine").setup {
...
        lualine_y = {"filetype", "progress", get_wakatime},
...} 
ditsuke commented 1 year ago

Here's my version* based on @smezzy's (note that mine requires https://github.com/nvim-lua/plenary.nvim)

local Job = require("plenary.job")
local async = require("plenary.async")

local get_wakatime_time = function()
  local tx, rx = async.control.channel.oneshot()
  local ok, job = pcall(Job.new, Job, {
    command = os.getenv("HOME") .. "/.wakatime/wakatime-cli",
    args = { "--today" },
    on_exit = function(j, _) tx(j:result()[1] or "") end,
  })
  if not ok then
    vim.notify("Bad WakaTime call: " .. job, "warn")
    return ""
  end

  job:start()
  return rx()
end

---@diagnostic disable
local state = { comp_wakatime_time = "" }

-- Yield statusline value
local wakatime = function()
  local WAKATIME_UPDATE_INTERVAL = 10000

  if not Wakatime_routine_init then
    local timer = uv.new_timer()
    if timer == nil then return "" end
    -- Update wakatime every 10s
    uv.timer_start(timer, 500, WAKATIME_UPDATE_INTERVAL, function()
      async.run(get_wakatime_time, function(time) state.comp_wakatime_time = time end)
    end)
    Wakatime_routine_init = true
  end

  return state.comp_wakatime_time
end

And the lualine component:

{
  components.wakatime,
  cond = function() return vim.g["loaded_wakatime"] == 1 end,
  icon = "󱑆",
  color = { bg = COLORS.bg, fg = COLORS.cyan },
}

image

alanhamlett commented 1 year ago

Instead of calling wakatime-cli --today directly you can also run the command :WakaTimeToday.

ditsuke commented 1 year ago

Instead of calling wakatime-cli --today directly you can also run the command :WakaTimeToday.

I believe :WakaTimeToday echoes values instead of returning them so it wouldn't be possible to use the plugin unless it exposes a vimscript / lua function for the job.

alanhamlett commented 1 year ago

Yes, there's also g:WakaTimeToday(callback).

tmillr commented 1 year ago

Instead of calling wakatime-cli --today directly you can also run the command :WakaTimeToday.

I believe :WakaTimeToday echoes values instead of returning them so it wouldn't be possible to use the plugin unless it exposes a vimscript / lua function for the job.

FWIW, unless a vim command is writing directly to vim's stdout (and it almost never should be as this will ruin the TUI/display), you can usually capture a command's output with vim's execute() function (see :help execute() in vim for details) or the :redir command (see :help :redir in vim for details). If you are using Neovim, there are a few Neovim-api (Lua) functions that can accomplish this as well: vim.api.nvim_cmd() (see :help nvim_cmd() in vim for details). For example:

-- This should be silent and should capture the cmd's output into the `output` variable.
-- `output` is a string.
local output = vim.api.nvim_cmd({ cmd = "WakaTimeToday" }, { output = true })

There's also :help nvim_command() and :help nvim_exec2(), however nvim_cmd() is probably the best (i.e. slightly more performant in theory) as it avoids the need for command parsing.