From 089b972acca731ac943dfbc454c39003468d7e11 Mon Sep 17 00:00:00 2001
From: numToStr <24727447+numToStr@users.noreply.github.com>
Date: Fri, 19 Aug 2022 16:10:35 +0530
Subject: [PATCH] feat: help docs `:h comment-nvim` (#205)
Finally! We now have proper help docs for everything from keybindings to Lua API. It's auto generated from emmylua annotation so it would always be up to date.
Credits to https://github.com/phaazon/hop.nvim for excellent docs and reference.
---
.github/workflows/ci.yaml | 1 -
.gitignore | 3 +
README.md | 136 ++----
doc/API.md | 228 +---------
doc/Comment.txt | 874 ++++++++++++++++++++++++++++++++++++++
doc/plugs.md | 35 +-
dump.lua | 56 ---
lua/Comment/api.lua | 207 ++++++---
lua/Comment/config.lua | 123 ++++--
lua/Comment/extra.lua | 9 +-
lua/Comment/ft.lua | 78 +++-
lua/Comment/init.lua | 87 +++-
lua/Comment/opfunc.lua | 113 ++---
lua/Comment/utils.lua | 10 +-
plugin/Comment.lua | 85 ++++
15 files changed, 1449 insertions(+), 596 deletions(-)
create mode 100644 doc/Comment.txt
delete mode 100644 dump.lua
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 31900b2..0870cfc 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -6,7 +6,6 @@ on:
- "**.lua"
branches:
- master
- - docs
env:
PLUGIN_NAME: Comment
diff --git a/.gitignore b/.gitignore
index 2deeee7..8aa6b8d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,6 @@ luac.out
tmp
scratch
+
+# ignore generated doc tags
+doc/tags
diff --git a/README.md b/README.md
index 7e47fb9..3f2d052 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
### โจ Features
- Supports treesitter. [Read more](#treesitter)
-- Supports `commentstring`. [Read more](#commentstring)
+- Supports `commentstring`. Read `:h comment.commentstring`
- Supports line (`//`) and block (`/* */`) comments
- Dot (`.`) repeat support for `gcc`, `gbc` and friends
- Count support for `[count]gcc` and `[count]gbc`
@@ -37,6 +37,10 @@ Plug 'numToStr/Comment.nvim'
lua require('Comment').setup()
```
+### ๐ Getting Help
+
+`Comment.nvim` provides help docs which can be accessed by running `:help comment-nvim`
+
### โ๏ธ Setup
@@ -63,46 +67,31 @@ EOF
#### Configuration (optional)
-Following are the **default** config for the [`setup()`](#setup). If you want to override, just modify the option that you want then it will be merged with the default config.
+Following are the **default** config for the [`setup()`](#setup). If you want to override, just modify the option that you want then it will be merged with the default config. Read `:h comment.config` for more info.
```lua
{
---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
+ ---Lines to be ignored while (un)comment
ignore = nil,
-
---LHS of toggle mappings in NORMAL mode
- ---@type table
toggler = {
---Line-comment toggle keymap
line = 'gcc',
---Block-comment toggle keymap
block = 'gbc',
},
-
- ---LHS of operator-pending mappings in NORMAL mode
- ---LHS of mapping in VISUAL mode
- ---@type table
+ ---LHS of operator-pending mappings in NORMAL and VISUAL mode
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',
@@ -111,29 +100,19 @@ Following are the **default** config for the [`setup()`](#setup). If you want to
---Add comment at the end of line
eol = 'gcA',
},
-
- ---Create basic (operator-pending) and extended mappings for NORMAL + VISUAL mode
- ---NOTE: If `mappings = false` then the plugin won't create any mappings
- ---@type boolean|table
+ ---Enable keybindings
+ ---NOTE: If given `false` then the plugin won't create any mappings
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
+ ---Operator-pending mapping; `gcc` `gbc` `gc[count]{motion}` `gb[count]{motion}`
basic = true,
- ---Extra mapping
- ---Includes `gco`, `gcO`, `gcA`
+ ---Extra mapping; `gco`, `gcO`, `gcA`
extra = true,
- ---Extended mapping
- ---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
+ ---Extended mapping; `g>` `g<` `g>[count]{motion}` `g<[count]{motion}`
extended = false,
},
-
- ---Pre-hook, called before commenting the line
- ---@type fun(ctx: CommentCtx):string
+ ---Function to call before (un)comment
pre_hook = nil,
-
- ---Post-hook, called after commenting is done
- ---@type fun(ctx: CommentCtx)
+ ---Function to call after (un)comment
post_hook = nil,
}
```
@@ -224,14 +203,6 @@ These mappings are disabled by default. (config: `mappings.extended`)
`gbac` - Toggle comment around a class (w/ LSP/treesitter support)
```
-
-
-### โ๏ธ API
-
-- [Plug Mappings](./doc/plugs.md) - Excellent for creating custom keybindings
-
-- [Lua API](./doc/API.md) - Details the Lua API. Great for making custom comment function.
-
### ๐ณ Treesitter
@@ -254,12 +225,10 @@ There are two hook methods i.e `pre_hook` and `post_hook` which are called befor
-- `pre_hook` - This method is called with a [`ctx`](#comment-context) 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](https://github.com/JoosepAlviste/nvim-ts-context-commentstring) to compute the commentstring using treesitter.
+- `pre_hook` - Called with a `ctx` argument (Read `:h comment.utils.CommentCtx`) before (un)comment. Can optionally return a `commentstring` to be used for (un)commenting. You can use [nvim-ts-context-commentstring](https://github.com/JoosepAlviste/nvim-ts-context-commentstring) to easily comment `tsx/jsx` files.
```lua
--- NOTE: The example below is a proper integration and it is RECOMMENDED.
{
- ---@param ctx CommentCtx
pre_hook = function(ctx)
-- Only calculate commentstring for tsx filetypes
if vim.bo.filetype == 'typescriptreact' then
@@ -285,13 +254,14 @@ There are two hook methods i.e `pre_hook` and `post_hook` which are called befor
}
```
+> **Note** - `Comment.nvim` already supports [`treesitter`](#treesitter) out-of-the-box except for `tsx/jsx`.
+
-- `post_hook` - This method is called after commenting is done. It receives the same [`ctx`](#comment-context) argument as [`pre_hook`](#pre_hook).
+- `post_hook` - This method is called after (un)commenting. It receives the same `ctx` (Read `:h comment.utils.CommentCtx`) argument as [`pre_hook`](#pre_hook).
```lua
{
- ---@param ctx CommentCtx
post_hook = function(ctx)
if ctx.range.srow == ctx.range.erow then
-- do something with the current line
@@ -347,7 +317,7 @@ ignore = '^const(.*)=(%s?)%((.*)%)(%s?)=>'
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
+1. You can set `commentstring` for that particular filetype like the following. Read `:h commentstring` for more info.
```lua
vim.bo.commentstring = '//%s'
@@ -356,27 +326,23 @@ vim.bo.commentstring = '//%s'
vim.api.nvim_command('set commentstring=//%s')
```
-> Run `:h commentstring` for more help
-
-2. 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`
+2. 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`. Read `:h comment.ft` for more info.
```lua
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')
+ft
+ -- Set only line comment
+ .set('yaml', '#%s')
+ -- Or set both line and block commentstring
+ .set('javascript', {'//%s', '/*%s*/'})
-- 2. Metatable magic
--- One filetype at a time
ft.javascript = {'//%s', '/*%s*/'}
ft.yaml = '#%s'
@@ -391,56 +357,6 @@ 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`](#hooks) - If a string is returned from this method then it will be used for commenting.
-
-- [`ft.lua`](#ft-lua) - 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
-
-```lua
----Comment context
----@class CommentCtx
----@field ctype CommentType
----@field cmode CommentMode
----@field cmotion CommentMotion
----@field range CommentRange
-
----Range of the selection that needs to be commented
----@class CommentRange
----@field srow integer Starting row
----@field scol integer Starting column
----@field erow integer Ending row
----@field ecol integer Ending column
-```
-
-`CommentType`, `CommentMode` and `CommentMotion` all of them are exported from the plugin's utils for reuse
-
-```lua
-require('Comment.utils').ctype.{linewise,blockwise}
-
-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](./lua/Comment/ft.lua) and sending PR.
diff --git a/doc/API.md b/doc/API.md
index a547063..ecc574f 100644
--- a/doc/API.md
+++ b/doc/API.md
@@ -1,227 +1 @@
-# โ๏ธ API
-
-Following are list of APIs that are exported from the plugin. These can be used to setup [custom keybinding](#usage) or to make your own custom comment function. All API functions can take a `{motion}` (Read `:h :map-operator`) and a optional [`{cfg}`](../README.md#config) argument which can be used to override the [default configuration](../README.md#config)
-
-
-Deprecated API
-
-```lua
----@alias OpMode 'line'|'char'|'v'|'V' Vim operator-mode motions. Read `:h map-operator`
-```
-
-### Core
-
-These APIs powers the [basic-mappings](../README.md#basic-mappings).
-
-```lua
---######### LINEWISE #########--
-
----Toggle linewise-comment on the current line
----@param cfg? CommentConfig
-require('Comment.api').toggle_current_linewise(cfg)
-
----(Operator-Pending) Toggle linewise-comment on the current line
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').toggle_current_linewise_op(opmode, cfg)
-
----(Operator-Pending) Toggle linewise-comment over multiple lines
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').toggle_linewise_op(opmode, cfg)
-
----Toggle linewise-comment over multiple lines using `vim.v.count`
----@param cfg? CommentConfig
-require('Comment.api').toggle_linewise_count(cfg)
-
---######### BLOCKWISE #########--
-
----Toggle blockwise comment on the current line
----@param cfg? CommentConfig
-require('Comment.api').toggle_current_blockwise(cfg)
-
----(Operator-Pending) Toggle blockwise comment on the current line
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').toggle_current_blockwise_op(opmode, cfg)
-
----(Operator-Pending) Toggle blockwise-comment over multiple lines
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').toggle_blockwise_op(opmode, cfg)
-
----Toggle blockwise-comment over multiple lines using `vim.v.count`
----@param cfg? CommentConfig
-require('Comment.api').toggle_blockwise_count(cfg)
-```
-
-### Extra
-
-These APIs powers the [extra-mappings](../README.md#extra-mappings) and also provides the blockwise version.
-
-```lua
---######### LINEWISE #########--
-
----Insert a linewise-comment below
----@param cfg? CommentConfig
-require('Comment.api').insert_linewise_below(cfg)
-
----Insert a linewise-comment above
----@param cfg? CommentConfig
-require('Comment.api').insert_linewise_above(cfg)
-
----Insert a linewise-comment at the end-of-line
----@param cfg? CommentConfig
-require('Comment.api').insert_linewise_eol(cfg)
-
---######### BLOCKWISE #########--
-
----Insert a blockwise-comment below
----@param cfg? CommentConfig
-require('Comment.api').insert_blockwise_below(cfg)
-
----Insert a blockwise-comment above
----@param cfg? CommentConfig
-require('Comment.api').insert_blockwise_above(cfg)
-
----Insert a blockwise-comment at the end-of-line
----@param cfg? CommentConfig
-require('Comment.api').insert_blockwise_eol(cfg)
-```
-
-### Extended
-
-These APIs powers the [extended-mappings](../README.md#extended-mappings).
-
-```lua
---######### LINEWISE #########--
-
----Comment current line using linewise-comment
----@param cfg? CommentConfig
-require('Comment.api').comment_current_linewise(cfg)
-
----(Operator-Pending) Comment current line using linewise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').comment_current_linewise_op(opmode, cfg)
-
----(Operator-Pending) Comment multiple line using linewise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').comment_linewise_op(opmode, cfg)
-
----Uncomment current line using linewise-comment
----@param cfg? CommentConfig
-require('Comment.api').uncomment_current_linewise(cfg)
-
----(Operator-Pending) Uncomment current line using linewise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').uncomment_current_linewise_op(opmode, cfg)
-
----(Operator-Pending) Uncomment multiple line using linewise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').uncomment_linewise_op(opmode, cfg)
-
---######### BLOCKWISE #########--
-
----Comment current line using linewise-comment
----@param cfg? CommentConfig
-require('Comment.api').comment_current_blockwise(cfg)
-
----(Operator-Pending) Comment current line using blockwise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').comment_current_blockwise_op(opmode, cfg)
-
----Uncomment current line using blockwise-comment
----@param cfg? CommentConfig
-require('Comment.api').uncomment_current_blockwise(cfg)
-
----(Operator-Pending) Uncomment current line using blockwise-comment
----@param opmode OpMode
----@param cfg? CommentConfig
-require('Comment.api').uncomment_current_blockwise_op(opmode, cfg)
-```
-
-
-
-### Core
-
-> **NOTE**:
->
-> 1. All API functions are dot-repeatable except `*.count()`
-> 2. For the `*.current()` functions, `{motion}` argument is optional
-> 3. `{cfg}` is optional for all the API functions
-
-```lua
-require('Comment.api').toggle.linewise(motion, cfg)
-require('Comment.api').toggle.linewise.current(motion, cfg)
-require('Comment.api').toggle.linewise.count(count, cfg)
-
-require('Comment.api').toggle.blockwise(motion, cfg)
-require('Comment.api').toggle.blockwise.current(motion, cfg)
-require('Comment.api').toggle.blockwise.count(count, cfg)
-
-require('Comment.api').comment.linewise(motion, cfg)
-require('Comment.api').comment.linewise.current(motion, cfg)
-require('Comment.api').comment.linewise.count(count, cfg)
-
-require('Comment.api').comment.blockwise(motion, cfg)
-require('Comment.api').comment.blockwise.current(motion, cfg)
-require('Comment.api').comment.blockwise.count(count, cfg)
-
-require('Comment.api').uncomment.linewise(motion, cfg)
-require('Comment.api').uncomment.linewise.current(motion, cfg)
-require('Comment.api').uncomment.linewise.count(count, cfg)
-
-require('Comment.api').uncomment.blockwise(motion, cfg)
-require('Comment.api').uncomment.blockwise.current(motion, cfg)
-require('Comment.api').uncomment.blockwise.count(count, cfg)
-```
-
-### Additional
-
-```lua
----Callback function to provide dot-repeat support
----NOTE: VISUAL mode mapping doesn't support dot-repeat
----@param cb string Name of the API function to call
-require('Comment.api').call(cb)
-```
-
-
-
-# โ๏ธ Usage
-
-Following are some example keybindings using the APIs.
-
-```lua
--- # NORMAL mode
-
--- Linewise toggle current line using C-/
-vim.keymap.set('n', '', 'lua require("Comment.api").toggle.linewise.current()')
--- or with dot-repeat support
--- vim.keymap.set('n', '', 'lua require("Comment.api").call("toggle.linewise.current")g@$')
-
--- Blockwise toggle current line using C-\
-vim.keymap.set('n', '', 'lua require("Comment.api").toggle.blockwise.current()')
--- or with dot-repeat support
--- vim.keymap.set('n', '', 'lua require("Comment.api").call("toggle.blockwise.current")g@$')
-
--- Linewise toggle multiple line using gc with dot-repeat support
--- Example: gc3j will comment 4 lines
-vim.keymap.set('n', 'gc', 'lua require("Comment.api").call("toggle.linewise")g@')
-
--- Blockwise toggle multiple line using gc with dot-repeat support
--- Example: gb3j will comment 4 lines
-vim.keymap.set('n', 'gb', 'lua require("Comment.api").call("toggle.blockwise")g@')
-
--- # VISUAL mode
-
--- Linewise toggle using C-/
-vim.keymap.set('x', '', 'lua require("Comment.api").toggle.linewise(vim.fn.visualmode())')
-
--- Blockwise toggle using gb
-vim.keymap.set('x', 'gb', 'lua require("Comment.api").toggle.blockwise(vim.fn.visualmode())')
-```
+`Comment.nvim` now has `:help` docs ๐. Read `:h comment.api` for the Lua API documentation and usage.
diff --git a/doc/Comment.txt b/doc/Comment.txt
new file mode 100644
index 0000000..8d303af
--- /dev/null
+++ b/doc/Comment.txt
@@ -0,0 +1,874 @@
+*comment-nvim.txt* For Neovim version 0.7 Last change: 2021 July 11
+
+ _____ _ _
+ / ____/ / / (_)
+ / / ___ _ __ ___ _ __ ___ ___ _ __ / /_ _ ____ ___ _ __ ___
+ / / / _ \/ '_ ` _ \/ '_ ` _ \ / _ \ '_ \/ __/ / '_ \ \ / / / '_ ` _ \
+ / /___/ (_) / / / / / / / / / / / __/ / / / /_ _/ / / \ V // / / / / / /
+ \_____\___//_/ /_/ /_/_/ /_/ /_/\___/_/ /_/\__(_)_/ /_/\_/ /_/_/ /_/ /_/
+
+ ยท Smart and Powerful comment plugin ยท
+
+
+================================================================================
+Table of Contents *comment.contents*
+
+Introductionยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment-nvim|
+Usageยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.usage|
+Configurationยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.config|
+Keybindingsยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.keybindings|
+Plug Mappingsยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.plugmap|
+Core Lua APIยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.api|
+Language/Filetype detectionยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.ft|
+Utilitiesยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.utils|
+Operator-mode APIยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.opfunc|
+Insert APIยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|comment.extra|
+
+================================================================================
+Introduction *comment-nvim*
+
+Comment.nvim is a smart and powerful comment plugin for neovim. It supports
+dot-repeat, counts, line ('//') and block ('/* */') comments, and can be used
+with motion and text-objects. It has native integration with tressitter to
+support embedded filetypes like html, vue, markdown with codeblocks etc.
+
+ *comment.dotrepeat*
+Comment.nvim uses |operatorfunc| combined with |g@| to support dot-repeat, and
+various marks i.e., |'[| |']| |'<| |'>| to deduce the region with the {motion}
+argument provided by 'operatorfunc'. See |comment.api.call|
+
+ *comment.commentstring*
+Comment.nvim picks commentstring, either linewise/blockwise, from one of the
+following places
+
+ 1. 'pre_hook'
+ If a string is returned from this function then it will be used for
+ (un)commenting. See |comment.config|
+
+ 2. |comment.ft|
+ Using the commentstring table inside the plugin (using treesitter).
+ Fallback to |commentstring|, if not found.
+
+ 3. |commentstring| - Neovim's native commentstring for the filetype
+
+Although Comment.nvim supports native 'commentstring' but unfortunately it has
+the least priority. The caveat with this approach is that if someone sets the
+`commentstring`, without returning it, from the 'pre_hook' and the current
+filetype also exists in the |comment.ft| then the commenting will be done using
+the string in |comment.ft| instead of using 'commentstring'. To override this
+behavior, you have to manually return the 'commentstring' from 'pre_hook'.
+
+================================================================================
+Usage *comment.usage*
+
+Before using the plugin, you need to call the `setup()` function to create the
+default mappings. If you want, you can also override the default configuration
+by giving it a partial 'comment.config.Config' object, it will then be merged
+with the default config.
+
+C.setup({config?}) *comment.usage.setup*
+ Configures the plugin
+
+ Parameters: ~
+ {config?} (CommentConfig) User configuration
+
+ Returns: ~
+ {CommentConfig} Returns the mutated config
+
+ See: ~
+ |comment.config|
+
+ Usage: ~
+ >
+ require('Comment').setup({
+ ignore = '^$',
+ toggler = {
+ line = 'cc',
+ block = 'bc',
+ },
+ opleader = {
+ line = 'c',
+ block = 'b',
+ },
+ })
+ <
+
+
+================================================================================
+Configuration *comment.config*
+
+CommentConfig *comment.config.CommentConfig*
+ Plugin's configuration
+
+ Fields: ~
+ {padding} (boolean) Controls space between the comment
+ and the line (default: 'true')
+ {sticky} (boolean) Whether cursor should stay at the
+ same position. Only works with NORMAL
+ mode mappings (default: 'true')
+ {ignore} (string|fun():string) Lua pattern used to ignore lines
+ during (un)comment (default: 'nil')
+ {mappings} (Mappings|boolean)
+ {toggler} (Toggler)
+ {opleader} (Opleader)
+ {extra} (ExtraMapping)
+ {pre_hook} (fun(ctx):string) Function to call before (un)comment
+ (default: 'nil')
+ {post_hook} (fun(ctx)) Function to call after (un)comment
+ (default: 'nil')
+
+
+Mappings *comment.config.Mappings*
+ Create default mappings
+
+ Fields: ~
+ {basic} (boolean) Enables operator-pending mapping; `gcc`, `gbc`,
+ `gc{motion}` and `gb{motion}` (default: 'true')
+ {extra} (boolean) Enable extra mapping; `gco`, `gcO` and `gcA`
+ (default: 'true')
+ {extended} (boolean) Enable extended mapping; `g>`, `g{motion}` and `g<{motion}`
+ (default: 'false')
+
+
+Toggler *comment.config.Toggler*
+ LHS of toggle mappings in NORMAL
+
+ Fields: ~
+ {line} (string) Linewise comment (default: 'gcc')
+ {block} (string) Blockwise comment (default: 'gbc')
+
+
+Opleader *comment.config.Opleader*
+ LHS of operator-mode mappings in NORMAL and VISUAL mode
+
+ Fields: ~
+ {line} (string) Linewise comment (default: 'gc')
+ {block} (string) Blockwise comment (default: 'gb')
+
+
+ExtraMapping *comment.config.ExtraMapping*
+ LHS of extra mappings
+
+ Fields: ~
+ {below} (string) Inserts comment below (default: 'gco')
+ {above} (string) Inserts comment above (default: 'gcO')
+ {eol} (string) Inserts comment at the end of line (default: 'gcA')
+
+
+Config:get() *comment.config:get*
+ Get the config
+
+ Returns: ~
+ {CommentConfig}
+
+ Usage: ~
+ >
+ require('Comment.config'):get()
+ <
+
+
+================================================================================
+Keybindings *comment.keybindings*
+
+Comment.nvim provides default keybinds which is used for (un)comment your code.
+These keybinds are enabled upon calling |commen.usage.setup| and can be
+configured or disabled, if desired.
+
+Basic: ~
+
+ *gc*
+ *gb*
+ *gc[count]{motion}*
+ *gb[count]{motion}*
+
+ Toggle comment on a region using linewise/blockwise comment. In 'NORMAL'
+ mode, it uses 'Operator-Pending' mode to listen for an operator/motion.
+ In 'VISUAL' mode it simply comment the selected region.
+
+ *gcc*
+ *gbc*
+ *[count]gcc*
+ *[count]gbc*
+
+ Toggle comment on the current line using linewise/blockwise comment. If
+ prefixed with a 'v:count' then it will comment over the number of lines
+ corresponding to the {count}. These are only available in 'NORMAL' mode.
+
+
+Extra: ~
+
+ *gco* - Inserts comment below and enters INSERT mode
+ *gcO* - Inserts comment above and enters INSERT mode
+ *gcA* - Inserts comment at the end of line and enters INSERT mode
+
+================================================================================
+Plug Mappings *comment.plugmap*
+
+Comment.nvim provides mappings for most commonly used actions. These
+can be used to make custom keybindings and are enabled by default. All plug
+mappings has support for dot-repeat except VISUAL mode keybindings. To create
+custom comment function, check out 'comment.api' section.
+
+ *(comment_toggle_linewise)*
+ *(comment_toggle_blockwise)*
+
+ Toggle comment on a region with linewise/blockwise comment in NORMAL mode.
+ using |Operator-Pending| mode (or |g@|) to get the region to comment.
+ These powers the |gc| and |gb| keybindings.
+
+ *(comment_toggle_linewise_current)*
+ *(comment_toggle_blockwise_current)*
+
+ Toggle comment on the current line with linewise/blockwise comment in
+ NORMAL mode. These powers the |gcc| and 'gbc' keybindings.
+
+ *(comment_toggle_linewise_count)*
+ *(comment_toggle_blockwise_count)*
+
+ Toggle comment on a region using 'v:count' with linewise/blockwise comment
+ in NORMAL mode. These powers the |[count]gcc| and |[count]gbc| keybindings.
+
+ *(comment_toggle_linewise_visual)*
+ *(comment_toggle_blockwise_visual)*
+
+ Toggle comment on the selected region with linewise/blockwise comment in
+ NORMAL mode. These powers the |{visual}gc| and |{visual}gb| keybindings.
+
+Usage: ~
+
+>
+ -- Toggle current line or with count
+ vim.keymap.set('n', 'gcc', function()
+ return vim.v.count == 0
+ and '(comment_toggle_linewise_current)'
+ or '(comment_toggle_linewise_count)'
+ end, { expr = true })
+
+ -- Toggle in Op-pending mode
+ vim.keymap.set('n', 'gc', '(comment_toggle_linewise)')
+
+ -- Toggle in VISUAL mode
+ vim.keymap.set('x', 'gc', '(comment_toggle_linewise_visual)')
+<
+
+================================================================================
+Core Lua API *comment.api*
+
+This module provides the core lua APIs which is used by the default keybindings
+and (Read |comment.plugmap|) mappings. These API can be used to setup your
+own custom keybindings or to even make your (un)comment function.
+
+ *comment.api.toggle.linewise*
+ *comment.api.toggle.blockwise*
+api.toggle *comment.api.toggle*
+ Provides API to toggle comments over a region, on current-line, or with a
+ count using line or block comment string.
+
+ All functions takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+
+ api.toggle.linewise(motion, config)
+ api.toggle.linewise.current(motion?, config?)
+ api.toggle.linewise.count(count, config?)
+
+ api.toggle.blockwise(motion, config?)
+ api.toggle.blockwise.current(motion?, config?)
+ api.toggle.blockwise.count(count, config?)
+
+ -- NORMAL mode
+
+ -- Toggle current line (linewise) using C-/
+ vim.keymap.set('n', '', api.toggle.linewise.current)
+
+ -- Toggle current line (blockwise) using C-\
+ vim.keymap.set('n', '', api.toggle.blockwise.current)
+
+ -- Toggle lines (linewise) with dot-repeat support
+ -- Example: gc3j will comment 4 lines
+ vim.keymap.set(
+ 'n', 'gc', api.call('toggle.linewise', 'g@'),
+ { expr = true }
+ )
+
+ -- Toggle lines (blockwise) with dot-repeat support
+ -- Example: gb3j will comment 4 lines
+ vim.keymap.set(
+ 'n', 'gb', api.call('toggle.blockwise', 'g@'),
+ { expr = true }
+ )
+
+ -- VISUAL mode
+
+ local esc = vim.api.nvim_replace_termcodes(
+ '', true, false, true
+ )
+
+ -- Linewise toggle (linewise)
+ vim.keymap.set('x', 'c', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.toggle.linewise(vim.fn.visualmode())
+ end)
+
+ -- Blockwise toggle (blockwise)
+ vim.keymap.set('x', 'b', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.toggle.blockwise(vim.fn.visualmode())
+ end)
+ <
+
+
+ *comment.api.comment.linewise*
+ *comment.api.comment.blockwise*
+api.comment *comment.api.comment*
+ Provides API to (only) comment a region, on current-line, or with a
+ count using line or block comment string.
+
+ All functions takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+
+ api.comment.linewise(motion, config)
+ api.comment.linewise.current(motion?, config?)
+ api.comment.linewise.count(count, config?)
+
+ api.comment.blockwise(motion, config?)
+ api.comment.blockwise.current(motion?, config?)
+ api.comment.blockwise.count(count, config?)
+ <
+
+
+ *comment.api.uncomment.linewise*
+ *comment.api.uncomment.blockwise*
+api.uncomment *comment.api.uncomment*
+ Provides API to (only) uncomment a region, on current-line, or with a
+ count using line or block comment string.
+
+ All functions takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+
+ api.uncomment.linewise(motion, config)
+ api.uncomment.linewise.current(motion?, config?)
+ api.uncomment.linewise.count(count, config?)
+
+ api.uncomment.blockwise(motion, config?)
+ api.uncomment.blockwise.current(motion?, config?)
+ api.uncomment.blockwise.count(count, config?)
+ <
+
+
+api.insert *comment.api.insert*
+ Provides API to to insert comment on previous, next or at the end-of-line.
+ All functions takes an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.config|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+
+ api.insert.linewise.above(cfg?)
+ api.insert.linewise.below(cfg?)
+ api.insert.linewise.eol(cfg?)
+
+ api.insert.blockwise.above(cfg?)
+ api.insert.blockwise.below(cfg?)
+ api.insert.blockwise.eol(cfg?)
+ <
+
+
+api.locked *comment.api.locked*
+ Wraps the given API function with 'lockmarks' to preserve marks/jumps
+
+ Type: ~
+ (fun(cb:string):fun(motion:OpMotion))
+
+ See: ~
+ |lockmarks|
+ |comment.opfunc.OpMotion|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+
+ vim.keymap.set(
+ 'n', 'c', api.locked('toggle.linewise.current')
+ )
+
+ local esc = vim.api.nvim_replace_termcodes(
+ '', true, false, true
+ )
+ vim.keymap.set('x', 'c', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.locked('toggle.linewise')(vim.fn.visualmode())
+ end)
+
+ -- NOTE: `locked` method is just a wrapper around `lockmarks`
+ vim.api.nvim_command([[
+ lockmarks lua require('Comment.api').toggle.linewise.current()
+ ]])
+ <
+
+
+api.call({cb}, {op}) *comment.api.call*
+ Callback function which does the following
+ 1. Sets 'operatorfunc' for dot-repeat
+ 2. Preserves jumps and marks
+ 3. Stores last cursor position
+
+ Parameters: ~
+ {cb} (string) Name of the API function to call
+ {op} ('g@'|'g@$') Operator string to execute
+
+ Returns: ~
+ {fun():string} Keymap RHS callback
+
+ See: ~
+ |g@|
+ |operatorfunc|
+
+ Usage: ~
+ >
+ local api = require('Comment.api')
+ vim.keymap.set(
+ 'n', 'gc', api.call('toggle.linewise', 'g@'),
+ { expr = true }
+ )
+ vim.keymap.set(
+ 'n', 'gcc', api.call('toggle.linewise.current', 'g@$'),
+ { expr = true }
+ )
+ <
+
+
+================================================================================
+Language/Filetype detection *comment.ft*
+
+ft.set({lang}, {val}) *comment.ft.set*
+ Sets a commentstring(s) for a filetype/language
+
+ Parameters: ~
+ {lang} (string) Filetype/Language of the buffer
+ {val} (string|string[])
+
+ Returns: ~
+ {table} Returns itself
+
+ Usage: ~
+ >
+ local ft = require('Comment.ft')
+
+ --1. Using method signature
+ -- Set only line comment or both
+ -- You can also chain the set calls
+ ft.set('yaml', '#%s').set('javascript', {'//%s', '/*%s*/'})
+
+ -- 2. Metatable magic
+ ft.javascript = {'//%s', '/*%s*/'}
+ ft.yaml = '#%s'
+
+ -- 3. Multiple filetypes
+ ft({'go', 'rust'}, {'//%s', '/*%s*/'})
+ ft({'toml', 'graphql'}, '#%s')
+ <
+
+
+ft.get({lang}, {ctype}) *comment.ft.get*
+ Get line/block commentstring for a given filetype
+
+ Parameters: ~
+ {lang} (string) Filetype/Language of the buffer
+ {ctype} (integer) See |comment.utils.ctype|
+
+ Returns: ~
+ {string} Commentstring
+
+ Usage: ~
+ >
+ local ft = require('Comment.ft')
+ local U = require('Comment.utils')
+ print(ft.get(vim.bo.filetype, U.ctype.linewise))
+ <
+
+
+ft.lang({lang}) *comment.ft.lang*
+ Get a copy of commentstring(s) for a given filetype
+
+ Parameters: ~
+ {lang} (string) Filetype/Language of the buffer
+
+ Returns: ~
+ {string[]} Tuple of { line, block } commentstring
+
+ Usage: ~
+ >
+ require('Comment.ft').lang(vim.bo.filetype)
+ <
+
+
+ft.contains({tree}, {range}) *comment.ft.contains*
+ Get a language tree for a given range by walking the parse tree recursively.
+ This uses 'lua-treesitter' API under the hood. This can be used to calculate
+ language of a particular region which embedded multiple filetypes like html,
+ vue, markdown etc.
+
+ NOTE: This ignores `tree-sitter-comment` parser, if installed.
+
+ Parameters: ~
+ {tree} (userdata) Parse tree to be walked
+ {range} (integer[]) Range to check for
+ {start_row, start_col, end_row, end_col}
+
+ Returns: ~
+ {userdata} Returns a |treesitter-languagetree|
+
+ See: ~
+ |treesitter-languagetree|
+ |lua-treesitter-core|
+
+ Usage: ~
+ >
+ local ok, parser = pcall(vim.treesitter.get_parser, 0)
+ assert(ok, "No parser found!")
+ local tree = require('Comment.ft').contains(parser, {0, 0, -1, 0})
+ print('Lang:', tree:lang())
+ <
+
+
+ft.calculate({ctx}) *comment.ft.calculate*
+ Calculate commentstring with the power of treesitter
+
+ Parameters: ~
+ {ctx} (CommentCtx)
+
+ Returns: ~
+ {string} Commentstring
+
+ See: ~
+ |comment.utils.CommentCtx|
+
+
+================================================================================
+Utilities *comment.utils*
+
+CommentCtx *comment.utils.CommentCtx*
+ Comment context
+
+ Fields: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cmode} (integer) See |comment.utils.cmode|
+ {cmotion} (integer) See |comment.utils.cmotion|
+ {range} (CommentRange)
+
+
+CommentRange *comment.utils.CommentRange*
+ Range of the selection that needs to be commented
+
+ Fields: ~
+ {srow} (integer) Starting row
+ {scol} (integer) Starting column
+ {erow} (integer) Ending row
+ {ecol} (integer) Ending column
+
+
+CommentMode *comment.utils.CommentMode*
+ Comment modes - Can be manual or computed via operator-mode
+
+ Fields: ~
+ {toggle} (integer) Toggle action
+ {comment} (integer) Comment action
+ {uncomment} (integer) Uncomment action
+
+
+U.cmode *comment.utils.cmode*
+ An object containing comment modes
+
+ Type: ~
+ (CommentMode)
+
+
+CommentType *comment.utils.CommentType*
+ Comment types
+
+ Fields: ~
+ {linewise} (integer) Use linewise commentstring
+ {blockwise} (integer) Use blockwise commentstring
+
+
+U.ctype *comment.utils.ctype*
+ An object containing comment types
+
+ Type: ~
+ (CommentType)
+
+
+CommentMotion *comment.utils.CommentMotion*
+ Comment motion types
+
+ Fields: ~
+ {line} (integer) Line motion (ie. 'gc2j')
+ {char} (integer) Character/left-right motion (ie. 'gc2w')
+ {block} (integer) Visual operator-pending motion
+ {v} (integer) Visual motion (ie. 'v3jgc')
+ {V} (integer) Visual-line motion (ie. 'V10kgc')
+
+
+U.cmotion *comment.utils.cmotion*
+ An object containing comment motions
+
+ Type: ~
+ (CommentMotion)
+
+
+U.get_region({opmode?}) *comment.utils.get_region*
+ Get region for line movement or visual selection
+ NOTE: Returns the current line region, if `opmode` is not given.
+
+ Parameters: ~
+ {opmode?} (OpMotion)
+
+ Returns: ~
+ {CommentRange}
+
+
+U.get_count_lines({count}) *comment.utils.get_count_lines*
+ Get lines from the current position to the given count
+
+ Parameters: ~
+ {count} (integer) Probably 'vim.v.count'
+
+ Returns: ~
+ {string[]} of lines
+ {CommentRange}
+
+
+U.get_lines({range}) *comment.utils.get_lines*
+ Get lines from a NORMAL/VISUAL mode
+
+ Parameters: ~
+ {range} (CommentRange)
+
+ Returns: ~
+ {string[]} of lines
+
+
+U.unwrap_cstr({cstr}) *comment.utils.unwrap_cstr*
+ Validates and unwraps the given commentstring
+
+ Parameters: ~
+ {cstr} (string) See 'commentstring'
+
+ Returns: ~
+ {string} Left side of the commentstring
+ {string} Right side of the commentstring
+
+
+U.parse_cstr({cfg}, {ctx}) *comment.utils.parse_cstr*
+ Parses commentstring from the following places in the respective order
+ 1. pre_hook - commentstring returned from the function
+ 2. ft.lua - commentstring table bundled with the plugin
+ 3. commentstring - Neovim's native. See 'commentstring'
+
+ Parameters: ~
+ {cfg} (CommentConfig)
+ {ctx} (CommentCtx)
+
+ Returns: ~
+ {string} Left side of the commentstring
+ {string} Right side of the commentstring
+
+
+ *comment.utils.commenter*
+U.commenter({left}, {right}, {padding}, {scol?}, {ecol?})
+ Returns a closure which is used to do comments
+
+ If given {string[]} to the closure then it will do blockwise comment
+ else linewise comment will be done with the given {string}
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+
+ Returns: ~
+ {fun(line:string|string[]):string}
+
+
+ *comment.utils.uncommenter*
+U.uncommenter({left}, {right}, {padding}, {scol?}, {ecol?})
+ Returns a closure which is used to uncomment a line
+
+ If given {string[]} to the closure then it will block uncomment
+ else linewise uncomment will be done with the given {string}
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+
+ Returns: ~
+ {fun(line:string|string[]):string}
+
+
+ *comment.utils.is_commented*
+U.is_commented({left}, {right}, {padding}, {scol?}, {ecol?})
+ Check if the given string is commented or not
+
+ If given {string[]} to the closure, it will check the first and last line
+ with LHS and RHS of commentstring respectively else it will check the given
+ line with LHS and RHS (if given) of the commenstring
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+
+ Returns: ~
+ {fun(line:string|string[]):boolean}
+
+
+================================================================================
+Operator-mode API *comment.opfunc*
+
+Underlying functions that powers the |comment.api.toggle|, |comment.api.comment|,
+and |comment.api.uncomment| lua API.
+
+OpMotion *comment.opfunc.OpMotion*
+ Vim operator-mode motion enum. Read |:map-operator|
+
+ Variants: ~
+ ('line') Vertical motion
+ ('char') Horizontal motion
+ ('v') Visual Block motion
+ ('V') Visual Line motion
+
+
+ *comment.opfunc.opfunc*
+Op.opfunc({motion?}, {cfg}, {cmode}, {ctype})
+ Common operatorfunc callback
+ This function contains the core logic for comment/uncomment
+
+ Parameters: ~
+ {motion?} (OpMotion) If given 'nil', it'll only (un)comment
+ the current line
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {ctype} (integer) See |comment.utils.ctype|
+
+
+ *comment.opfunc.count*
+Op.count({count}, {cfg}, {cmode}, {ctype})
+ Line commenting with count
+
+ Parameters: ~
+ {count} (integer) Value of |v:count|
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {ctype} (integer) See |comment.utils.ctype|
+
+
+OpFnParams *comment.opfunc.OpFnParams*
+ Operator-mode function parameters
+
+ Fields: ~
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {lines} (string[]) List of lines
+ {rcs} (string) RHS of commentstring
+ {lcs} (string) LHS of commentstring
+ {range} (CommentRange)
+
+
+Op.linewise({param}) *comment.opfunc.linewise*
+ Line commenting
+
+ Parameters: ~
+ {param} (OpFnParams)
+
+ Returns: ~
+ {integer} Returns a calculated comment mode
+
+
+Op.blockwise({param}, {partial?}) *comment.opfunc.blockwise*
+ Full/Partial/Current-Line Block commenting
+
+ Parameters: ~
+ {param} (OpFnParams)
+ {partial?} (boolean) Comment the partial region (visual mode)
+
+ Returns: ~
+ {integer} Returns a calculated comment mode
+
+
+================================================================================
+Insert API *comment.extra*
+
+Underlying functions that powers the |comment.api.insert| lua API.
+
+extra.insert_below({ctype}, {cfg}) *comment.extra.insert_below*
+ Add a comment below the current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+extra.insert_above({ctype}, {cfg}) *comment.extra.insert_above*
+ Add a comment above the current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+extra.insert_eol({ctype}, {cfg}) *comment.extra.insert_eol*
+ Add a comment at the end of current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/doc/plugs.md b/doc/plugs.md
index 11622d7..b1fdf31 100644
--- a/doc/plugs.md
+++ b/doc/plugs.md
@@ -1,34 +1 @@
-## ๐ Plug Mappings
-
-Following are the `` mappings which you can use to quickly setup your custom keybindings
-
-- `(comment_toggle_linewise)` - Toggles line comment via Operator pending mode
-- `(comment_toggle_blockwise)` - Toggles block comment via Operator pending mode
-- `(comment_toggle_linewise_current)` - Toggles line comment on the current line
-- `(comment_toggle_blockwise_current)` - Toggles block comment on the current line
-- `(comment_toggle_linewise_count)` - Toggles line comment with count
-- `(comment_toggle_blockwise_count)` - Toggles block comment with count
-- `(comment_toggle_linewise_visual)` - Toggles line comment in VISUAL mode
-- `(comment_toggle_blockwise_visual)` - Toggles block comment in VISUAL mode
-
-> NOTE: There are only meant for custom keybindings but If you want to create a custom comment function then be sure to check out all the [API](./API.md).
-
-#### Usage
-
-Following snippets is same as the default mappings set by the plugin.
-
-```lua
-local opt = { expr = true, remap = true, replace_keycodes = false }
-
--- Toggle using count
-vim.keymap.set('n', 'gcc', "v:count == 0 ? '(comment_toggle_linewise_current)' : '(comment_toggle_linewise_count)'", opt)
-vim.keymap.set('n', 'gbc', "v:count == 0 ? '(comment_toggle_blockwise_current)' : '(comment_toggle_blockwise_count)'", opt)
-
--- Toggle in Op-pending mode
-vim.keymap.set('n', 'gc', '(comment_toggle_linewise)')
-vim.keymap.set('n', 'gb', '(comment_toggle_blockwise)')
-
--- Toggle in VISUAL mode
-vim.keymap.set('x', 'gc', '(comment_toggle_linewise_visual)')
-vim.keymap.set('x', 'gb', '(comment_toggle_blockwise_visual)')
-```
+`Comment.nvim` now has `:help` docs ๐. Read `:h comment.plugmap` for the `` mappings documentation and usage.
diff --git a/dump.lua b/dump.lua
deleted file mode 100644
index 832c703..0000000
--- a/dump.lua
+++ /dev/null
@@ -1,56 +0,0 @@
--- TODO
--- [x] Handle Tabs
--- [x] Dot repeat
--- [x] Comment multiple line.
--- [x] Hook support
--- [x] pre
--- [x] post
--- [x] Custom (language) commentstring support
--- [x] Block comment basic ie. /* */ (for js)
--- [-] Block comment extended
--- [x] left-right-motions
--- [x] Partial blocks ie. gba{ gbaf
--- [ ] V-BLOCK (IDK, maybe)
--- [ ] Char motion covering mutliple lines ie. gc300w (level: HARD)
--- [-] Treesitter Integration
--- [ ] Better comment detection
--- [x] Context commentstring
--- [x] Port `commentstring` from tcomment
--- [x] Ignore line
--- [x] Disable `extra` mapping by default
--- [x] Provide more arguments to pre and post hooks
--- [x] `ignore` as a function
--- [x] Return the operator's starting and ending position in pre and post hook
--- [x] Restore cursor position in some motion operator (try `gcip`)
--- [ ] Doc comment ie. /** */ (for js)
--- [ ] Header comment
-
--- FIXME
--- [x] visual mode not working correctly
--- [x] space after and before of commentstring
--- [x] multiple line behavior to tcomment
--- [x] preserve indent
--- [x] determine comment status (to comment or not)
--- [x] prevent uncomment on uncommented line
--- [x] `comment` and `toggle` misbehaving when there is leading space
--- [x] messed up indentation, if the first line has greater indentation than next line (calc min indendation)
--- [x] `gcc` empty line not toggling comment
--- [x] Optimize blockwise mode (just modifiy the start and end line)
--- [x] Weird commenting when the first line is empty and the whole is indented
--- [x] no padding support in block-x
-
--- THINK:
--- [ ] Dot support for `[count]gcc` and `[count]gbc`
--- [ ] Parse `comments` if block comment is missing in the plugin
-
--- ITS_OK:
--- 1. Weird comments, if you do comments on already commented lines incl. an extra empty line
--- 2. Conflict when uncommenting interchangebly with line/block wise comment
--- 3. `ignore` doesn't work in blockwise and blockwise_x
--- 4. When a empty line is b/w two commented blocks then it should uncomment instead of commenting again in toggle.
-
--- DROPPED:
--- 1. Insert mode mapping (also move the cursor after commentstring)
--- 2. Use `nvim_buf_get_text` instead of `nvim_buf_get_lines`. Blocked by https://github.com/neovim/neovim/pull/15181
--- 3. Use `nvim_buf_set_text` instead of `nvim_buf_set_lines`
--- 4. Dot repeat support for visual mode mappings (Doesn't make sense)
diff --git a/lua/Comment/api.lua b/lua/Comment/api.lua
index 7b9cdfe..d9b75c9 100644
--- a/lua/Comment/api.lua
+++ b/lua/Comment/api.lua
@@ -1,4 +1,9 @@
----@mod comment.api API functions
+---@mod comment.api Core Lua API
+---@brief [[
+---This module provides the core lua APIs which is used by the default keybindings
+---and (Read |comment.plugmap|) mappings. These API can be used to setup your
+---own custom keybindings or to even make your (un)comment function.
+---@brief ]]
local Config = require('Comment.config')
local U = require('Comment.utils')
@@ -281,7 +286,7 @@ function core.__index(that, ctype)
---To comment lines with a count
function idxd.count(count, cfg)
- Op.count(Config.count or count, cfg or Config:get(), U.ctype[ctype])
+ Op.count(Config.count or count, cfg or Config:get(), that.cmode, U.ctype[ctype])
end
---@private
@@ -299,60 +304,126 @@ function core.__index(that, ctype)
})
end
----API to toggle comments using line or block comment string
+---@tag comment.api.toggle.linewise
+---@tag comment.api.toggle.blockwise
+---Provides API to toggle comments over a region, on current-line, or with a
+---count using line or block comment string.
---
----Following are the API functions that are available:
----
----require('Comment.api').toggle.linewise({motion}, {cfg?})
----require('Comment.api').toggle.linewise.current({motion?}, {cfg?})
----require('Comment.api').toggle.linewise.count({count}, {cfg?})
----
----require('Comment.api').toggle.blockwise({motion}, {cfg?})
----require('Comment.api').toggle.blockwise.current({motion?}, {cfg?})
----require('Comment.api').toggle.blockwise.count({count}, {cfg?})
+---All functions takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
---@type table A metatable containing API functions
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---
+---api.toggle.linewise(motion, config)
+---api.toggle.linewise.current(motion?, config?)
+---api.toggle.linewise.count(count, config?)
+---
+---api.toggle.blockwise(motion, config?)
+---api.toggle.blockwise.current(motion?, config?)
+---api.toggle.blockwise.count(count, config?)
+---
+----- Toggle current line (linewise) using C-/
+---vim.keymap.set('n', '', api.toggle.linewise.current)
+---
+----- Toggle current line (blockwise) using C-\
+---vim.keymap.set('n', '', api.toggle.blockwise.current)
+---
+----- Toggle lines (linewise) with dot-repeat support
+----- Example: gc3j will comment 4 lines
+---vim.keymap.set(
+--- 'n', 'gc', api.call('toggle.linewise', 'g@'),
+--- { expr = true }
+---)
+---
+----- Toggle lines (blockwise) with dot-repeat support
+----- Example: gb3j will comment 4 lines
+---vim.keymap.set(
+--- 'n', 'gb', api.call('toggle.blockwise', 'g@'),
+--- { expr = true }
+---)
+---
+---local esc = vim.api.nvim_replace_termcodes(
+--- '', true, false, true
+---)
+---
+----- Toggle selection (linewise)
+---vim.keymap.set('x', 'c', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.toggle.linewise(vim.fn.visualmode())
+---end)
+---
+----- Toggle selection (blockwise)
+---vim.keymap.set('x', 'b', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.toggle.blockwise(vim.fn.visualmode())
+---end)
+---@usage ]]
api.toggle = setmetatable({ cmode = U.cmode.toggle }, core)
----API to (only) comment using line or block comment string
+---@tag comment.api.comment.linewise
+---@tag comment.api.comment.blockwise
+---Provides API to (only) comment a region, on current-line, or with a
+---count using line or block comment string.
---
----Following are the API functions that are available:
----
----require('Comment.api').comment.linewise({motion}, {cfg?})
----require('Comment.api').comment.linewise.current({motion?}, {cfg?})
----require('Comment.api').comment.linewise.count({count}, {cfg?})
----
----require('Comment.api').comment.blockwise({motion}, {cfg?})
----require('Comment.api').comment.blockwise.current({motion?}, {cfg?})
----require('Comment.api').comment.blockwise.count({count}, {cfg?})
+---All functions takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
---@type table A metatable containing API functions
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---
+---api.comment.linewise(motion, config)
+---api.comment.linewise.current(motion?, config?)
+---api.comment.linewise.count(count, config?)
+---
+---api.comment.blockwise(motion, config?)
+---api.comment.blockwise.current(motion?, config?)
+---api.comment.blockwise.count(count, config?)
+---@usage ]]
api.comment = setmetatable({ cmode = U.cmode.comment }, core)
----API to (only) uncomment using line or block comment string
+---@tag comment.api.uncomment.linewise
+---@tag comment.api.uncomment.blockwise
+---Provides API to (only) uncomment a region, on current-line, or with a
+---count using line or block comment string.
---
----Following are the API functions that are available:
----
----require('Comment.api').uncomment.linewise({motion}, {cfg?})
----require('Comment.api').uncomment.linewise.current({motion?}, {cfg?})
----require('Comment.api').uncomment.linewise.count({count}, {cfg?})
----
----require('Comment.api').uncomment.blockwise({motion}, {cfg?})
----require('Comment.api').uncomment.blockwise.current({motion?}, {cfg?})
----require('Comment.api').uncomment.blockwise.count({count}, {cfg?})
+---All functions takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
---@type table A metatable containing API functions
-api.uncomment = setmetatable({ cmode = U.cmode.comment }, core)
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---
+---api.uncomment.linewise(motion, config)
+---api.uncomment.linewise.current(motion?, config?)
+---api.uncomment.linewise.count(count, config?)
+---
+---api.uncomment.blockwise(motion, config?)
+---api.uncomment.blockwise.current(motion?, config?)
+---api.uncomment.blockwise.count(count, config?)
+---@usage ]]
+api.uncomment = setmetatable({ cmode = U.cmode.uncomment }, core)
----API to insert comment on previous, next or at the end-of-line
----
----Following are the API functions that are available:
----
----require('Comment.api').insert.linewise.above({cfg?})
----require('Comment.api').insert.linewise.below({cfg?})
----require('Comment.api').insert.linewise.eol({cfg?})
----
----require('Comment.api').insert.blockwise.above({cfg?})
----require('Comment.api').insert.blockwise.below({cfg?})
----require('Comment.api').insert.blockwise.eol({cfg?})
+---Provides API to to insert comment on previous, next or at the end-of-line.
+---All functions takes an optional {config} parameter.
---@type table A metatable containing API functions
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---
+---api.insert.linewise.above(cfg?)
+---api.insert.linewise.below(cfg?)
+---api.insert.linewise.eol(cfg?)
+---
+---api.insert.blockwise.above(cfg?)
+---api.insert.blockwise.below(cfg?)
+---api.insert.blockwise.eol(cfg?)
+---@usage ]]
api.insert = setmetatable({}, {
__index = function(_, ctype)
return {
@@ -369,17 +440,41 @@ api.insert = setmetatable({}, {
end,
})
----Wraps a given function with `lockmarks` to preserve marks/jumps when commenting
+-- TODO: After removing old API
+-- 1. make `api.locked` a simple function call
+-- 2. fix emmylua doc
+
+---Wraps the given API function with 'lockmarks' to preserve marks/jumps
---@type fun(cb:string):fun(motion:OpMotion)
----@usage `require('Comment.api').locked('toggle.linewise.current')()`
+---@see lockmarks
+---@see comment.opfunc.OpMotion
+---@usage [[
+---local api = require('Comment.api')
+---
+---vim.keymap.set(
+--- 'n', 'c', api.locked('toggle.linewise.current')
+---)
+---
+---local esc = vim.api.nvim_replace_termcodes(
+--- '', true, false, true
+---)
+---vim.keymap.set('x', 'c', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.locked('toggle.linewise')(vim.fn.visualmode())
+---end)
+---
+----- NOTE: `locked` method is just a wrapper around `lockmarks`
+---vim.api.nvim_command([[
+--- lockmarks lua require('Comment.api').toggle.linewise.current()
+---]])
+---@usage ]]
api.locked = setmetatable({}, {
__index = function(this, cb)
D(string.format('locker.%s(args...)', cb), string.format('locked(%q)(args...)', cb))
return this(cb)
end,
- -- TODO: After removal of the old api functions, make `api.locked` a simple function call
__call = function(_, cb)
- ---Actual function which will be attached to operatorfunc
+ ---operatorfunc callback
---@param motion OpMotion
return function(motion)
return A.nvim_command(
@@ -390,13 +485,25 @@ api.locked = setmetatable({}, {
})
---Callback function which does the following
---- 1. Sets operatorfunc for dot-repeat
+--- 1. Sets 'operatorfunc' for dot-repeat
--- 2. Preserves jumps and marks
--- 3. Stores last cursor position
---@param cb string Name of the API function to call
---@param op 'g@'|'g@$' Operator string to execute
---@return fun():string _ Keymap RHS callback
----@usage `vim.keymap.set('n', 'gc', api.call('toggle.linewise', 'g@'), { expr = true })`
+---@see g@
+---@see operatorfunc
+---@usage [[
+---local api = require('Comment.api')
+---vim.keymap.set(
+--- 'n', 'gc', api.call('toggle.linewise', 'g@'),
+--- { expr = true }
+---)
+---vim.keymap.set(
+--- 'n', 'gcc', api.call('toggle.linewise.current', 'g@$'),
+--- { expr = true }
+---)
+---@usage ]]
function api.call(cb, op)
return function()
A.nvim_set_option('operatorfunc', ("v:lua.require'Comment.api'.locked'%s'"):format(cb))
diff --git a/lua/Comment/config.lua b/lua/Comment/config.lua
index fae4a16..775c894 100644
--- a/lua/Comment/config.lua
+++ b/lua/Comment/config.lua
@@ -1,45 +1,92 @@
---@mod comment.config Configuration
-
----@class Toggler LHS of toggle mappings in NORMAL + VISUAL mode
----@field line string Linewise comment keymap
----@field block string Blockwise comment keymap
-
----@class Opleader LHS of operator-mode mappings in NORMAL + VISUAL mode
----@field line string Linewise comment keymap
----@field block string Blockwise comment keymap
-
----@class ExtraMapping LHS of extra mappings
----@field above string Mapping to add comment on the line above
----@field below string Mapping to add comment on the line below
----@field eol string Mapping to add comment at the end of line
-
----@class Mappings Create default mappings
----Enable 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
----@field basic boolean
----Enable extra mapping
----Includes `gco`, `gcO`, `gcA`
----@field extra boolean
----Enable extended mapping
----Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
----@field extended boolean
+---@tag comment.config.defaults
+---@brief [[
+---Following is the default config for the |comment.usage.setup|. If you want to
+---override, just modify the option that you want, then it will be merged with the
+---default config.
+---
+--->
+--- {
+--- padding = true,
+--- sticky = true,
+--- ignore = nil,
+--- toggler = {
+--- line = 'gcc',
+--- block = 'gbc',
+--- },
+--- opleader = {
+--- line = 'gc',
+--- block = 'gb',
+--- },
+--- extra = {
+--- above = 'gcO',
+--- below = 'gco',
+--- eol = 'gcA',
+--- },
+--- mappings = {
+--- basic = true,
+--- extra = true,
+--- extended = false,
+--- },
+--- pre_hook = nil,
+--- post_hook = nil,
+--- }
+---<
+---@brief ]]
---@class CommentConfig Plugin's configuration
----@field padding boolean Add a space b/w comment and the line
----Whether the cursor should stay at its position
----NOTE: This only affects NORMAL mode mappings and doesn't work with dot-repeat
+---Controls space between the comment
+---and the line (default: 'true')
+---@field padding boolean|fun():boolean
+---Whether cursor should stay at the
+---same position. Only works in NORMAL
+---mode mappings (default: 'true')
---@field sticky boolean
----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
+---Lua pattern used to ignore lines
+---during (un)comment (default: 'nil')
---@field ignore string|fun():string
----@field mappings boolean|Mappings
+---Enables |comment.keybindings|
+---NOTE: If given 'false', then the
+---plugin won't create any mappings
+---@field mappings Mappings|false
---@field toggler Toggler
---@field opleader Opleader
---@field extra ExtraMapping
----@field pre_hook fun(ctx:CommentCtx):string Function to be called before comment/uncomment
----@field post_hook fun(ctx:CommentCtx) Function to be called after comment/uncomment
+---Function to call before (un)comment.
+---It is called with a {ctx} argument
+---of type |comment.utils.CommentCtx|
+---(default: 'nil')
+---@field pre_hook fun(ctx):string
+---Function to call after (un)comment.
+---It is called with a {ctx} argument
+---of type |comment.utils.CommentCtx|
+---(default: 'nil')
+---@field post_hook fun(ctx)
+
+---@class Mappings Create default mappings
+---Enables operator-pending mapping; `gcc`, `gbc`,
+---`gc{motion}` and `gb{motion}` (default: 'true')
+---@field basic boolean
+---Enable extra mapping; `gco`, `gcO` and `gcA`
+---(default: 'true')
+---@field extra boolean
+---Enable extended mapping; `g>`, `g{motion}` and `g<{motion}`
+---(default: 'false')
+---@field extended boolean
+
+---@class Toggler LHS of toggle mappings in NORMAL
+---@field line string Linewise comment (default: 'gcc')
+---@field block string Blockwise comment (default: 'gbc')
+
+---@class Opleader LHS of operator-mode mappings in NORMAL and VISUAL mode
+---@field line string Linewise comment (default: 'gc')
+---@field block string Blockwise comment (default: 'gb')
+
+---@class ExtraMapping LHS of extra mappings
+---@field below string Inserts comment below (default: 'gco')
+---@field above string Inserts comment above (default: 'gcO')
+---@field eol string Inserts comment at the end of line (default: 'gcA')
---@private
---@class RootConfig
@@ -72,9 +119,12 @@ local Config = {
},
}
----Update the config
+---@private
+---Updates the default config
---@param cfg? CommentConfig
---@return RootConfig
+---@see comment.usage.setup
+---@usage `require('Comment.config'):set({config})`
function Config:set(cfg)
if cfg then
self.config = vim.tbl_deep_extend('force', self.config, cfg)
@@ -84,11 +134,12 @@ end
---Get the config
---@return CommentConfig
+---@usage `require('Comment.config'):get()`
function Config:get()
return self.config
end
----@export ft
+---@export Config
return setmetatable(Config, {
__index = function(this, k)
return this.state[k]
diff --git a/lua/Comment/extra.lua b/lua/Comment/extra.lua
index 495394f..6c3dcc4 100644
--- a/lua/Comment/extra.lua
+++ b/lua/Comment/extra.lua
@@ -1,4 +1,7 @@
----@mod comment.extra Extra functions
+---@mod comment.extra Extra API
+---@brief [[
+---Underlying functions that powers the |comment.api.insert| lua API.
+---@brief ]]
local U = require('Comment.utils')
local A = vim.api
@@ -30,7 +33,7 @@ local function ins_on_line(lnum, ctype, cfg)
local srow = row + lnum
local lcs, rcs = U.parse_cstr(cfg, ctx)
- local padding = U.get_pad(cfg.padding)
+ local padding = U.get_pad(U.is_fn(cfg.padding))
-- We need RHS of cstr, if we are doing block comments or if RHS exists
-- because even in line comment RHS do exists for some filetypes like jsx_element, ocaml
@@ -73,7 +76,7 @@ function extra.insert_eol(ctype, cfg)
local lcs, rcs = U.parse_cstr(cfg, ctx)
local line = A.nvim_get_current_line()
- local padding = U.get_pad(cfg.padding)
+ local padding = U.get_pad(U.is_fn(cfg.padding))
-- We need RHS of cstr, if we are doing block comments or if RHS exists
-- because even in line comment RHS do exists for some filetypes like jsx_element, ocaml
diff --git a/lua/Comment/ft.lua b/lua/Comment/ft.lua
index 7d61da8..a2dd3cb 100644
--- a/lua/Comment/ft.lua
+++ b/lua/Comment/ft.lua
@@ -1,4 +1,9 @@
----@mod comment.ft Language or Filetype detection
+---@mod comment.ft Language/Filetype detection
+---@brief [[
+---This module is the core of filetype and commentstring detection and uses the
+---|lua-treesitter| APIs to accurately detect filetype and gives the corresponding
+---commentstring, stored inside the plugin, for the filetype/langauge.
+---@brief ]]
local A = vim.api
@@ -108,37 +113,71 @@ local L = {
local ft = {}
----@alias CommentLang string Filetype/Language of the buffer
-
---Sets a commentstring(s) for a filetype/language
----@param lang CommentLang
+---@param lang string Filetype/Language of the buffer
---@param val string|string[]
+---@return table self Returns itself
+---@usage [[
+---local ft = require('Comment.ft')
+---
+-----1. Using method signature
+----- Set only line comment or both
+----- You can also chain the set calls
+---ft.set('yaml', '#%s').set('javascript', {'//%s', '/*%s*/'})
+---
+----- 2. Metatable magic
+---ft.javascript = {'//%s', '/*%s*/'}
+---ft.yaml = '#%s'
+---
+----- 3. Multiple filetypes
+---ft({'go', 'rust'}, {'//%s', '/*%s*/'})
+---ft({'toml', 'graphql'}, '#%s')
+---@usage ]]
function ft.set(lang, val)
L[lang] = type(val) == 'string' and { val } or val --[[ @as string[] ]]
return ft
end
----Get a commentstring from the filtype list
----@param lang CommentLang
+---Get line/block commentstring for a given filetype
+---@param lang string Filetype/Language of the buffer
---@param ctype integer See |comment.utils.ctype|
----@return string
+---@return string _ Commentstring
+---@usage [[
+---local ft = require('Comment.ft')
+---local U = require('Comment.utils')
+---print(ft.get(vim.bo.filetype, U.ctype.linewise))
+---@usage ]]
function ft.get(lang, ctype)
- local l = ft.lang(lang)
+ local l = L[lang]
return l and l[ctype]
end
----Get the commentstring(s) from the filtype list
----@param lang CommentLang
----@return string[]
+---Get a copy of commentstring(s) for a given filetype
+---@param lang string Filetype/Language of the buffer
+---@return string[] _ Tuple of { line, block } commentstring
+---@usage `require('Comment.ft').lang(vim.bo.filetype)`
function ft.lang(lang)
- return L[lang]
+ return vim.deepcopy(L[lang])
end
----Get the tree in range by walking the whole tree recursively
----NOTE: This ignores `comment` parser as this is not needed
----@param tree userdata Tree to be walked
----@param range integer[] Range to check - {start_line, s_col, end_line, end_col}
----@return userdata _ Returns a 'treesitter-languagetree'
+---Get a language tree for a given range by walking the parse tree recursively.
+---This uses 'lua-treesitter' API under the hood. This can be used to calculate
+---language of a particular region which embedded multiple filetypes like html,
+---vue, markdown etc.
+---
+---NOTE: This ignores `tree-sitter-comment` parser, if installed.
+---@param tree userdata Parse tree to be walked
+---@param range integer[] Range to check for
+---{start_row, start_col, end_row, end_col}
+---@return userdata _ Returns a |treesitter-languagetree|
+---@see treesitter-languagetree
+---@see lua-treesitter-core
+---@usage [[
+---local ok, parser = pcall(vim.treesitter.get_parser, 0)
+---assert(ok, "No parser found!")
+---local tree = require('Comment.ft').contains(parser, {0, 0, -1, 0})
+---print('Lang:', tree:lang())
+---@usage ]]
function ft.contains(tree, range)
for lang, child in pairs(tree:children()) do
if lang ~= 'comment' and child:contains(range) then
@@ -149,9 +188,10 @@ function ft.contains(tree, range)
return tree
end
----Calculate commentstring w/ the power of treesitter
+---Calculate commentstring with the power of treesitter
---@param ctx CommentCtx
----@return string
+---@return string _ Commentstring
+---@see comment.utils.CommentCtx
function ft.calculate(ctx)
local buf = A.nvim_get_current_buf()
local ok, parser = pcall(vim.treesitter.get_parser, buf)
diff --git a/lua/Comment/init.lua b/lua/Comment/init.lua
index 21987f0..54a1146 100644
--- a/lua/Comment/init.lua
+++ b/lua/Comment/init.lua
@@ -1,10 +1,91 @@
----@mod comment.nvim Welcome to Comment.nvim
+---@brief [[
+---*comment-nvim.txt* For Neovim version 0.7 Last change: 2021 July 11
+---
+--- _____ _ _
+--- / ____/ / / (_)
+--- / / ___ _ __ ___ _ __ ___ ___ _ __ / /_ _ ____ ___ _ __ ___
+--- / / / _ \/ '_ ` _ \/ '_ ` _ \ / _ \ '_ \/ __/ / '_ \ \ / / / '_ ` _ \
+--- / /___/ (_) / / / / / / / / / / / __/ / / / /_ _/ / / \ V // / / / / / /
+--- \_____\___//_/ /_/ /_/_/ /_/ /_/\___/_/ /_/\__(_)_/ /_/\_/ /_/_/ /_/ /_/
+---
+--- ยท Smart and Powerful comment plugin ยท
+---
+---@brief ]]
+
+---@toc comment.contents
+
+---@mod comment-nvim Introduction
+---@brief [[
+---Comment.nvim is a smart and powerful comment plugin for neovim. It supports
+---dot-repeat, counts, line ('//') and block ('/* */') comments, and can be used
+---with motion and text-objects. It has native integration with |tressitter| to
+---support embedded filetypes like html, vue, markdown with codeblocks etc.
+---@brief ]]
+---@tag comment.dotrepeat
+---@brief [[
+---Comment.nvim uses |operatorfunc| combined with |g@| to support dot-repeat, and
+---various marks i.e., |'[| |']| |'<| |'>| to deduce the region with the {motion}
+---argument provided by 'operatorfunc'. See |comment.api.call|
+---@brief ]]
+---@tag comment.commentstring
+---@brief [[
+---Comment.nvim picks commentstring, either linewise/blockwise, from one of the
+---following places
+---
+--- 1. 'pre_hook'
+--- If a string is returned from this function then it will be used for
+--- (un)commenting. See |comment.config|
+---
+--- 2. |comment.ft|
+--- Using the commentstring table inside the plugin (using treesitter).
+--- Fallback to |commentstring|, if not found.
+---
+--- 3. |commentstring| - Neovim's native commentstring for the filetype
+---
+---Although Comment.nvim supports native 'commentstring' but unfortunately it has
+---the least priority. The caveat with this approach is that if someone sets the
+---`commentstring`, without returning it, from the 'pre_hook' and the current
+---filetype also exists in the |comment.ft| then the commenting will be done using
+---the string in |comment.ft| instead of using 'commentstring'. To override this
+---behavior, you have to manually return the 'commentstring' from 'pre_hook'.
+---@brief ]]
+---@tag comment.sourcecode
+---@brief [[
+---Comment.nvim is FOSS provided under MIT license. All the source code is avaiable
+---at https://github.com/numToStr/Comment.nvim
+---@brief ]]
+
+---@mod comment.usage Usage
+---@brief [[
+---Before using the plugin, you need to call the `setup()` function to create the
+---default mappings. If you want, you can also override the default configuration
+---by giving it a partial 'comment.config.Config' object, it will then be merged
+---with the default config.
+---@brief ]]
local C = {}
---Configures the plugin
----@param config? CommentConfig
----@return CommentConfig
+---@param config? CommentConfig User configuration
+---@return CommentConfig _ Returns the mutated config
+---@see comment.config
+---@usage [[
+----- Use default configuration
+---require('Comment').setup()
+---
+----- or with custom configuration
+---require('Comment').setup({
+--- ignore = '^$',
+--- toggler = {
+--- line = 'cc',
+--- block = 'bc',
+--- },
+--- opleader = {
+--- line = 'c',
+--- block = 'b',
+--- },
+---})
+---@usage ]]
function C.setup(config)
return require('Comment.api').setup(config)
end
diff --git a/lua/Comment/opfunc.lua b/lua/Comment/opfunc.lua
index 02d90f7..df94a71 100644
--- a/lua/Comment/opfunc.lua
+++ b/lua/Comment/opfunc.lua
@@ -1,4 +1,8 @@
----@mod comment.opfunc Operator-mode
+---@mod comment.opfunc Operator-mode API
+---@brief [[
+---Underlying functions that powers the |comment.api.toggle|, |comment.api.comment|,
+---and |comment.api.uncomment| lua API.
+---@brief ]]
local U = require('Comment.utils')
local Config = require('Comment.config')
@@ -6,31 +10,18 @@ local A = vim.api
local Op = {}
----Vim operator-mode motions.
----Read `:h :map-operator`
+---Vim operator-mode motion enum. Read |:map-operator|
---@alias OpMotion
---| 'line' # Vertical motion
---| 'char' # Horizontal motion
---| 'v' # Visual Block motion
---| 'V' # Visual Line motion
----@class CommentCtx Comment context
----@field ctype integer See |comment.utils.ctype|
----@field cmode integer See |comment.utils.cmode|
----@field cmotion integer See |comment.utils.cmotion|
----@field range CommentRange
-
----@class OpFnParams Operator-mode function parameters
----@field cfg CommentConfig
----@field cmode integer See |comment.utils.cmode|
----@field lines string[] List of lines
----@field rcs string RHS of commentstring
----@field lcs string LHS of commentstring
----@field range CommentRange
-
---Common operatorfunc callback
---This function contains the core logic for comment/uncomment
----@param motion? OpMotion If nil is given, it'll work on the current line
+---@param motion? OpMotion
+---If given 'nil', it'll only (un)comment
+---the current line
---@param cfg CommentConfig
---@param cmode integer See |comment.utils.cmode|
---@param ctype integer See |comment.utils.ctype|
@@ -90,6 +81,50 @@ function Op.opfunc(motion, cfg, cmode, ctype)
U.is_fn(cfg.post_hook, ctx)
end
+---Line commenting with count
+---@param count integer Value of |v:count|
+---@param cfg CommentConfig
+---@param cmode integer See |comment.utils.cmode|
+---@param ctype integer See |comment.utils.ctype|
+function Op.count(count, cfg, cmode, ctype)
+ local lines, range = U.get_count_lines(count)
+
+ ---@type CommentCtx
+ local ctx = {
+ cmode = cmode,
+ cmotion = U.cmotion.line,
+ ctype = ctype,
+ range = range,
+ }
+ local lcs, rcs = U.parse_cstr(cfg, ctx)
+
+ ---@type OpFnParams
+ local params = {
+ cfg = cfg,
+ cmode = ctx.cmode,
+ lines = lines,
+ lcs = lcs,
+ rcs = rcs,
+ range = range,
+ }
+
+ if ctype == U.ctype.blockwise then
+ ctx.cmode = Op.blockwise(params)
+ else
+ ctx.cmode = Op.linewise(params)
+ end
+
+ U.is_fn(cfg.post_hook, ctx)
+end
+
+---@class OpFnParams Operator-mode function parameters
+---@field cfg CommentConfig
+---@field cmode integer See |comment.utils.cmode|
+---@field lines string[] List of lines
+---@field rcs string RHS of commentstring
+---@field lcs string LHS of commentstring
+---@field range CommentRange
+
---Line commenting
---@param param OpFnParams
---@return integer _ Returns a calculated comment mode
@@ -113,7 +148,7 @@ function Op.linewise(param)
for _, line in ipairs(param.lines) do
-- I wish lua had `continue` statement [sad noises]
if not U.ignore(line, pattern) then
- if cmode == U.cmode.uncomment and (not check_comment(line)) then
+ if cmode == U.cmode.uncomment and param.cmode == U.cmode.toggle and (not check_comment(line)) then
cmode = U.cmode.comment
end
@@ -129,6 +164,11 @@ function Op.linewise(param)
end
end
+ -- If the comment mode given is not toggle than force that mode
+ if param.cmode ~= U.cmode.toggle then
+ cmode = param.cmode
+ end
+
if cmode == U.cmode.uncomment then
local uncomment = U.uncommenter(param.lcs, param.rcs, padding)
for i, line in ipairs(param.lines) do
@@ -187,39 +227,4 @@ function Op.blockwise(param, partial)
return cmode
end
----Line commenting with count i.e vim.v.count
----@param count integer Number of lines
----@param cfg CommentConfig
----@param ctype integer See |comment.utils.ctype|
-function Op.count(count, cfg, ctype)
- local lines, range = U.get_count_lines(count)
-
- ---@type CommentCtx
- local ctx = {
- cmode = U.cmode.toggle,
- cmotion = U.cmotion.line,
- ctype = ctype,
- range = range,
- }
- local lcs, rcs = U.parse_cstr(cfg, ctx)
-
- ---@type OpFnParams
- local params = {
- cfg = cfg,
- cmode = ctx.cmode,
- lines = lines,
- lcs = lcs,
- rcs = rcs,
- range = range,
- }
-
- if ctype == U.ctype.blockwise then
- ctx.cmode = Op.blockwise(params)
- else
- ctx.cmode = Op.linewise(params)
- end
-
- U.is_fn(cfg.post_hook, ctx)
-end
-
return Op
diff --git a/lua/Comment/utils.lua b/lua/Comment/utils.lua
index 3f513d0..3988836 100644
--- a/lua/Comment/utils.lua
+++ b/lua/Comment/utils.lua
@@ -4,7 +4,11 @@ local A = vim.api
local U = {}
----@alias CommentLines string[] List of lines inside the start and end index
+---@class CommentCtx Comment context
+---@field ctype integer See |comment.utils.ctype|
+---@field cmode integer See |comment.utils.cmode|
+---@field cmotion integer See |comment.utils.cmotion|
+---@field range CommentRange
---@class CommentRange Range of the selection that needs to be commented
---@field srow integer Starting row
@@ -124,7 +128,7 @@ end
---Get lines from the current position to the given count
---@param count integer Probably 'vim.v.count'
----@return CommentLines
+---@return string[] _ List of lines
---@return CommentRange
function U.get_count_lines(count)
local srow = unpack(A.nvim_win_get_cursor(0))
@@ -136,7 +140,7 @@ end
---Get lines from a NORMAL/VISUAL mode
---@param range CommentRange
----@return CommentLines
+---@return string[] _ List of lines
function U.get_lines(range)
-- If start and end is same, then just return the current line
if range.srow == range.erow then
diff --git a/plugin/Comment.lua b/plugin/Comment.lua
index d3d8605..9681d9d 100644
--- a/plugin/Comment.lua
+++ b/plugin/Comment.lua
@@ -1,6 +1,91 @@
local K = vim.keymap.set
local call = require('Comment.api').call
+---@mod comment.keybindings Keybindings
+---@brief [[
+---Comment.nvim provides default keybinds which is used for (un)comment your code.
+---These keybinds are enabled upon calling |commen.usage.setup| and can be
+---configured or disabled, if desired.
+---
+---Basic: ~
+---
+--- *gc*
+--- *gb*
+--- *gc[count]{motion}*
+--- *gb[count]{motion}*
+---
+--- Toggle comment on a region using linewise/blockwise comment. In 'NORMAL'
+--- mode, it uses 'Operator-Pending' mode to listen for an operator/motion.
+--- In 'VISUAL' mode it simply comment the selected region.
+---
+--- *gcc*
+--- *gbc*
+--- *[count]gcc*
+--- *[count]gbc*
+---
+--- Toggle comment on the current line using linewise/blockwise comment. If
+--- prefixed with a 'v:count' then it will comment over the number of lines
+--- corresponding to the {count}. These are only available in 'NORMAL' mode.
+---
+---
+---Extra: ~
+---
+--- *gco* - Inserts comment below and enters INSERT mode
+--- *gcO* - Inserts comment above and enters INSERT mode
+--- *gcA* - Inserts comment at the end of line and enters INSERT mode
+---@brief ]]
+
+---@mod comment.plugmap Plug Mappings
+---@brief [[
+---Comment.nvim provides mappings for most commonly used actions. These
+---can be used to make custom keybindings and are enabled by default. All plug
+---mappings has support for dot-repeat except VISUAL mode keybindings. To create
+---custom comment function, check out 'comment.api' section.
+---
+--- *(comment_toggle_linewise)*
+--- *(comment_toggle_blockwise)*
+---
+--- Toggle comment on a region with linewise/blockwise comment in NORMAL mode.
+--- using |Operator-Pending| mode (or |g@|) to get the region to comment.
+--- These powers the |gc| and |gb| keybindings.
+---
+--- *(comment_toggle_linewise_current)*
+--- *(comment_toggle_blockwise_current)*
+---
+--- Toggle comment on the current line with linewise/blockwise comment in
+--- NORMAL mode. These powers the |gcc| and 'gbc' keybindings.
+---
+--- *(comment_toggle_linewise_count)*
+--- *(comment_toggle_blockwise_count)*
+---
+--- Toggle comment on a region using 'v:count' with linewise/blockwise comment
+--- in NORMAL mode. These powers the |[count]gcc| and |[count]gbc| keybindings.
+---
+--- *(comment_toggle_linewise_visual)*
+--- *(comment_toggle_blockwise_visual)*
+---
+--- Toggle comment on the selected region with linewise/blockwise comment in
+--- NORMAL mode. These powers the |{visual}gc| and |{visual}gb| keybindings.
+---
+---Usage: ~
+---
+--->
+--- -- Toggle current line or with count
+--- vim.keymap.set('n', 'gcc', function()
+--- return vim.v.count == 0
+--- and '(comment_toggle_linewise_current)'
+--- or '(comment_toggle_linewise_count)'
+--- end, { expr = true })
+---
+--- -- Toggle in Op-pending mode
+--- vim.keymap.set('n', 'gc', '(comment_toggle_linewise)')
+---
+--- -- Toggle in VISUAL mode
+--- vim.keymap.set('x', 'gc', '(comment_toggle_linewise_visual)')
+---<
+---@brief ]]
+---@export plugs
+
-- Operator-Pending mappings
K(
'n',