Skip to content

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

annotate.nvim

Line-anchored notes for Neovim, under a single :Annotate command. A note is displayed as virtual text at the end of its line, follows the line as the file is edited.

image
command description
Annotate [set] add or edit the note on the current line
Annotate delete remove the note on the current line
Annotate list select a note and jump to it
Annotate qflist send every note to the quickfix list
Annotate clear_file remove every note in the current file
Annotate clear_all remove every note in the store

Requirements

Neovim >= 0.10. No other dependencies.

Installation

With vim.pack, Neovim 0.12's built-in plugin manager:

vim.pack.add({ "https://github.com/mbfoss/annotate.nvim" })

With lazy.nvim:

{ "mbfoss/annotate.nvim" }

There is no required setup call: :Annotate is registered when the plugin loads, and the plugin's modules are loaded on first use or when a file with notes is opened.

Notes

:Annotate with no arguments, or :Annotate set, prompts for the text of a note on the current line. On a line that already has a note, the existing text is offered for editing; submitting an empty prompt removes the note.

A note can be displayed as virtual text at the end of its line, as a sign in the gutter, or both. sign sets the sign character, and "" disables it; virt_text_pos = "off" or "" disables the virtual text. With both disabled, a note is invisible in the buffer but still appears in :Annotate list and :Annotate qflist.

Notes are extmarks, so they track their line through inserts and deletes above them instead of holding a fixed line number. Line numbers are recorded as they stand when the file is written.

Deleting an annotated line does not discard the note. It moves to the line that takes the deleted line's place, or to the last line of the file if the delete extended to the end. The note remains visible and reachable from :Annotate list, where it can be moved or removed with :Annotate delete.

:Annotate list opens vim.ui.select over every note in the store and jumps to the selected one. :Annotate qflist sends the same list to the quickfix window, which is more suitable for reading through notes than for jumping to a single one.

:Annotate delete removes the note on the current line. :Annotate clear_file and :Annotate clear_all remove every note in the current file or in the whole store, after a confirmation.

Storage

Notes are stored in a single JSON file, stdpath("data")/annotate.json by default, as a map from file to the notes on it:

{
  "version": 2,
  "notes": {
    "/home/me/proj/lua/init.lua": [{ "lnum": 12, "text": "rewrite this" }]
  }
}

To keep notes per project, set storage_file to a function returning a path. It is resolved at every read and write, so it can depend on the current buffer or directory:

require("annotate").setup({
    storage_file = function()
        local root = vim.fs.root(0, ".git") or assert(vim.uv.cwd())
        return vim.fs.joinpath(root, ".annotate.json")
    end,
})

That writes .annotate.json in the root of the current git repository, which is then a file to commit or to add to .gitignore. Paths are stored relative to the directory the store is in when they are under it, so such a store survives the project being moved or cloned elsewhere; a note on a file outside that directory keeps its absolute path.

The store is written when a note changes, when a buffer holding notes is written, and on exit. A store left with no notes is removed.

Configuration

setup() is optional and only needed to change a default.

require("annotate").setup({
    symbol        = "",        -- drawn before the note text
    priority      = 50,         -- extmark priority of the virtual text
    sign          = "",         -- one or two cells in the gutter; "" draws none
    virt_text_pos = "eol",      -- or "right_align", or "off" ("") for none
    storage_file  = nil,        -- path, or a function returning one; defaults
                                -- to stdpath("data")/annotate.json
})
option type description
symbol string prefix drawn before the note text
priority number extmark priority for the virtual text
sign string sign placed in the gutter, one or two cells wide; "" draws none
virt_text_pos string extmark virt_text_pos: eol, right_align, or off (or "") for no virtual text
storage_file string or function JSON file the notes are written to; a function is called at every read and write

Highlights

group default applies to
AnnotateNote Todo the note's virtual text
AnnotateSign AnnotateNote the note's sign in the gutter

API

require("annotate.notes") exposes the functionality directly, for keymaps and for use from other code.

local notes = require("annotate.notes")

notes.set(file, lnum, text)   -- add or replace the note on a line
notes.get(file, lnum)         -- its text, or nil
notes.remove(file, lnum)      -- remove it, returns whether there was one
notes.list()                  -- every note: { file, lnum, text }, ordered
notes.clear_file(file)
notes.clear_all()

notes.set_at_cursor()         -- the functions the commands call
notes.delete_at_cursor()
notes.select()
notes.qflist()
notes.clear_current_file()
notes.clear_all_confirm()
vim.keymap.set("n", "<leader>na", require("annotate.notes").set_at_cursor)
vim.keymap.set("n", "<leader>nd", require("annotate.notes").delete_at_cursor)
vim.keymap.set("n", "<leader>nl", require("annotate.notes").select)

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages