All Projects โ†’ numToStr โ†’ Comment.nvim

numToStr / Comment.nvim

Licence: MIT License
๐Ÿง  ๐Ÿ’ช // Smart and powerful comment plugin for neovim. Supports treesitter, dot repeat, left-right/up-down motions, hooks, and more

Programming Languages

lua
6591 projects

Projects that are alternatives of or similar to Comment.nvim

neogen
A better annotation generator. Supports multiple languages and annotation conventions.
Stars: โœญ 339 (-57.41%)
Mutual labels:  neovim, nvim, comment, neovim-plugin, neovim-lua
awesome-neovim
Awesome Configurations for C/C++,Zig,Web and Lua development in NeoVim
Stars: โœญ 54 (-93.22%)
Mutual labels:  nvim, neovim-plugin, neovim-lua, treesitter
comment-box.nvim
โœจ Clarify and beautify your comments using boxes and lines.
Stars: โœญ 91 (-88.57%)
Mutual labels:  nvim, comment, neovim-plugin, commenting
nvim context vt
Virtual text context for neovim treesitter
Stars: โœญ 193 (-75.75%)
Mutual labels:  neovim, neovim-plugin, treesitter
Iron.nvim
Interactive Repl Over Neovim
Stars: โœญ 265 (-66.71%)
Mutual labels:  neovim, nvim, neovim-plugin
Packer.nvim
A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
Stars: โœญ 418 (-47.49%)
Mutual labels:  neovim, nvim, neovim-plugin
nvim-ghost.nvim
๐Ÿ‘ป GhostText plugin for Neovim with zero dependencies ๐ŸŽ‰ Supports neovim running inside WSL too! ๐Ÿฅณ Windows/Linux/macOS supported out-of-the-box! ๐Ÿ˜„ (Other OSes need python3.6+ installed)
Stars: โœญ 32 (-95.98%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Hlslens
Hlsearch Lens for Neovim
Stars: โœญ 55 (-93.09%)
Mutual labels:  neovim, nvim, neovim-plugin
Chadtree
File manager for Neovim. Better than NERDTree.
Stars: โœญ 653 (-17.96%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Bqf
Better quickfix window in Neovim, polish old quickfix window.
Stars: โœญ 120 (-84.92%)
Mutual labels:  neovim, nvim, neovim-plugin
Lsp Status.nvim
Utility functions for getting diagnostic status and progress messages from LSP servers, for use in the Neovim statusline
Stars: โœญ 201 (-74.75%)
Mutual labels:  neovim, nvim, neovim-plugin
Lualine.nvim
A blazing fast and easy to configure neovim statusline written in pure lua.
Stars: โœญ 198 (-75.13%)
Mutual labels:  neovim, nvim, neovim-plugin
modes.nvim
Prismatic line decorations for the adventurous vim user
Stars: โœญ 299 (-62.44%)
Mutual labels:  nvim, neovim-plugin, neovim-lua
agitator.nvim
No description or website provided.
Stars: โœญ 16 (-97.99%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Compe
Auto completion plugin for nvim that written in Lua.
Stars: โœญ 433 (-45.6%)
Mutual labels:  neovim, nvim, neovim-plugin
boo-colorscheme-nvim
Boo is a colorscheme for Neovim with handcrafted support for LSP, Treesitter.
Stars: โœญ 62 (-92.21%)
Mutual labels:  neovim, neovim-plugin, treesitter
Semshi
๐ŸŒˆ Semantic Highlighting for Python in Neovim
Stars: โœญ 758 (-4.77%)
Mutual labels:  neovim, nvim, neovim-plugin
close-buffers.nvim
๐Ÿ“‘ Delete multiple vim buffers based on different conditions
Stars: โœญ 54 (-93.22%)
Mutual labels:  neovim, nvim, neovim-plugin
zephyr-nvim
A dark neovim colorscheme written in lua
Stars: โœญ 196 (-75.38%)
Mutual labels:  neovim, treesitter, nvim-treesitter
Acid.nvim
Asynchronous Clojure Interactive Development
Stars: โœญ 147 (-81.53%)
Mutual labels:  neovim, nvim, neovim-plugin

// Comment.nvim

โšก Smart and Powerful commenting plugin for neovim โšก

Comment.nvim

โœจ Features

  • Supports treesitter. Read more
  • Supports commentstring. Read more
  • Prefers single-line/linewise comments
  • Supports line (//) and block (/* */) comments
  • Dot (.) repeat support for gcc, gbc and friends
  • Count support for [count]gcc and [count]gbc
  • Left-right (gcw gc$) and Up-Down (gc2j gc4k) motions
  • Use with text-objects (gci{ gbat)
  • Supports pre and post hooks
  • Ignore certain lines, powered by Lua regex

๐Ÿš€ Installation

use {
    'numToStr/Comment.nvim',
    config = function()
        require('Comment').setup()
    end
}
Plug 'numToStr/Comment.nvim'

" Somewhere after plug#end()
lua require('Comment').setup()

โš’๏ธ Setup

First you need to call the setup() method to create the default mappings.

  • Lua
require('Comment').setup()
  • VimL
lua << EOF
require('Comment').setup()
EOF

Configuration (optional)

Following are the default config for the setup(). If you want to override, just modify the option that you want then it will be merged with the default config.

{
    ---Add a space b/w comment and the line
    ---@type boolean|fun():boolean
    padding = true,

    ---Whether the cursor should stay at its position
    ---NOTE: This only affects NORMAL mode mappings and doesn't work with dot-repeat
    ---@type boolean
    sticky = true,

    ---Lines to be ignored while comment/uncomment.
    ---Could be a regex string or a function that returns a regex string.
    ---Example: Use '^$' to ignore empty lines
    ---@type string|fun():string
    ignore = nil,

    ---LHS of toggle mappings in NORMAL + VISUAL mode
    ---@type table
    toggler = {
        ---Line-comment toggle keymap
        line = 'gcc',
        ---Block-comment toggle keymap
        block = 'gbc',
    },

    ---LHS of operator-pending mappings in NORMAL + VISUAL mode
    ---@type table
    opleader = {
        ---Line-comment keymap
        line = 'gc',
        ---Block-comment keymap
        block = 'gb',
    },

    ---LHS of extra mappings
    ---@type table
    extra = {
        ---Add comment on the line above
        above = 'gcO',
        ---Add comment on the line below
        below = 'gco',
        ---Add comment at the end of line
        eol = 'gcA',
    },

    ---Create basic (operator-pending) and extended mappings for NORMAL + VISUAL mode
    ---@type table
    mappings = {
        ---Operator-pending mapping
        ---Includes `gcc`, `gbc`, `gc[count]{motion}` and `gb[count]{motion}`
        ---NOTE: These mappings can be changed individually by `opleader` and `toggler` config
        basic = true,
        ---Extra mapping
        ---Includes `gco`, `gcO`, `gcA`
        extra = true,
        ---Extended mapping
        ---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
        extended = false,
    },

    ---Pre-hook, called before commenting the line
    ---@type fun(ctx: Ctx):string
    pre_hook = nil,

    ---Post-hook, called after commenting is done
    ---@type fun(ctx: Ctx)
    post_hook = nil,
}

๐Ÿ”ฅ Usage

When you call setup() method, Comment.nvim sets up some basic mapping which can used in NORMAL and VISUAL mode to get you started with the pleasure of commenting stuff out.

Basic mappings

These mappings are enabled by default. (config: mappings.basic)

  • NORMAL mode
`gcc` - Toggles the current line using linewise comment
`gbc` - Toggles the current line using blockwise comment
`[count]gcc` - Toggles the number of line given as a prefix-count using linewise
`[count]gbc` - Toggles the number of line given as a prefix-count using blockwise
`gc[count]{motion}` - (Op-pending) Toggles the region using linewise comment
`gb[count]{motion}` - (Op-pending) Toggles the region using blockwise comment
  • VISUAL mode
`gc` - Toggles the region using linewise comment
`gb` - Toggles the region using blockwise comment

Extra mappings

These mappings are enabled by default. (config: mappings.extra)

  • NORMAL mode
`gco` - Insert comment to the next line and enters INSERT mode
`gcO` - Insert comment to the previous line and enters INSERT mode
`gcA` - Insert comment to end of the current line and enters INSERT mode

Extended mappings

These mappings are disabled by default. (config: mappings.extended)

  • NORMAL mode
`g>[count]{motion}` - (Op-pending) Comments the region using linewise comment
`g>c` - Comments the current line using linewise comment
`g>b` - Comments the current line using blockwise comment
`g<[count]{motion}` - (Op-pending) Uncomments the region using linewise comment
`g<c` - Uncomments the current line using linewise comment
`g<b`- Uncomments the current line using blockwise comment
  • VISUAL mode
`g>` - Comments the region using single line
`g<` - Unomments the region using single line
Examples
# Linewise

`gcw` - Toggle from the current cursor position to the next word
`gc$` - Toggle from the current cursor position to the end of line
`gc}` - Toggle until the next blank line
`gc5j` - Toggle 5 lines after the current cursor position
`gc8k` - Toggle 8 lines before the current cursor position
`gcip` - Toggle inside of paragraph
`gca}` - Toggle around curly brackets

# Blockwise

`gb2}` - Toggle until the 2 next blank line
`gbaf` - Toggle comment around a function (w/ LSP/treesitter support)
`gbac` - Toggle comment around a class (w/ LSP/treesitter support)

โš™๏ธ API

Read doc/API.md to see all the API/functions that are exported from the plugin.

๐ŸŒณ Treesitter

This plugin has native treesitter support for calculating commentstring which works for multiple (injected/embedded) languages like Vue or Markdown. But due to the nature of the parsed tree, this implementation has some known limitations.

  1. No jsx/tsx support. Its implementation was quite complicated.
  2. Invalid comment on the region where one language ends and the other starts. Read more

For advance use cases, use nvim-ts-context-commentstring. See pre_hook section for the integration.

๐ŸŽฃ Hooks

There are two hook methods i.e pre_hook and post_hook which are called before comment and after comment respectively. Both should be provided during setup().

  • pre_hook - This method is called with a ctx argument before comment/uncomment is started. It can be used to return a custom commentstring which will be used for comment/uncomment the lines. You can use something like nvim-ts-context-commentstring to compute the commentstring using treesitter.
-- NOTE: The example below is a proper integration and it is RECOMMENDED.
{
    ---@param ctx Ctx
    pre_hook = function(ctx)
        -- Only calculate commentstring for tsx filetypes
        if vim.bo.filetype == 'typescriptreact' then
            local U = require('Comment.utils')

            -- Detemine whether to use linewise or blockwise commentstring
            local type = ctx.ctype == U.ctype.line and '__default' or '__multiline'

            -- Determine the location where to calculate commentstring from
            local location = nil
            if ctx.ctype == U.ctype.block then
                location = require('ts_context_commentstring.utils').get_cursor_location()
            elseif ctx.cmotion == U.cmotion.v or ctx.cmotion == U.cmotion.V then
                location = require('ts_context_commentstring.utils').get_visual_start_location()
            end

            return require('ts_context_commentstring.internal').calculate_commentstring({
                key = type,
                location = location,
            })
        end
    end,
}

  • post_hook - This method is called after commenting is done. It receives the same ctx argument as pre_hook.
{
    ---@param ctx Ctx
    post_hook = function(ctx)
        if ctx.range.srow == ctx.range.erow then
            -- do something with the current line
        else
            -- do something with lines range
        end
    end
}

The post_hook can be implemented to cover some niche use cases like the following:

  • Using newlines instead of padding e.g. for commenting out code in C with #if 0. See an example here.
  • Duplicating the commented block (using pre_hook) and moving the cursor to the next block (using post_hook). See this.

NOTE: When pressing gc, gb and friends, cmode (Comment mode) inside pre_hook will always be toggle because when pre-hook is called, in that moment we don't know whether gc or gb will comment or uncomment the lines. But luckily, we do know this before post_hook and this will always receive either comment or uncomment status

๐Ÿšซ Ignoring lines

You can use ignore to ignore certain lines during comment/uncomment. It can takes lua regex string or a function that returns a regex string and should be provided during setup().

NOTE: Ignore only works when with linewise comment. This is by design. As ignoring lines in block comments doesn't make that much sense.

  • With string
-- ignores empty lines
ignore = '^$'

-- ignores line that starts with `local` (excluding any leading whitespace)
ignore = '^(%s*)local'

-- ignores any lines similar to arrow function
ignore = '^const(.*)=(%s?)%((.*)%)(%s?)=>'
  • With function
{
    ignore = function()
        -- Only ignore empty lines for lua files
        if vim.bo.filetype == 'lua' then
            return '^$'
        end
    end,
}

๐Ÿ—จ๏ธ Filetypes + Languages

Most languages/filetypes have native support for comments via commentstring but there might be a filetype that is not supported. There are two ways to enable commenting for unsupported filetypes:

  1. You can set commentstring for that particular filetype like the following
vim.bo.commentstring = '//%s'

-- or
vim.api.nvim_command('set commentstring=//%s')

Run :h commentstring for more help

  1. You can also use this plugin interface to store both line and block commentstring for the filetype. You can treat this as a more powerful version of the commentstring
local ft = require('Comment.ft')

-- 1. Using set function

-- Just set only line comment
ft.set('yaml', '#%s')

-- Or set both line and block commentstring
-- You can also chain the set calls
ft.set('javascript', {'//%s', '/*%s*/'}).set('conf', '#%s')

-- 2. Metatable magic

-- One filetype at a time
ft.javascript = {'//%s', '/*%s*/'}
ft.yaml = '#%s'

-- Multiple filetypes
ft({'go', 'rust'}, {'//%s', '/*%s*/'})
ft({'toml', 'graphql'}, '#%s')

-- 3. Get the whole set of commentstring
ft.lang('lua') -- { '--%s', '--[[%s]]' }
ft.lang('javascript') -- { '//%s', '/*%s*/' }

PR(s) are welcome to add more commentstring inside the plugin

๐Ÿงต Comment String

Although, Comment.nvim supports neovim's commentstring but unfortunately it has the least priority. The commentstring is taken from the following place in the respective order.

  • pre_hook - If a string is returned from this method then it will be used for commenting.

  • ft_table - If the current filetype is found in the table, then the string there will be used.

  • commentstring - Neovim's native commentstring for the filetype

There is one caveat with this approach. If someone sets the commentstring (w/o returning a string) from the pre_hook method and if the current filetype also exists in the ft_table then the commenting will be done using the string in ft_table instead of using commentstring

๐Ÿง  Comment Context

The following object is provided as an argument to pre_hook and post_hook functions.

I am just placing it here just for documentation purpose

---Comment context
---@class Ctx
---@field ctype CType
---@field cmode CMode
---@field cmotion CMotion
---@field range CRange

---Range of the selection that needs to be commented
---@class CRange
---@field srow number Starting row
---@field scol number Starting column
---@field erow number Ending row
---@field ecol number Ending column

CType (Comment type), CMode (Comment mode) and CMotion (Comment motion) all of them are exported from the plugin's utils for reuse

require('Comment.utils').ctype.{line,block}

require('Comment.utils').cmode.{toggle,comment,uncomment}

require('Comment.utils').cmotion.{line,char,v,V}

๐Ÿค Contributing

There are multiple ways to contribute reporting/fixing bugs, feature requests. You can also submit commentstring to this plugin by updating ft.lua and sending PR.

๐Ÿ“บ Videos

๐Ÿ’ Credits

  • tcomment - To be with me forever and motivated me to write this.
  • nvim-comment - Little and less powerful cousin. Also I took some code from it.
  • kommentary - Nicely done plugin but lacks some features. But it helped me to design this plugin.

๐Ÿš— Roadmap

  • Doc comment i.e /**%s*/ (js), ///%s (rust)
  • Header comment
----------------------
-- This is a header --
----------------------
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].