feat: add Obsidian, WakaTime and Neovide clipboard keys #8

Merged
rootiest merged 1 commits from feat/obsidian-wakatime-neovide into main 2026-10-01 05:48:35 +00:00
5 changed files with 384 additions and 96 deletions
Showing only changes of commit 56eb86885e - Show all commits

No files matched your search

+189
View File
@@ -188,3 +188,192 @@ docs/plans
docs/specs
docs/devlogs
# ────────────────────────────────────────────────────────
# id: gitig-boilerplate-92f3a89d2c63f6a381be8bebd1862de5
# ╭──────────────────────────────────────────────────────────╮
# │ GitIgnore Boilerplate Template │
# ╰──────────────────────────────────────────────────────────╯
#
# ──────────────────── OS-Generated Files ────────────────────
# automatic backup files created by some editors (e.g., Vim, Emacs)
*~
# temporary files created if a process still has a handle to a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# MacOS junk
.DS_Store
Thumbs.db
# Linux trash folder which might appear on any partition or disk
.Trash-*
# files created when an open file is removed but is still being accessed
.nfs*
# ─────────────────── Debug/Temporary/Testing ────────────────
# Matches OLD / .OLD
[Oo][Ll][Dd]/
.[Oo][Ll][Dd]/
# Matches DISABLE / .DISABLE
[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
# Matches DISABLED / .DISABLED
[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
# Matches DEBUG / .DEBUG
[Dd][Ee][Bb][Uu][Gg]/
.[Dd][Ee][Bb][Uu][Gg]/
# Matches TMP / .TMP
[Tt][Mm][Pp]/
.[Tt][Mm][Pp]/
# Matches TEMP / .TEMP
[Tt][Ee][Mm][Pp]/
.[Tt][Ee][Mm][Pp]/
# Matches TEMPORARY / .TEMPORARY
[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
.[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
# Matches TESTING / .TESTING
[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
.[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
# ─────────────────── AI Sessions and Rules ──────────────────
# Matches CLAUDE.md, .claud*, etc.
[Cc][Ll][Aa][Uu][Dd][Ee].[Mm][Dd]
.[Cc][Ll][Aa][Uu][Dd]*
# Matches GEMINI.md, .gemin*, etc.
[Gg][Ee][Mm][Ii][Nn][Ii].[Mm][Dd]
.[Gg][Ee][Mm][Ii][Nn]*
# Matches ANTIGRAVITY.md, .antigrav*, etc.
[Aa][nN][Tt][Ii][Gg][Rr][Aa][Vv][Ii][Tt][Yy].[Mm][Dd]
.[Aa][Nn][Tt][Ii][Gg][Rr][Aa][Vv]*
# Matches AGENTS.md, .remember, etc.
[Aa][Gg][Ee][Nn][Tt][Ss].[Mm][Dd]
.[Rr][Ee][Mm][Ee][Mm][Bb][Ee][Rr]
# ──────────────────── Planning Artifacts ───────────────────
# Catalog files generated by pre-implementation analysis passes
.superpowers
docs/superpowers
docs/specs
# ──────────────────────────────────────────────────────────────
# id: gi-patterns-54143085ec229f3cf907a5aa2a8fcade
# Created by https://www.toptal.com/developers/gitignore/api/linux
# Edit at https://www.toptal.com/developers/gitignore?templates=linux
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# End of https://www.toptal.com/developers/gitignore/api/linux
# id: gitig-boilerplate-e76d1ca7170bfb8385be6293da3f57bc
# ╭──────────────────────────────────────────────────────────╮
# │ GitIgnore Boilerplate Template │
# ╰──────────────────────────────────────────────────────────╯
#
# ──────────────────── OS-Generated Files ────────────────────
# automatic backup files created by some editors (e.g., Vim, Emacs)
*~
# temporary files created if a process still has a handle to a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# MacOS junk
.DS_Store
Thumbs.db
# Linux trash folder which might appear on any partition or disk
.Trash-*
# files created when an open file is removed but is still being accessed
.nfs*
# ─────────────────── Debug/Temporary/Testing ────────────────
# Matches OLD / .OLD
[Oo][Ll][Dd]/
.[Oo][Ll][Dd]/
# Matches DISABLE / .DISABLE
[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee]/
# Matches DISABLED / .DISABLED
[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
.[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd]/
# Matches DEBUG / .DEBUG
[Dd][Ee][Bb][Uu][Gg]/
.[Dd][Ee][Bb][Uu][Gg]/
# Matches TMP / .TMP
[Tt][Mm][Pp]/
.[Tt][Mm][Pp]/
# Matches TEMP / .TEMP
[Tt][Ee][Mm][Pp]/
.[Tt][Ee][Mm][Pp]/
# Matches TEMPORARY / .TEMPORARY
[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
.[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
# Matches TESTING / .TESTING
[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
.[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
# ─────────────────── AI Sessions and Rules ──────────────────
# Matches CLAUDE.md, .claud*, etc.
[Cc][Ll][Aa][Uu][Dd][Ee].[Mm][Dd]
.[Cc][Ll][Aa][Uu][Dd]*
# Matches GEMINI.md, .gemin*, etc.
[Gg][Ee][Mm][Ii][Nn][Ii].[Mm][Dd]
.[Gg][Ee][Mm][Ii][Nn]*
# Matches ANTIGRAVITY.md, .antigrav*, etc.
[Aa][nN][Tt][Ii][Gg][Rr][Aa][Vv][Ii][Tt][Yy].[Mm][Dd]
.[Aa][Nn][Tt][Ii][Gg][Rr][Aa][Vv]*
# Matches AGENTS.md, .agents, .remember, etc.
[Aa][Gg][Ee][Nn][Tt][Ss].[Mm][Dd]
.[Aa][Gg][Ee][Nn][Tt][Ss]
.[Rr][Ee][Mm][Ee][Mm][Bb][Ee][Rr]
# ──────────────────── Planning Artifacts ───────────────────
# Catalog files generated by pre-implementation analysis passes
.superpowers
docs/superpowers
docs/specs
docs/devlogs
# ──────────────────────────────────────────────────────────────
+6
View File
@@ -53,6 +53,7 @@ The configuration is strictly modular:
- **Haunt.nvim**: In-buffer annotation and bookmark manager. Integrates with the Snacks picker for browsing bookmarks and exposes `haunt_all` / `haunt_buffer` prompt contexts to Sidekick AI sessions.
- **Zen Mode**: Distraction-free editing.
- **Qalc**: Inline calculator via `qalculate`.
- **Obsidian.nvim**: Obsidian vault integration for note-taking and knowledge management, with `notebook` (`~/Documents/Notebook`) and `notes` (`~/Documents/Notes`) workspaces.
### LSP & Completion
- **Blink.cmp** + **blink.lib**: High-performance Rust-based completion. Auto-detects binary across install layouts; falls back gracefully if unavailable. Rebuilds automatically on `PackChanged`.
@@ -65,6 +66,10 @@ The configuration is strictly modular:
### Terminal
- **Kitty Scrollback**: Browse Kitty terminal scrollback buffer inside Neovim.
- **Neovide**: When running under the Neovide GUI, adds terminal-style system-clipboard keys: `Ctrl+Shift+V` paste (all modes; in Normal mode an empty line is replaced and the cursor lands after the paste), `Ctrl+Shift+C` copy and `Ctrl+Shift+X` cut (selection in Visual mode, current line in Normal mode).
### Tracking
- **Vim-wakatime**: Coding-time tracking. Loaded eagerly so it sees `VimEnter`/`BufEnter`; server and API key come from `~/.wakatime.cfg`. Reports as `neovim-wakatime` so Wakapi attributes time to Neovim instead of "Unknown".
## 🛠️ System Dependencies
@@ -78,6 +83,7 @@ To ensure all features (pickers, formatters, and LSPs) work correctly, the follo
- `lazygit` (Git TUI)
- `gh` (GitHub CLI integration)
- `xclip` / `xsel` (X11) or `wl-copy` (Wayland) for clipboard sync.
- `wakatime-cli` (Optional, installed automatically for Wakatime tracking)
### Runtime Environments
- `Node.js` & `npm` (Copilot and various LSPs)
+141 -91
View File
@@ -16,14 +16,14 @@ vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- Indentation
vim.opt.tabstop = 2 -- Tab width in spaces
vim.opt.shiftwidth = 2 -- Indent width for >> and auto-indent
vim.opt.tabstop = 2 -- Tab width in spaces
vim.opt.shiftwidth = 2 -- Indent width for >> and auto-indent
vim.opt.expandtab = true -- Use spaces instead of tabs
-- Performance and UI defaults
vim.opt.updatetime = 200 -- Faster completion and CursorHold events
vim.opt.autowrite = true -- Enable auto write
vim.opt.number = true -- Show line numbers
vim.opt.updatetime = 200 -- Faster completion and CursorHold events
vim.opt.autowrite = true -- Enable auto write
vim.opt.number = true -- Show line numbers
vim.opt.relativenumber = true -- Relative line numbers
-- ╭─────────────────────────────────────────────────────────╮
@@ -36,14 +36,14 @@ vim.opt.undofile = true
-- Autowrite/Autosave
-- This ensures changes are saved on every buffer change or when leaving insert mode.
vim.api.nvim_create_autocmd({ "InsertLeave", "TextChanged" }, {
group = vim.api.nvim_create_augroup("autosave", { clear = true }),
pattern = { "*" },
callback = function()
local buftype = vim.api.nvim_get_option_value("buftype", { buf = 0 })
if buftype == "" and vim.bo.modified then
vim.cmd("silent! update")
end
end,
group = vim.api.nvim_create_augroup("autosave", { clear = true }),
pattern = { "*" },
callback = function()
local buftype = vim.api.nvim_get_option_value("buftype", { buf = 0 })
if buftype == "" and vim.bo.modified then
vim.cmd("silent! update")
end
end,
})
-- Automatically reload files changed outside of Neovim
@@ -52,14 +52,14 @@ vim.opt.autoread = true
-- Auto-reload Triggers
-- Reload when focus is gained or when the cursor is idle
vim.api.nvim_create_autocmd({ "FocusGained", "CursorHold" }, {
group = vim.api.nvim_create_augroup("autoread_on_focus", { clear = true }),
pattern = "*",
callback = function()
-- Only if the buffer is not modified, to avoid losing unsaved changes
if vim.bo.modified == false then
vim.cmd("checktime")
end
end,
group = vim.api.nvim_create_augroup("autoread_on_focus", { clear = true }),
pattern = "*",
callback = function()
-- Only if the buffer is not modified, to avoid losing unsaved changes
if vim.bo.modified == false then
vim.cmd("checktime")
end
end,
})
-- Format Function
@@ -67,26 +67,26 @@ vim.api.nvim_create_autocmd({ "FocusGained", "CursorHold" }, {
-- but if a range is provided (e.g., via visual selection),
-- it formats only that range.
vim.api.nvim_create_user_command("Format", function(args)
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format({ async = true, lsp_format = "fallback", range = range })
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format({ async = true, lsp_format = "fallback", range = range })
end, { range = true })
-- FormatOnSave
-- Formats the buffer before saving.
-- This is a common practice to ensure code is consistently formatted.
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*",
callback = function()
-- Call Format function
vim.api.nvim_command("Format")
end,
pattern = "*",
callback = function()
-- Call Format function
vim.api.nvim_command("Format")
end,
})
-- Return to last-known cursor position when reopening files
@@ -109,38 +109,38 @@ vim.api.nvim_create_autocmd("BufReadPost", {
-- This ensures that plugins like Snacks.picker and GrugFar work
-- relative to the file or project you are currently editing.
vim.api.nvim_create_autocmd("BufEnter", {
group = vim.api.nvim_create_augroup("buffer_auto_cd", { clear = true }),
callback = function()
local path = vim.api.nvim_buf_get_name(0)
if path == "" then
return
end
group = vim.api.nvim_create_augroup("buffer_auto_cd", { clear = true }),
callback = function()
local path = vim.api.nvim_buf_get_name(0)
if path == "" then
return
end
-- Skip special buffers, but allow directory buffers (for explorer support)
if vim.bo.buftype ~= "" and vim.bo.filetype ~= "snacks_explorer_tree" then
return
end
-- Skip special buffers, but allow directory buffers (for explorer support)
if vim.bo.buftype ~= "" and vim.bo.filetype ~= "snacks_explorer_tree" then
return
end
-- Get the directory (handle both files and directory paths)
local dir = vim.fn.isdirectory(path) == 1 and path or vim.fn.fnamemodify(path, ":p:h")
-- Get the directory (handle both files and directory paths)
local dir = vim.fn.isdirectory(path) == 1 and path or vim.fn.fnamemodify(path, ":p:h")
-- Find the project root using common markers, fallback to the directory itself
local root = vim.fs.root(dir, { ".git", "lua", "package.json", "go.mod", "Cargo.toml", "Makefile" }) or dir
-- Find the project root using common markers, fallback to the directory itself
local root = vim.fs.root(dir, { ".git", "lua", "package.json", "go.mod", "Cargo.toml", "Makefile" }) or dir
-- Change directory if it's different and valid
if root and vim.fn.isdirectory(root) == 1 and root ~= vim.fn.getcwd() then
vim.fn.chdir(root)
end
end,
-- Change directory if it's different and valid
if root and vim.fn.isdirectory(root) == 1 and root ~= vim.fn.getcwd() then
vim.fn.chdir(root)
end
end,
})
-- Grug-far QoL: Close with 'q'
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("grug_far_q_to_close", { clear = true }),
pattern = "grug-far",
callback = function(args)
vim.keymap.set("n", "q", "<cmd>close<cr>", { buffer = args.buf, silent = true, desc = "Close Grug-far" })
end,
group = vim.api.nvim_create_augroup("grug_far_q_to_close", { clear = true }),
pattern = "grug-far",
callback = function(args)
vim.keymap.set("n", "q", "<cmd>close<cr>", { buffer = args.buf, silent = true, desc = "Close Grug-far" })
end,
})
-- ╭─────────────────────────────────────────────────────────╮
@@ -157,47 +157,97 @@ local title_group = vim.api.nvim_create_augroup("TerminalTitle", { clear = true
-- Helper function to update the terminal title
local function set_terminal_title(title)
-- If in Kitty, we use the direct escape sequence as it's reliable
if is_kitty then
io.stdout:write("\27]2;" .. title .. "\7")
-- Fallback: Use Neovim's built-in title management for other terminals
-- (Standard OSC 2 sequences are supported by most, but opt.title is safer)
elseif os.getenv("TERM") ~= "linux" then
vim.opt.title = true
vim.opt.titlestring = title
end
-- If in Kitty, we use the direct escape sequence as it's reliable
if is_kitty then
io.stdout:write("\27]2;" .. title .. "\7")
-- Fallback: Use Neovim's built-in title management for other terminals
-- (Standard OSC 2 sequences are supported by most, but opt.title is safer)
elseif os.getenv("TERM") ~= "linux" then
vim.opt.title = true
vim.opt.titlestring = title
end
end
-- Terminal title updates on buffer enter and window enter
vim.api.nvim_create_autocmd({ "BufEnter", "BufWinEnter" }, {
group = title_group,
callback = function()
local buftype = vim.bo.buftype
local filetype = vim.bo.filetype
local filename = vim.fn.expand("%:t")
group = title_group,
callback = function()
local buftype = vim.bo.buftype
local filetype = vim.bo.filetype
local filename = vim.fn.expand("%:t")
-- 1. Specifically catch Snacks Terminal or standard Terminals
if filetype == "snacks_terminal" or buftype == "terminal" then
set_terminal_title("NVIM: Terminal")
-- 1. Specifically catch Snacks Terminal or standard Terminals
if filetype == "snacks_terminal" or buftype == "terminal" then
set_terminal_title("NVIM: Terminal")
-- 2. Handle normal files (buftype is empty)
elseif buftype == "" and filename ~= "" then
set_terminal_title("NVIM: " .. filename)
-- 2. Handle normal files (buftype is empty)
elseif buftype == "" and filename ~= "" then
set_terminal_title("NVIM: " .. filename)
-- 3. Handle the empty start screen
elseif filename == "" and buftype == "" then
set_terminal_title("Neovim")
end
end,
-- 3. Handle the empty start screen
elseif filename == "" and buftype == "" then
set_terminal_title("Neovim")
end
end,
})
-- Reset the title back to the shell name when you quit Neovim
vim.api.nvim_create_autocmd("VimLeave", {
group = title_group,
callback = function()
-- On leave, direct stdout is more reliable than setting an option
if is_kitty or os.getenv("TERM") ~= "linux" then
io.stdout:write("\27]2;" .. shell_name .. "\7")
end
end,
group = title_group,
callback = function()
-- On leave, direct stdout is more reliable than setting an option
if is_kitty or os.getenv("TERM") ~= "linux" then
io.stdout:write("\27]2;" .. shell_name .. "\7")
end
end,
})
-- ╭─────────────────────────────────────────────────────────╮
-- │ Neovide Configuration │
-- ╰─────────────────────────────────────────────────────────╯
if vim.g.neovide then
-- ==========================================
-- Paste (Ctrl+Shift+V)
-- ==========================================
-- Normal mode: Smart paste system clipboard (replaces empty line and moves cursor to end)
vim.keymap.set('n', '<C-S-v>', function()
local cur_line = vim.api.nvim_get_current_line()
if cur_line == '' then
local lines = vim.fn.getreg('+', 1, true)
if #lines > 0 then
local r = vim.api.nvim_win_get_cursor(0)[1]
vim.api.nvim_buf_set_lines(0, r - 1, r, false, lines)
-- Calculate position at the end of the newly pasted text
local target_row = r + #lines - 1
local target_col = math.max(0, #lines[#lines] - 1)
vim.api.nvim_win_set_cursor(0, { target_row, target_col })
end
else
-- "]+p puts and positions cursor after the pasted text
vim.cmd('normal! "+]p')
end
end, { desc = 'Paste system clipboard' })
vim.keymap.set('i', '<C-S-v>', '<C-r>+', { desc = 'Paste system clipboard' })
vim.keymap.set('c', '<C-S-v>', '<C-r>+', { desc = 'Paste system clipboard' })
vim.keymap.set('v', '<C-S-v>', '"+p', { desc = 'Paste system clipboard' })
vim.keymap.set('t', '<C-S-v>', [[<C-\><C-n>"+pi]], { desc = 'Paste system clipboard' })
-- ==========================================
-- Copy (Ctrl+Shift+C)
-- ==========================================
-- Visual mode: Yank selected text directly to system clipboard
vim.keymap.set('v', '<C-S-c>', '"+y', { desc = 'Copy to system clipboard' })
-- Normal mode: Yank the current line directly to system clipboard
vim.keymap.set('n', '<C-S-c>', '"+yy', { desc = 'Copy line to system clipboard' })
-- ==========================================
-- Cut (Ctrl+Shift+X)
-- ==========================================
-- Visual mode: Delete selected text and store in system clipboard
vim.keymap.set('v', '<C-S-x>', '"+d', { desc = 'Cut to system clipboard' })
-- Normal mode: Delete the current line and store in system clipboard
vim.keymap.set('n', '<C-S-x>', '"+dd', { desc = 'Cut line to system clipboard' })
end
+39 -5
View File
@@ -124,6 +124,19 @@ Config.plugins.persistence = {
}
require("persistence").setup(Config.plugins.persistence)
-- Vim-wakatime
-- Eagerly loaded: it hooks VimEnter/BufEnter, which a deferred load would miss.
-- Server/api_key come from ~/.wakatime.cfg, shared with other WakaTime clients.
vim.pack.add({ { src = "https://github.com/wakatime/vim-wakatime", name = "vim-wakatime" } })
-- Wakatime Config
-- Wakapi derives the editor from a `<editor>-wakatime/` user-agent token; the
-- default `wakatime.nvim` has none, so time lands under "Unknown".
Config.plugins.wakatime = {
plugin_name = "neovim-wakatime",
}
require("wakatime").setup(Config.plugins.wakatime)
-- Lazy-loaded Plugins
local lazyload = require("lazyload")
@@ -135,7 +148,7 @@ lazyload.on_vim_enter(function()
signcolumn = true,
current_line_blame = true, -- Required for the statusline variable to update
current_line_blame_opts = {
virt_text = false, -- Disable virtual text as we'll use the statusline
virt_text = false, -- Disable virtual text as we'll use the statusline
},
})
@@ -547,11 +560,11 @@ lazyload.on_vim_enter(function()
},
-- you can enable a preset for easier configuration
presets = {
bottom_search = true, -- use a classic bottom cmdline for search
command_palette = true, -- position the cmdline and popupmenu together
bottom_search = true, -- use a classic bottom cmdline for search
command_palette = true, -- position the cmdline and popupmenu together
long_message_to_split = true, -- long messages will be sent to a split
inc_rename = true, -- enables an input dialog for inc-rename.nvim
lsp_doc_border = false, -- add a border to hover docs and signature help
inc_rename = true, -- enables an input dialog for inc-rename.nvim
lsp_doc_border = false, -- add a border to hover docs and signature help
},
routes = {
{
@@ -596,4 +609,25 @@ lazyload.on_vim_enter(function()
},
}
require("sidekick").setup(Config.plugins.sidekick)
vim.pack.add {
{
src = "https://github.com/obsidian-nvim/obsidian.nvim",
version = vim.version.range "*", -- use latest release, remove to use latest commit
},
}
require("obsidian").setup {
legacy_commands = false, -- this will be removed in 4.0.0
workspaces = {
{
name = "notebook",
path = "~/Documents/Notebook",
},
{
name = "notes",
path = "~/Documents/Notes",
},
},
}
end)
+9
View File
@@ -124,6 +124,11 @@
"rev": "4fc505ac7bd7692824a142e96e5f529c133862f8",
"src": "https://github.com/nvim-tree/nvim-web-devicons"
},
"obsidian.nvim": {
"rev": "7a2b7caf41de196de66f27c1969d0d429810621a",
"src": "https://github.com/obsidian-nvim/obsidian.nvim",
"version": ">=0.0.0"
},
"persistence": {
"rev": "b20b2a7887bd39c1a356980b45e03250f3dce49c",
"src": "https://github.com/folke/persistence.nvim"
@@ -144,6 +149,10 @@
"rev": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d",
"src": "https://github.com/mbbill/undotree"
},
"vim-wakatime": {
"rev": "9f8a1d3b9c6f3a948988a0896b3227c1e1f74a58",
"src": "https://github.com/wakatime/vim-wakatime"
},
"which-key": {
"rev": "3aab2147e74890957785941f0c1ad87d0a44c15a",
"src": "https://github.com/folke/which-key.nvim"