doc/buffer-ctx.txt — rendered from the plugin's own vimdoc
*buffer-ctx.txt* Buffer context for Neovim *buffer-ctx.nvim* Author: Stefan Bartl Version: 0.1.0
CONTENTS
1. Introduction .............. |buffer-ctx-intro| 2. Requirements .............. |buffer-ctx-requirements| 3. Installation .............. |buffer-ctx-installation| 4. Configuration ............. |buffer-ctx-config| 5. Commands .................. |buffer-ctx-commands| 5.1 filepath .............. |:Insert-filepath| 5.2 filename .............. |:Insert-filename| 5.3 module ................ |:Insert-module| 5.4 location .............. |:Insert-location| 5.5 timestamp ............. |:Insert-timestamp| 5.6 uuid .................. |:Insert-uuid| 5.7 annotation ............ |:Insert-annotation| 5.8 boilerplate ........... |:Insert-boilerplate| 5.9 env ................... |:Insert-env| 5.10 date .................. |:Insert-date| 5.11 snippet ............... |:Insert-snippet| 5.12 git ................... |:Insert-git| 5.13 linecount / bufnr ..... |:Insert-linecount| 5.14 mdlink ................ |:Insert-mdlink| 5.15 imagepaste ............ |:Insert-imagepaste| 6. Format command ............ |buffer-ctx-format| 6.1 column ................ |:Format-column| 6.2 table ................. |:Format-table| 6.3 textwidth ............. |:Format-textwidth| 6.4 filter ................ |:Format-filter| 6.5 enum .................. |:Format-enum| 6.6 misc .................. |:Format-misc| 6.7 squeeze ............... |:Format-squeeze| 7. Mark command .............. |buffer-ctx-mark| 7.1 toggle ................ |:Mark-toggle| 7.2 yank .................. |:Mark-yank| 7.3 clear ................. |:Mark-clear| 8. Reveal commands ........... |buffer-ctx-reveal| 8.1 RevealInFm ............ |:RevealInFm| 8.2 OpenInBrowser ......... |:OpenInBrowser| 9. Keymaps ................... |buffer-ctx-keymaps| 10. Lua API ................... |buffer-ctx-api| 11. Tab completion ............ |buffer-ctx-completion| 12. Telescope integration ..... |buffer-ctx-telescope| 13. Health check .............. |buffer-ctx-health| 14. Architecture .............. |buffer-ctx-architecture|
1. INTRODUCTION
buffer-ctx.nvim provides two commands with (almost) an identical subcommand
catalog:
:Insert {subcmd} [args…] — write text at the current cursor position
:Copy {subcmd} [args…] — copy text to the system clipboard (+ register)
All subcommands derive their output from the current buffer: its path, cursor
position, Lua module hierarchy, or structured content patterns. Two
subcommands are cross-plugin shims to sister plugins instead, soft-dependency
style: mdlink (|:Insert-mdlink|, delegates to markdown.nvim,
works under both commands) and imagepaste (|:Insert-imagepaste|, delegates
to images.nvim, :Insert-only — see its own section for why).
No hard dependency. Pure Lua, with one exception: the git subcommand shells
out to the git executable. Every other subcommand is shell-free.
2. REQUIREMENTS
- Neovim 0.9 or later - lib.nvim (https://github.com/StefanBartl/lib.nvim) — REQUIRED The:Insert/:Copy/:Format/:Markcommand layer is built onlib.nvim.bindings.usercmd.composer.notify/mapremain a soft dependency on top of that (nicer formatting when installed, falls back to plainvim.notify/vim.keymap.setotherwise). - (optional) which-key.nvim (https://github.com/folke/which-key.nvim) Labels the<leader>cnkeymap group when installed. - (optional) telescope.nvim (https://github.com/nvim-telescope/telescope.nvim) Enables the boilerplate picker, see |buffer-ctx-telescope|. - (optional)gitin $PATH — only for the |:Insert-git| subcommand. - (optional) open.nvim (https://github.com/StefanBartl/open.nvim) |:OpenInBrowser| delegates to itsbrowserhandler when installed; falls back to|vim.ui.open|(Neovim 0.10+) otherwise. - (optional) markdown.nvim (https://github.com/StefanBartl/markdown.nvim) |:Insert-mdlink| delegates to its own link builder when installed; falls back to a literal "[title](path)" otherwise. - (optional) images.nvim (https://github.com/StefanBartl/images.nvim) |:Insert-imagepaste| delegates to itspastefeature. No local fallback — the subcommand fails without images.nvim installed.
3. INSTALLATION
lazy.nvim, recommended (load shortly after startup):
{
"stefanbartl/buffer-ctx.nvim",
dependencies = { "stefanbartl/lib.nvim" },
event = "VeryLazy",
opts = {},
}
lazy.nvim, lazy-loaded on command use:
{
"stefanbartl/buffer-ctx.nvim",
dependencies = { "stefanbartl/lib.nvim" },
cmd = { "Insert", "Copy", "Format", "Mark", "RevealInFm", "OpenInBrowser" },
opts = {},
}
packer:
use {
"stefanbartl/buffer-ctx.nvim",
requires = { "stefanbartl/lib.nvim" },
config = function()
require("buffer_ctx").setup()
end,
}
4. CONFIGURATION
require("buffer_ctx").setup({
commands = true,
keymaps = {
location_copy = "<leader>cnl",
module_copy = "<leader>cnm",
filepath_copy = "<leader>cnf",
},
})
commands
Register:Insertand:Copy. Default:true.
keymaps
Table of keymap strings, or false to disable all keymaps.
See |buffer-ctx-keymaps| for defaults.
which_key
boolean Label the<leader>cngroup with which-key when installed. Default:true. No-op if which-key.nvim is not installed.
timestamp
Table controlling |:Insert-timestamp|. Default:
timestamp = { utc = false }
utcboolean Emit every timestamp in UTC without passing--utceach time. Default:false. An explicit--utcstill works; it can only turn UTC on, never off.
snippets
Table controlling |:Insert-snippet|. Default:
snippets = { paths = {} }
pathsstring[] VSCode-format snippet files to load. Paths are expanded, so~and$VARwork. Example:
snippets = {
paths = { vim.fn.stdpath("config") .. "/snippets/lua.json" },
}
format
Table controlling the :Format command tree. Default:
format = { enable = true, command = "Format" }
enableboolean Register:Format. Default:true.commandstring Command name. Default:"Format". Setformat = falseto disable the entire:Formattree.
mark
Table controlling the :Mark command tree. Default:
mark = {
enable = true,
command = "Mark",
keymaps = { toggle = "<S-m>", yank = "<C-p>" },
sign = { text = "●", hl = "ErrorMsg" },
categories = {},
}
enableboolean Register:Mark. Default:true.commandstring Command name. Default:"Mark".keymapstable Normal-mode keymaps, orfalseto disable. Keys:toggle,yank,clear(clearunset by default).signtable Appearance of thedefaultcategory: glyph + highlight.categoriesarray Extra named appearances, each{ name, text?, hl? }.:Mark toggle <name>marks in that category;yankandcleartake a<name>to filter by it. Setmark = falseto disable the entire:Marktree.
reveal
Table controlling |:RevealInFm| / |:OpenInBrowser|. Default:
reveal = {
enable = true,
keymaps = { fm = "<leader>of", browser = "<leader>ob" },
}
enableboolean Register both commands. Default:true.keymapstable Normal-mode keymaps, orfalseto disable. Keys:fm,browser. Setreveal = falseto disable both commands entirely.
5. COMMANDS
:Insertand:Copyaccept the same subcommands and arguments, with one exception:imagepaste(|:Insert-imagepaste|) is:Insert-only, since it delegates to a sister plugin whose own action always inserts its result at the cursor rather than returning text to a sink. :Insert {subcmd} [args…] Insert at cursor :Copy {subcmd} [args…] Copy to clipboard Tab completion covers the subcommand and its first argument; further tokens have no completion (forwarded straight to the subcommand's own parser). See |buffer-ctx-completion|.
5.1 filepath
:Insert filepath [mode] [format] [depth] Get the current buffer's file path.
mode
cwdrelative to working directory (default)absabsolute pathnvimrelative tostdpath("config")reposrelative to$REPOS_DIR(errors if unset)
format
unixforward slashes (default)luadot-separated module notation (strips extension + /lua/ prefix)winbackslashessystemOS-native separator
depth
Integer 0–3: only include the last (depth+1) path segments. Examples:
:Copy filepath → lua/buffer_ctx/ops/filepath.lua
:Copy filepath abs → C:/…/filepath.lua
:Copy filepath lua → buffer_ctx.ops.filepath
:Copy filepath 1 → filepath.lua
:Copy filepath nvim → relative to nvim config dir
:Copy filepath repos → relative to $REPOS_DIR
:Copy filepath env → "$REPOS_DIR/…" or "$NVIM_CONFIG_DIR/…"
envfolds the buffer path under whichever of $REPOS_DIR / $NVIM_CONFIG_DIR (stdpath("config")) it lives under into a literal "$VAR/…" string (longest root wins); with neither set or matching, it falls back to the plain cwd-relative path, same asnvim/reposdo. Compat commands are registered automatically: :CopyFilepathAbsolute → :Copy filepath absolute :CopyFilepathRelative → :Copy filepath relative :CopyFilepathRepos → :Copy filepath repos :CopyFilepathEnv → :Copy filepath env
5.2 filename
:Insert filename [noext] Basename of the current buffer's file. noext strip the extension Examples:
:Insert filename → filepath.lua
:Insert filename noext → filepath
5.3 module
:Insert module [style]
Derive the Lua module path from the /lua/ segment and emit it as a
statement or annotation.
style
requirerequire("foo.bar") (default)lua_ls/luals---@module'foo.bar'jsimport "foo/bar"c#include "foo/bar.h"genericfoo.bar Examples:
:Copy module → require("buffer_ctx.ops.filepath")
:Copy module lua_ls → ---@module 'buffer_ctx.ops.filepath'
5.4 location
:Insert location [mode] [range]
Current cursor position as path:line.
mode
cwdrelative (default)absabsoluteluaLua module path
range
Emitpath:L1-L2for a line span instead of a single line — useful for code-review comments and GitHub-style links. The span comes from the command's range. In visual mode, pressing:inserts'<,'>for you. Without an explicit range, the last visual selection's marks are used as a fallback. A single-line range has no span to express and collapses back topath:42. Examples:
:Copy location → lua/buffer_ctx/ops/filepath.lua:42
:Copy location abs → C:/…/filepath.lua:42
:Copy location lua → buffer_ctx.ops.filepath:42
:'<,'>Copy location range → lua/buffer_ctx/ops/filepath.lua:L10-L20
:10,20Copy location range → lua/buffer_ctx/ops/filepath.lua:L10-L20
5.5 timestamp
:Insert timestamp [format] [--utc]
format
iso2026-06-22T14:35:00 (default)iso-date2026-06-22iso-time14:35:00unix1750600500humanJune 22, 2026 14:35short22.06.2026log2026-06-22 14:35:00filename20260622_143500longMonday, June 22, 2026weekdayMondaytime14:35:00 (alias ofiso-time)12h02:35:00 PMrfc2822Mon, 22 Jun 2026 14:35:00--utcoutput in UTC instead of local timeweekday/long/rfc2822always render English weekday/month names regardless of'v:lang'/system locale (os.date's%A/%B/%a/%bfollow the C locale, e.g. German renders%aas "Di");12his built by hand since Windows' C runtime drops%p(AM/PM) silently. Examples:
:Insert timestamp → 2026-06-22T14:35:00
:Insert timestamp short --utc → 22.06.2026 (UTC)
:Insert timestamp 12h → 02:35:00 PM
5.6 uuid
:Insert uuid [format] UUID v4 (randomly generated).
format
standard550e8400-e29b-41d4-a716-446655440000 (default)compact550e8400e29b41d4a716446655440000upper550E8400-E29B-41D4-A716-446655440000braced{550e8400-e29b-41d4-a716-446655440000}
5.7 annotation
:Insert annotation {type} [args…]
type
module---@module'foo.bar'(from current buffer path)class[name] ---@class Namefield[n] [t] ---@field name typeparam[n] [t] ---@param name typereturn[type] ---@return typealias[n] [t] ---@alias Name stringoverload[sig] ---@overload fun(a: string): booleandiagnostic[c] ---@diagnostic disable-next-line: codedeprecated[r] ---@deprecated Reasonfunctionguided dialog → multi-line annotation block Arguments not provided on the command line are prompted viavim.fn.input.overloadanddeprecatedtake free text that may contain spaces; the whole remainder of the command line is used, not just the first word.overloadwraps the signature infun(…)if you leave that off.:Copy annotation functionjoins the generated block into one\n-separated clipboard string. Examples:
:Insert annotation module → ---@module 'buffer_ctx.ops.module'
:Insert annotation class MyService → ---@class MyService
:Insert annotation param name string → ---@param name string
:Insert annotation overload fun(): nil → ---@overload fun(): nil
:Insert annotation diagnostic unused
→ ---@diagnostic disable-next-line: unused
:Insert annotation deprecated use new → ---@deprecated use new
:Insert annotation function → (interactive dialog)
5.8 boilerplate
:Insert boilerplate [template] [name] Insert (or copy) a multi-line code template.:Copy boilerplatejoins lines with newline before copying. Called without a template name, a|vim.ui.select|picker of the available keys is shown, so the feature does not depend on tab completion. With telescope.nvim installed, see |buffer-ctx-telescope| for a picker that also previews the generated lines. Templates:
lua-module Lua module skeleton with setup()
lua-class OOP class with new() constructor
lua-function Annotated function stub
nvim-autocmd nvim_create_autocmd block
nvim-keymap vim.keymap.set stub
guard-clause Guard clause pattern (interactive)
html-figure <figure> with <img> + <figcaption>
html-code Code listing <figure>
html-quote Blockquote <figure>
html-formula-table Formula reference table
html-aside <aside> block
html-pagination Pagination <nav>
html-accordion <details> accordion
html-table <table> with thead + 3x3 body
html-section <section> with h2 + p
lua-test busted stub (describe/it/assert.are.equal)
lua-enum Enum table + ---@alias block
md-frontmatter YAML frontmatter block
Examples:
:Insert boilerplate (interactive picker)
:Insert boilerplate lua-module
:Insert boilerplate lua-class MyService
:Insert boilerplate nvim-autocmd MyAuGroup
:Copy boilerplate html-figure intro
5.9 env
:Insert env {VAR}
Insert or copy the value of an environment variable. A leading $ is
stripped automatically. Tab completion lists the variables currently set.
Examples:
:Copy env GOPATH
:Insert env HOME
:Copy env $PATH
5.10 date
:Insert date [format] [--utc] Shorthand for |:Insert-timestamp| defaulting toiso-dateinstead ofiso— same[format]values (iso,iso-date,iso-time,unix,human,short,log,filename,long,weekday,time,12h,rfc2822) and the same--utcflag apply. Honours thetimestamp.utcconfig option, see |buffer-ctx-config|. Examples:
:Insert date → 2026-06-22
:Insert date long → Monday, June 22, 2026
:Insert date iso --utc → 2026-06-22T14:35:00 (UTC)
5.11 snippet
:Insert snippet [name] Insert a snippet from the VSCode-format files listed insnippets.paths, see |buffer-ctx-config|. Without a name, a|vim.ui.select|picker is shown. A snippet resolves by its key or by itsprefix, so both of these work for the file below:
:Insert snippet "For Loop"
:Insert snippet forl
File format:
{
"For Loop": {
"prefix": "forl",
"body": ["for ${1:i} = 1, ${2:10} do", "\t$0", "end"],
"description": "numeric for loop"
}
}
Placeholders are flattened rather than expanded:${1:i}becomesi,${1|a,b|}becomesa, and bare tabstops ($0,$1) are removed. buffer-ctx inserts plain text — for real tabstop navigation use a dedicated snippet engine.
5.12 git
:Insert git [mode]
Git revision info for the repository the current buffer belongs to. The query
runs in the buffer's own directory, so the result stays correct after |:cd|.
mode
shortabbreviated commit hash (default)hashfull commit hashbranchcurrent branch nametagnearest tag, else abbreviated hash (git describe --tags --always) Requires thegitexecutable in $PATH. On a detached HEAD,branchreports an error instead of returning the literal string "HEAD". Examples:
:Insert git → a577942
:Copy git hash → a577942dedbcb4e8a4e9ffb3529be12b27b58736
:Copy git branch → main
5.13 linecount / bufnr
*:Insert-bufnr* :Insert linecount :Insert bufnr Line count of the current buffer, and the current buffer handle. Useful for documentation references and for Lua scripting/debugging respectively. Examples:
:Insert linecount → 348
:Insert bufnr → 3
5.14 mdlink
:Insert mdlink [mode] [format] [depth]
Wrap the current buffer's path in a Markdown link ("[title](path)"). Takes
the exact same mode/format/depth arguments as |:Insert-filepath| —
whatever :Copy filepath ... would produce is what gets wrapped.
Cross-plugin shim: delegates to markdown.nvim's own
markdown.commands.markdown_links.for_paths() (the function behind
:Markdown links <path>) when markdown.nvim is installed — soft dependency,
pcall(require, ...), same convention as ui.kit in commands.lua's
resolve_kit(). Falls back to the literal "[%s](%s)" format inline
otherwise (markdown.nvim hardcodes the exact same format for a single file,
so nothing behaves differently either way).
Examples:
:Copy mdlink → [filepath.lua](lua/buffer_ctx/ops/filepath.lua)
:Insert mdlink abs → [filepath.lua](C:/…/filepath.lua)
:Copy mdlink repos → [filepath.lua](buffer-ctx.nvim/lua/…/filepath.lua)
5.15 imagepaste
:Insert imagepaste [name] [path=relative|absolute|repos|<prefix>] Paste the clipboard image via images.nvim's ownpastefeature (require("images").paste(name, nil, path_mode)) — the exact same{name}/path=...grammar:Image pasteitself accepts, so this is a convenience alias for reaching that action through buffer-ctx's own:Insertfamily rather than a second implementation of it.:Insert-only, unlike every other subcommand above: images.nvim'spastereads the OS clipboard *asynchronously* and inserts the resulting Markdown link directly into the buffer at the cursor itself — there is no "give me the link text instead" mode to route through:Copy's clipboard sink, so:Copy imagepastedoes not exist (attempting it errors "unknown subcommand", the same as any other typo). Cross-plugin shim: soft dependency on images.nvim,pcall(require, "images")re-checked on every call, same convention asui.kitincommands.lua'sresolve_kit(). Without images.nvim installed, this errors rather than falling back — reimplementing its clipboard-read pipeline here would duplicate platform-specific logic that already exists once, there, on purpose. Examples:
:Insert imagepaste
:Insert imagepaste screenshot-1
:Insert imagepaste path=absolute
6. FORMAT COMMAND
:Format {subcmd} [args…]
Unified buffer/selection formatting. Tab completion covers the subcommand
and its first argument (e.g. -r/--reverse for sort, a style/key=
for enum); further tokens have no completion.
6.1 column
:Format column [<N> [fill]]
With a column number: align the character under the cursor (or visually
selected block column) to column N, padding with fill (default: space).
Without arguments: opens an interactive prompt for N and fill character.
Examples:
:Format column 40 → pad current char to column 40 with spaces
:Format column 40 = → pad with "=" character
:Format column → interactive prompt
6.2 table
:Format table [ALIGN] [header=ALIGN] [cell=ALIGN] [skip=COL] [scope=SCOPE] Format Markdown tables in the current buffer, a file, or the entire cwd.
ALIGN
left,center,rightPositional shorthand for header + cell align.
header=ALIGN
Alignment for the header row (default: center).
cell=ALIGN
Alignment for data rows (default: center).
skip=COL
Column number(s) or name(s) to force-align left (comma-separated).
scope=SCOPE
cursorFormat only the table under the cursor (default).bufferFormat all tables in the current buffer.cwdFormat all *.md files under the working directory. Examples:
:Format table → format table at cursor
:Format table left → all columns left-aligned
:Format table header=left cell=right → mixed alignment
:Format table scope=buffer → format every table in buffer
6.3 textwidth
:Format textwidth <N|max> Settextwidthto N (or the current window width ifmax) and reflow the entire buffer using word-wrap, preserving paragraph breaks and list prefixes. Examples:
:Format textwidth 80
:Format textwidth max
6.4 filter
:Format filter [--remove] <pattern> [<pattern>…] Keep lines that match ALL patterns. With--remove(or-r): remove matching lines instead. Examples:
:Format filter TODO → keep only lines containing "TODO"
:Format filter --remove FIXME → remove lines containing "FIXME"
:Format filter foo bar → keep lines containing both "foo" and "bar"
6.5 enum
:Format enum [STYLE] [sep=SEP] [start=N] [inline=true|false] Enumerate whitespace-separated tokens from the visual selection.
STYLE
decimal1. 2. 3. (default)alphaa. b. c.ALPHAA. B. C.romani. ii. iii.ROMANI. II. III.
sep=SEP
Separator string after each label. Default: ". ".
start=N
First counter value. Default: 1.
inline=true|false
trueemit all on one line.falseemit one per line. auto single-line input → inline, multi-line → one per line. Examples:
:Format enum → 1. foo 2. bar (decimal, inline)
:Format enum roman → i. foo ii. bar
:Format enum alpha inline=false → a. foo\nb. bar
:Format enum sep=) start=3 → 3) foo 4) bar
6.6 misc subcommands
:Format trim
Remove trailing whitespace from every line in the buffer.
:Format sort [-r] [-i] [-n]
Sort buffer lines. -r reverse, -i ignore-case, -n numeric.
:Format unique [-i]
Remove duplicate lines. -i ignore-case.
:Format case <upper|lower|title|sentence>
Change the case of every line.
:Format indent [--spaces|--tabs] [N]
Normalise indentation using the current expandtab/shiftwidth, or the
flags/width provided.
:Format clear
Erase all lines in the buffer.
6.7 squeeze
:Format squeeze Collapse consecutive blank lines down to at most one, so a run of blank lines never separates two pieces of text by more than a single empty line. Operates on the whole buffer by default. With an explicit range — a visual selection (press:right after v/V/CTRL-V, Neovim fills in'<,'>for you) or a plain line range — only that span is squeezed; a blank line just outside the range is left untouched, since it was not part of the selection. Examples:
:Format squeeze (whole buffer)
:'<,'>Format squeeze (visual selection only)
:10,20Format squeeze (explicit line range only)
7. MARK COMMAND
:Mark {subcmd} [category]
Toggle per-line marks, clear them, and collect them to the system clipboard.
Marks are stored per buffer and survive buffer switches (until Neovim exits).
A marked line is indicated by a ● character:
• In the sign column when signcolumn ≠ "no"
• As a left-column extmark otherwise
toggle, yank and clear each take an optional category name (configured
via mark.categories, see |buffer-ctx-config|); yank/clear then act only
on marks in that category. Tab completion is supported for the subcommand and
the category argument.
Compat commands are registered automatically:
:MarkLineToggle → :Mark toggle
:MarkLinesYank → :Mark yank
7.1 toggle
:Mark toggle
Toggle the mark on the current line. If the line is already marked the mark
is removed; otherwise it is added.
Marks are anchored to the text, not to a line number: they follow their line
as you insert or delete lines above them, and toggling recognises a mark by
where it sits now. Deleting a marked line removes its mark (Neovim 0.10+;
on 0.9 the mark moves to the following line instead).
Marks are session-only and are cleared when the buffer is deleted or wiped.
Default keymap: <S-m>
7.2 yank
:Mark yank Collect all marked lines in the current buffer and write them to the system clipboard (+register) as newline-separated text. Lines come out in buffer order — that is, ordered by where each mark sits at the time of the yank, not by the order the marks were created in. A notification reports how many lines were copied. Default keymap:<C-p>
7.3 clear
:Mark clear [category]
Remove every mark in the current buffer, or — with a category name — only the
marks in that category. Before this the only way to unmark was toggling each
line one at a time.
No keymap by default. Bind one with mark.keymaps.clear, see
|buffer-ctx-config|.
8. REVEAL COMMANDS
Two independent, argument-less commands -- unlike |buffer-ctx-format| and
|buffer-ctx-mark| there is no shared subcommand tree here. Both act on the
current buffer's own path. Disable either (or both) via opts.reveal, see
|buffer-ctx-config|.
8.1 RevealInFm
:RevealInFm Reveals the current buffer in the system file manager -- a file selected inside its parent directory (Explorer/Finder/Nautilus/…). Delegates to lib.nvim'scross.reveal_in_fm, the exact dispatcher filetree.nvim's<leader>fmand open.nvim's:Open filemanagerhandler already share, so a fix there lands here too. No fallback: lib.nvim is already a hard dependency for this plugin's command layer (see |buffer-ctx-requirements|). Default keymap:<leader>of
8.2 OpenInBrowser
:OpenInBrowser Opens the current buffer with the OS-registered application for it -- a browser for an.htmlfile, whatever else the OS associates otherwise. Prefers open.nvim's ownbrowserhandler when open.nvim is installed (require("open").open("browser", "%"), an explicit target+scope so open.nvim dispatches straight to it rather than running its own no-target heuristic). Falls back to|vim.ui.open|(Neovim 0.10+) when open.nvim is absent. Default keymap:<leader>ob
9. KEYMAPS
Registered only whensetup()is called (orkeymaps = falseto disable).<leader>cnlCopy path:line (location, cwd-relative)<leader>cnmCopy Lua module path<leader>cnfCopy filepath (cwd-relative, unix format)<S-m>:Mark toggle (toggle mark on current line)<C-p>:Mark yank (yank all marked lines to clipboard)<leader>of:RevealInFm (reveal current buffer in file manager)<leader>ob:OpenInBrowser (open current buffer in the browser) All keys are configurable via the respective config tables. When which-key.nvim is installed, the<leader>cnprefix is automatically labeled "buffer-ctx: copy context". Setwhich_key = falseto disable this.
10. LUA API
local ctx = require("buffer_ctx")
setup({opts}) *buffer_ctx.setup()*
Configure and activate. Idempotent.
insert({subcmd}, {args}) *buffer_ctx.insert()*
Insert at cursor. Equivalent to :Insert {subcmd} [args…].
copy({subcmd}, {args}) *buffer_ctx.copy()*
Copy to clipboard. Equivalent to :Copy {subcmd} [args…].
Examples:
ctx.copy("location", {})
ctx.copy("module", { "lua_ls" })
ctx.insert("uuid", { "braced" })
ctx.insert("boilerplate", { "lua-class", "MyService" })
11. TAB COMPLETION
Both:Insertand:Copyprovide context-aware tab completion::Insert <Tab>→ list all subcommands:Insert filepath <Tab>→ cwd, abs, nvim, lua, unix, win, system, 0–3:Insert mdlink <Tab>→ same values asfilepath(see above):Insert module <Tab>→ require, lua_ls, js, c, generic:Insert timestamp <Tab>→ iso, iso-date, iso-time, unix, human, …:Insert uuid <Tab>→ standard, compact, upper, braced:Insert annotation <Tab>→ module, class, field, param, return, …:Insert boilerplate <Tab>→ lua-module, lua-class, nvim-autocmd, …:Insert location <Tab>→ cwd, abs, lua, range:Insert git <Tab>→ hash, short, branch, tag:Insert snippet <Tab>→ snippet keys and prefixes from your files:Insert env <Tab>→ environment variables currently set
12. TELESCOPE INTEGRATION
With telescope.nvim installed, register the extension:
require("telescope").load_extension("buffer_ctx")
Then:
:Telescope buffer_ctx boilerplate
The picker lists every boilerplate template with its description and previews the exact lines it would generate. Selecting one inserts it at the cursor. Telescope is an optional dependency — the extension file is only ever loaded by Telescope itself, so the plugin works standalone without it.
13. HEALTH CHECK
:checkhealth buffer_ctx
Checks: - Neovim >= 0.9 -vim.uv/vim.loopavailable -vim.fn.setregavailable - Plugin loaded (guard flag set) - lib.nvim detected? (required — command layer, lib.nvim.bindings.usercmd.composer) - lib.nvim detected? (optional — notify upgrade) - lib.nvim detected? (optional — map upgrade) - which-key detected? (optional — <leader>cn group label) - markdown.nvim detected? (optional — :Insert/:Copy mdlink's own link builder) - images.nvim detected? (optional, no local fallback — :Insert imagepaste) -buffer_ctx.bindingsloadable -:CopyFilepathAbsolute,:CopyFilepathRelative,:CopyFilepathReposand:CopyFilepathEnvcompat commands registered - Format subsystem: enabled flag,:Formatregistered, each sub-module loadable - Mark subsystem: enabled flag,:Markand:MarkLineToggleregistered - Reveal subsystem: enabled flag,:RevealInFm/:OpenInBrowserregistered, lib.nvim.cross.reveal_in_fm detected (required), open.nvim or vim.ui.open detected (optional — :OpenInBrowser's fallback chain)
14. ARCHITECTURE
plugin/buffer_ctx.lua Load guard
lua/buffer_ctx/
init.lua Public API, setup()
config/
init.lua setup()/get() — deep-merge over DEFAULTS
DEFAULTS.lua Plugin-side default configuration
@types.lua LuaLS annotations
commands.lua :Insert / :Copy (lib.nvim.bindings.usercmd.composer) + shared dispatch
health.lua checkhealth provider
bindings/
init.lua Orchestrates usrcmds + keymaps + autocmds
usrcmds.lua Registers :Insert / :Copy
keymaps.lua The 3 core copy keymaps (+ the <leader>cn
which-key group label, carried in the spec)
autocmds.lua Extension point (no autocmds registered today)
format/
init.lua :Format command (lib.nvim.bindings.usercmd.composer) + subcommand registry
column_align.lua Column-alignment (visual selection)
table_fmt.lua Markdown table formatter
text_width.lua Text reflow (word-wrap)
filter_lines.lua Line filter (keep / remove)
enum_lines.lua Token enumeration for visual selection
misc.lua trim, sort, unique, case, indent, clear
blank_lines.lua squeeze (collapse blank-line runs, range-aware)
mark/
init.lua :Mark command (lib.nvim.bindings.usercmd.composer) + toggle/clear/yank logic + compat cmds
reveal/
init.lua :RevealInFm / :OpenInBrowser (lib.nvim.bindings.usercmd, plain -- no composer verb needed for two argument-less commands) + keymaps
util/
notify.lua "[buffer-ctx] " notify wrapper; upgrades to lib.nvim if present
map.lua keymap wrapper; upgrades to lib.nvim.bindings.keymap if present
cursor.lua insert_text / insert_lines at cursor position
clip.lua setreg("+", …) + notify
path.lua get_module_path, relative_to_cwd, pick_depth
ops/
filepath.lua Path formatting (mode + format + depth)
module.lua Lua module path → statement
timestamp.lua Timestamp generation (13 formats)
uuid.lua UUID v4 generation
annotation.lua LuaLS annotation lines (with interactive dialog)
location.lua path:line (and path:L1-L2) from cursor/range
env.lua Environment variable lookup + completion list
git.lua Git revision info (hash/short/branch/tag)
bufinfo.lua Buffer line count and handle
snippet.lua VSCode-format snippet loading
reveal.lua reveal_in_fm / open.nvim / vim.ui.open dispatch (side effects, no text return)
markdown_link.lua [title](path) wrapper; delegates to markdown.nvim when installed
imagepaste.lua images.nvim "paste" delegate (side effect, no text return -- like reveal.lua)
boilerplate/
init.lua Template registry + dispatch
templates/
lua.lua Lua code templates
nvim.lua Neovim-specific templates
html.lua HTML snippet templates
markdown.lua Markdown templates (frontmatter)
guard.lua Guard clause pattern
utils.lua Shared prompt helpers
lua/telescope/_extensions/
buffer_ctx.lua Optional Telescope boilerplate picker
docs/
BINDINGS.md Keymap / command / autocommand cheatsheet
TESTS/ Headless spec suite (run.lua)
Module load order: util → ops → commands/format/mark → bindings → init