Eric's Blog 时光荏苒,岁月如梭

Neovim 日历插件 calendar.nvim

2026-01-04
Eric Wong

早在写 zettelkasten.nvim 插件的时候,我就想做一个日历试图,用来查看笔记的日期。可能是因为需求不是那么的迫切, 所以一直拖着没有写这样功能。

趁着这次假日,抽空写了这样一个日历插件 calendar.nvim,功能目前还是非常简单的,只是一个简单的日历月视图。 这算是 2026 年我的第一个 Neovim 插件,这篇文字主要介绍 calendar.nvim 插件的安装使用以及制作这一插件遇到的一些问题。

插件安装

calendar.nvim 是使用 Lua 实现的 Neovim 插件,零依赖,可以使用任意插件管理器直接安装,比如:nvim-plug

require('plug').add({
  {
    'wsdjeg/calendar.nvim',
  },
})

基本使用

插件的默认配置如下:

require('calendar').setup({
  mark_icon = '•',
  keymap = {
    next_month = 'L',      -- 下个月
    previous_month = 'H',  -- 上个月
    next_day = 'l',        -- 后一天
    previous_day = 'h',    -- 前一天
    next_week = 'j',       -- 下一周
    previous_week = 'k',   -- 前一周
    today = 't',           -- 跳到今天
  },
  highlights = {
    current = 'Visual',
    today = 'Todo',
    mark = 'Todo',
  },
})

记录一些坑

  1. nvim_buf_set_extmark 函数中 col 等参数指的并不是屏幕 column 列表,而是字符串的字节,

  2. overlay virt_text 的高亮会清除掉当前位置的 extmark hl_group 高亮

最终解决逻辑是给每一个需要标记的位置按照如下逻辑添加 virt_text,其高亮参数传输一个高亮列表.

local hls = { highlights.mark }

if is_totay() then
  table.insert(hls, highlights.today)
end

if is_current() then
  table.insert(hls, highlights.current)
end

vim.api.nvim_buf_set_extmark(buf, ns, col, {
  virt_text = { { mark_icon, hls } },
})

最终效果图

这里展示了一个添加了 zettelkasten 拓展的日历:

local zk_ext = {}

function zk_ext.get(year, month)
  local notes = require('zettelkasten.browser').get_notes()
  local marks = {}
  for _, note in ipairs(notes) do
    local t = vim.split(note.id, '-')
    if tonumber(t[1]) == year and tonumber(t[2]) == month then
      table.insert(
        marks,
        {
          year = tonumber(t[1]),
          month = tonumber(t[2]),
          day = tonumber(t[3]),
        }
      )
    end
  end

  return marks
end

require('calendar.extensions').register(zk_ext)

最终的效果图如下:

calendar-demo


版权声明:本文为原创文章,遵循 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)版权协议,转载请附上原文出处链接和本声明。


延生阅读

分享到:

评论