calendar.nvim
July 16, 2026 ยท View on GitHub
A lightweight and extensible pure-Lua monthly calendar plugin for Neovim, featuring Vim-style navigation, customizable day highlights and marks, and a simple extension system for integrating your own workflows.
- โจ Features
- ๐ฆ Installation
- ๐ง Configuration
- ๐งฉ Custom extensions
- ๐ผ๏ธ Screenshots
- ๐ฃ Self-Promotion
- ๐ฌ Feedback
- ๐ Credits
- ๐ License
โจ Features
- Monthly calendar view in Neovim
- Vim-style keyboard navigation
- Today highlighting and custom day highlights
- Marked days support
- Extensible architecture
- Configurable setup and keymaps
- Pure Lua, lightweight, no dependencies
๐ฆ Installation
return {
'wsdjeg/calendar.nvim',
}
๐ง Configuration
require('calendar').setup({
mark_icon = 'โข',
-- locale currently affects UI language only.
locale = 'en-US', -- en-US | de-DE | en-GB | es-ES | fr-FR | it-IT | ja-JP | ko-KR | zh-CN | zh-TW | ru-RU
show_adjacent_days = true,
-- calendar.nvim support vim style keyboard navigation, hjkl.
keymap = {
next_month = 'L',
previous_month = 'H',
next_day = 'l',
previous_day = 'h',
next_week = 'j',
previous_week = 'k',
today = 't',
close = 'q',
},
highlights = {
current = 'Visual',
today = 'Todo',
mark = 'Todo',
adjacent_days = 'Comment',
},
locales = {} -- See `## Locales`
})
locales
locales config is extendable.
(e.g. Add my-LC locale based on en-US)
require('calendar').setup({
locale = 'my-LC',
locales = {
['my-LC'] = {
-- stylua: ignore
months = { 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' },
weekdays = { 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' },
year_month = function(year, month, months)
return string.format('%s %d', months[month], year)
end,
},
},
})
๐งฉ Custom extensions
calendar.nvim supports extensions which can be used to mark specific date.
register extension manually
for example:
here is a simple extension to add zettelkasten.nvim support to calendar.nvim
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('zettelkasten', zk_ext)
automatically extensions
create lua/calendar/extensions/zettelkasten.lua
local extension = {}
function extension.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
extension.actions = {
create_daily_note = function(year, month, day) end,
view_daily_notes = function(year, month, day) end,
}
return extension
๐ผ๏ธ Screenshots
๐ฃ Self-Promotion
Like this plugin? Star the repository on GitHub.
Love this plugin? Follow me on GitHub.
๐ฌ Feedback
If you encounter any bugs or have suggestions, please file an issue in the issue tracker
๐ Credits
๐ License
Licensed under GPL-3.0.