- Copy editor context to clipboard via picker
- Built-in context items: file, position, selection, diagnostics, quickfix, and more
- Custom prompts with template variable expansion
- Picker-agnostic: works with Snacks, Telescope, fzf-lua, or vim.ui.select
- Tree-sitter powered function/class detection
- Visual selection aware positioning
Using lazy.nvim:
{
"ahkohd/context.nvim",
config = function()
require("context").setup()
end,
}return {
"ahkohd/context.nvim",
config = function()
local context = require("context")
context.setup({
picker = context.pickers.snacks,
prompts = {
explain = "Explain {this}",
fix = "Fix the issue at {position}",
review = "Review {file} for issues",
},
})
end,
keys = {
{
"<leader>a",
function()
require("context").pick()
end,
desc = "Context",
mode = { "n", "v" },
},
},
}require("context").setup({
-- Picker to use (required)
picker = require("context").pickers.snacks,
-- picker = require("context").pickers.telescope,
-- picker = require("context").pickers.fzf_lua,
-- picker = require("context").pickers.vim_ui,
-- Action when item is selected (default: copy to clipboard)
on_select = function(item)
vim.fn.setreg("+", item.value)
end,
-- Custom prompts with template variables
prompts = {
explain = "Explain {this}",
fix = "Fix the issue at {position}",
review = "Review {file} for issues",
diagnose = "Help fix these diagnostics:\n{diagnostics}",
},
-- Prefix for path output (default: "@")
-- path_prefix = "@", -- "@src/file.lua"
-- path_prefix = nil, -- "src/file.lua"
path_prefix = "@",
-- LSP settings for definition getter
lsp = {
enabled = false, -- set to true to enable LSP-based getters
timeout = 1000, -- request timeout in ms
},
})| Name | Description | Example Output |
|---|---|---|
buffers |
List of all open buffers | @src/main.lua@src/utils.lua |
file |
Current file path (relative) | @src/main.lua |
file_absolute |
Current file path (absolute) | /home/user/project/src/main.lua |
position |
Cursor position (relative) | @src/main.lua:42 |
position_absolute |
Cursor position (absolute) | /home/user/project/src/main.lua:42 |
line |
Current line content | local foo = "bar" |
selection |
Visual selection text | Selected text content |
diagnostics |
Diagnostics for current buffer | [ERROR] msg @file:10-10 |
diagnostics_all |
All workspace diagnostics | All diagnostics |
quickfix |
Quickfix list with title | Quickfix entries |
function |
Function at cursor (Tree-sitter) | function foo @file:10:1 |
class |
Class/struct at cursor (Tree-sitter) | class Bar @file:5:1 |
this |
Position if file, else 'this' + selection | Smart context |
- Cursor:
@file:line - Same-line selection:
@file:line:col-col - Multi-line selection:
@file:start-end
Use {variable} syntax in prompts to expand context:
prompts = {
review = "Review {file} for issues",
fix = "Fix the code at {position}:\n{selection}",
diagnose = "Help with:\n{diagnostics}",
}Available variables: {buffers}, {file}, {file_absolute}, {position}, {position_absolute}, {line}, {selection}, {diagnostics}, {diagnostics_all}, {quickfix}, {function}, {class}, {this}
Add custom context items:
require("context").setup({
getters = {
-- Shorthand: just a function
my_getter = function(builtin)
return "File: " .. (builtin.file() or "none")
end,
-- Full form: with description and filetype filter
lua_module = {
desc = "Lua module path",
enabled = function() return vim.bo.filetype == "lua" end,
get = function(builtin)
local file = builtin.file()
if not file then return nil end
return file:gsub("^@", ""):gsub("%.lua$", ""):gsub("/", ".")
end,
},
},
})builtinparameter provides access to all built-in getters for compositionenabledfunction controls visibility in picker (hidden when returnsfalse)
Pre-built LSP-based getters are available in context.extras.lsp:
| Name | Description | Example Output |
|---|---|---|
lsp.definition |
Path to symbol definition via LSP | @src/module.py:42 |
lsp.references |
All references to symbol via LSP | @src/main.py:10@src/utils.py:25 |
LSP getters are lazy-evaluated on selection to avoid blocking the picker.
Requires an LSP server (e.g., pyright, rust-analyzer). Set lsp.enabled = true to use.
Usage:
local context = require("context")
local extras = require("context.extras")
context.setup({
picker = context.pickers.snacks,
lsp = { enabled = true },
getters = {
definition = extras.lsp.definition,
references = extras.lsp.references,
},
})Implement a custom picker with this signature:
local function my_picker(items, on_select)
-- items: { { name = "file", desc = "...", value = "..." }, ... }
-- on_select: function(item) called when user selects an item
end
require("context").setup({
picker = my_picker,
})setup(opts)- Initialize the plugin with configurationpick(on_select?)- Open the context picker with optional callback overrideget_items()- Get all context items (prompts + built-in)pickers.snacks- Snacks.nvim picker adapterpickers.telescope- Telescope picker adapterpickers.fzf_lua- fzf-lua picker adapterpickers.vim_ui- vim.ui.select fallback adapter
Override the default action per-call:
-- Send to a terminal instead of clipboard
require("context").pick(function(item)
if item and item.value then
vim.api.nvim_chan_send(term_channel, item.value)
end
end)CleanShot.2025-11-29.at.11.21.51.mp4
PRs are welcome! If you have ideas or find bugs, open an issue.