[!IMPORTANT]
This plugin has done what it was supposed to do, and all that it could do.
This plugin is in maintenance mode now. No more new features will be added in general — only bug fixes. I still use it every day myself.
TextEdit preciselyTextEdit precisely in visual modeJSX/TSX out of the boxTextEdits -- unlike Noevim's built-in or other comment plugins, changes are modeled as TextEdits, making it more
hackable and composable. This also means that the edits commit method is up to you -- lockmarks + vim.api.nvim_buf_set_lines
for simplicity and performance, or vim.api.nvim_buf_set_text for more control (e.g. preserve regular marks and extmarks)@REM vs @rem vs @rEm//, ///, //!)| Feature | celeste_comment.nvim | Neovim built-in | Comment.nvim | mini.comment | vim-commentary |
|---|---|---|---|---|---|
| Edit model | TextEdits — edits as range+text objects• commit changes via nvim_buf_set_text or nvim_buf_set_lines (lockmarks) |
Direct line replacement• nvim_buf_set_lines (lockmarks) |
Direct line replacement• nvim_buf_set_lines (lockmarks) |
Direct line replacement• nvim_buf_set_lines (lockmarks) |
Direct line replacement• Vim setline() |
| Keep cursor | Precise tracking — cursor adjusts per TextEdit | No | Imprecise restore — save/restore• no edit adjustment | No | No |
| Keep selection | Precise tracking — selection adjusts per TextEdit | No | No | No | No |
| Multicursor support | More complete native multicursor support | Limited support | Limited support | Limited support | Limited support |
| Line comment | Yes | Yes | Yes | Yes | Yes |
| Block comment | Yes | No | Yes | No | No |
| Dot-repeat | Yes | Yes | Yes | Yes | Yes |
| Count | Yes | Yes | Yes | Yes | Yes |
| Line textobject | Yes | Yes | No | Yes | Yes |
| Block textobject | Yes | No | No | No | No |
| Textobject auto | Yes | No | No | No | No |
| Uncomment auto | Yes | No | No | No | Yes |
| Indent algorithm | VSCode-style — min visible col• handle mixed tab/space | Simple — min whitespace prefix• does not handle mixed tab/space | Standard — shiftwidth/tabstop | Simple — min whitespace prefix• does not handle mixed tab/space | Minimal — ^\s*\zs• optional startofline |
| Invert per line | Yes | No | No | No | No |
| Force add comment | Yes | No | No | No | No |
| Force remove comment | Yes | No | No | No | No |
vim.pack.add({
{
src = "https://github.com/celeste3z/celeste_comment.nvim",
version = vim.version.range("*"),
},
})
require("celeste_comment").setup()
{ "celeste3z/celeste_comment.nvim", lazy = false, opts = {} }
call plug#begin()
Plug 'celeste3z/celeste_comment.nvim'
call plug#end()
lua require("celeste_comment").setup()
---@type Celeste.Comment.PartialOpts
{
-- Restore cursor position after comment/uncomment.
keep_cursor = true,
-- Restore selection after commenting.
-- Possible values: "never" | "adjust" | "expand_block" | "expand_line" | "keep_visual"
--
-- Can also combine, e.g. "expand_line | keep_visual" which means: force line comments to
-- `V` mode and stay in visual mode
-- See `:help celeste_comment-config-keep_selection` for more details.
--
-- Recommend "adjust | expand_block" personally.
keep_selection = "never",
-- Insert space between comment marker and text.
insert_space = true,
-- Place comment at start of line, skip indent alignment
line_comment_no_indent = false,
-- Match comment markers case-insensitively (e.g. `@REM` vs `@rem` vs `@rEm`)
case_insensitive = false,
-- Whether to use `vim.api.nvim_buf_set_text` to commit edits.
-- `nvim_buf_set_text` only modifies parts of lines, preserving regular marks and
-- extmarks on non-modified parts.
-- `nvim_buf_set_lines` + `lockmarks` replaces whole lines, has better performance
-- but only preserves regular marks.
use_set_text = false,
-- Relaxed block comment detection: ignore whitespace around markers.
block_relaxed_detect = true,
-- Max lines to search for block comment pairs.
block_textobj_nlines = 200,
-- How to handle empty lines during comment toggle.
-- See `:help celeste_comment-config-ignore_empty_lines` for more details
-- Possible values: "never" | "mixed" | "always"
ignore_empty_lines = "always",
-- Fallback to block comment when line comment wraps.
-- See `:help celeste_comment-config-fallback_to_block` for more details
-- Possible values: "never" | "if_line_cms_wrapped"
fallback_to_block = "if_line_cms_wrapped",
-- Log level (nvim-0.13+). Ignored on older versions.
log_level = vim.log.levels.OFF,
-- Detect indent size and indent style (tabs vs spaces) from buffer content.
-- Does not modify any buffer options. See `:help celeste_comment-config-detect_indent`
-- for more details.
detect_indent = false,
-- Comment string configuration.
cms_confs = nil,
mappings = {
-- Line comment by motion (n)
line_toggle = "gc",
-- Line comment current line (n)
line_toggle_cur = "gcc",
-- Line comment visual selection (x)
line_toggle_visual = "gc",
-- Insert mode line toggle (i), example `{"<M-/>", "<M-_>"}`
line_toggle_insert = "",
-- Block comment by motion (n, x)
block_toggle = "gb",
-- Block comment current line (n)
block_toggle_cur = "gbc",
-- Block comment visual selection (x)
block_toggle_visual = "gb",
-- All textobjects below works without treesitter
-- NOTE: not works for end of line comment, like 'some code -- comment here'
-- Linewise textobject outer (o)
line_textobject = "gc",
-- Blockwise textobject outer (o)
block_textobject = "gb",
-- Auto textobject outer (o, x), example 'ac'
auto_textobject = "",
-- Auto textobject inner (o, x), example 'ic'
auto_textobject_inner = "",
-- Auto uncomment (n), example `gcu`
uncomment_auto = "",
-- Insert comment below (n), example `gco`
line_add_below = "",
-- Insert comment above (n), example `gcO`
line_add_above = "",
-- Insert comment at end of line (n), example `gcA`
line_add_eol = "",
-- Invert comment per line (n, x), example `gcI`
line_invert = "",
-- Force add line comment (n, x), example `gCC`
line_force_add = "",
-- Force remove line comment (n, x), example `gCU`
line_force_remove = "",
},
hooks = {
-- Called before commit edits
pre_commit_edits = nil,
-- Called after commit edits
post_commit_edits = nil,
-- Custom comment string resolver function
cms_conf_resolver = nil,
},
}
See :help celeste_comment-configuration for details.
[!TIP] Recommend set
vim.o.commentstring = ""andvim.o.comments = ""
[!TIP] If a language has built-in support for option
commentstringandcomments(e.g.vim,asm). you don't have to define anything here, we can fully fall back to Neovim's built-incommentstringandcommentsresolutionThis plugin already has built-in block comment support for most common languages.
If some filetype isn't included, you can use
cms_confs:-- for example, `lang` should be the Tree-sitter parser name or filetype require("celeste_comment").setup({ cms_confs = { ["lang"] = { "//%s", "/*%s*/" }, }, })Or, you can use options
comments(:help 'comments') to specify block comment string, for example, put this code:vim.cmd([[setlocal comments=s1:/*,ex:*/]])in your
after/ftplugin/<filetype>.lua. we can retrieve the block comment string from optioncomments.And also you can use options
commentstring(:help 'commentstring') to specify line comment string, for example, put this code:vim.cmd([[setlocal commentstring=//\%s]])in your
after/ftplugin/<filetype>.lua.For advanced comment string resolution, see
:help celeste_comment.
If you like this plugin, give it a ⭐!
Ambiguous comment syntax — Languages where line and block comments
share the same prefix (e.g., Lua's -- / --[[ ]]) may cause
textobject_auto() to misidentify block comments as line comments.
Use line_textobject or block_textobject explicitly instead.
Textobject limitations
char *s = "// not a comment";).block_textobj_nlines (default 200 lines).Visual block mode (<C-v>) — Comments are applied per-line,
not per-column. For column-wise commenting, use multicursor.
VSCode — The indent algorithm is ported from VSCode's comment implementation. Most of its test cases have also been ported to this plugin's test suite. This plugin is highly inspired by it.
Zed — The capture-based overrides paradigm for comment scope resolution.
mini.comment — Its code style and linewise textobjects implementation served as a reference for this plugin's development.
Comment.nvim — Part of the built-in language comment string table was adapted from Comment.nvim.