1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
---@mod comment.api Core Lua API
---@brief [[
---This module provides the core lua APIs which is used by the default keybindings
---and <Plug> (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')
local Op = require('Comment.opfunc')
local Ex = require('Comment.extra')
local A = vim.api
local api, core = {}, {}
---API metamethods
---@param that table
---@param ctype CommentType
---@return table
function core.__index(that, ctype)
local idxd = {}
local mode, type = that.cmode, U.ctype[ctype]
---To comment the current-line
---NOTE:
---In current-line linewise method, 'opmode' is not useful which is always equals to `char`
---but we need 'nil' here which is used for current-line
function idxd.current(_, cfg)
U.catch(Op.opfunc, nil, cfg or Config:get(), mode, type)
end
---To comment lines with a count
function idxd.count(count, cfg)
U.catch(Op.count, count or A.nvim_get_vvar('count'), cfg or Config:get(), mode, type)
end
---@private
---To comment lines with a count, also dot-repeatable
---WARN: This is not part of the API but anyone case use it, if they want
function idxd.count_repeat(_, count, cfg)
idxd.count(count, cfg)
end
return setmetatable({}, {
__index = idxd,
__call = function(_, motion, cfg)
U.catch(Op.opfunc, motion, cfg or Config:get(), mode, type)
end,
})
end
---@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.
---
---Every function 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')
---local config = require('Comment.config'):get()
---
---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', '<C-_>', api.toggle.linewise.current)
---
----- Toggle current line (blockwise) using C-\
---vim.keymap.set('n', '<C-\\>', api.toggle.blockwise.current)
---
----- Toggle lines (linewise) with dot-repeat support
----- Example: <leader>gc3j will comment 4 lines
---vim.keymap.set(
--- 'n', '<leader>gc', api.call('toggle.linewise', 'g@'),
--- { expr = true }
---)
---
----- Toggle lines (blockwise) with dot-repeat support
----- Example: <leader>gb3j will comment 4 lines
---vim.keymap.set(
--- 'n', '<leader>gb', api.call('toggle.blockwise', 'g@'),
--- { expr = true }
---)
---
---local esc = vim.api.nvim_replace_termcodes(
--- '<ESC>', true, false, true
---)
---
----- Toggle selection (linewise)
---vim.keymap.set('x', '<leader>c', function()
--- vim.api.nvim_feedkeys(esc, 'nx', false)
--- api.toggle.linewise(vim.fn.visualmode())
---end)
---
----- Toggle selection (blockwise)
---vim.keymap.set('x', '<leader>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)
---@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.
---
---Every function 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')
---local config = require('Comment.config'):get()
---
---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)
---@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.
---
---Every function 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')
---local config = require('Comment.config'):get()
---
---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)
---Provides API to to insert comment on previous, next or at the end-of-line.
---Every function takes an optional {config} parameter.
---@type table A metatable containing API functions
---@see comment.config
---@usage [[
---local api = require('Comment.api')
---local config = require('Comment.config'):get()
---
---api.insert.linewise.above(config?)
---api.insert.linewise.below(config?)
---api.insert.linewise.eol(config?)
---
---api.insert.blockwise.above(config?)
---api.insert.blockwise.below(config?)
---api.insert.blockwise.eol(config?)
---@usage ]]
api.insert = setmetatable({}, {
__index = function(_, ctype)
return {
above = function(cfg)
U.catch(Ex.insert_above, U.ctype[ctype], cfg or Config:get())
end,
below = function(cfg)
U.catch(Ex.insert_below, U.ctype[ctype], cfg or Config:get())
end,
eol = function(cfg)
U.catch(Ex.insert_eol, U.ctype[ctype], cfg or Config:get())
end,
}
end,
})
---Wraps the given API function with 'lockmarks' to preserve marks/jumps
---@param cb string Name of API function
---@return fun(motion:OpMotion) #Callback function
---@see lockmarks
---@see comment.opfunc.OpMotion
---@usage [[
---local api = require('Comment.api')
---
---vim.keymap.set(
--- 'n', '<leader>c', api.locked('toggle.linewise.current')
---)
---
---local esc = vim.api.nvim_replace_termcodes(
--- '<ESC>', true, false, true
---)
---vim.keymap.set('x', '<leader>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 ]]
function api.locked(cb)
return function(motion)
return A.nvim_command(
('lockmarks lua require("Comment.api").%s(%s)'):format(cb, motion and ('%q'):format(motion))
)
end
end
---Callback function which does the following
--- 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-mode expression
---@return fun():string #Keymap RHS callback
---@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))
Config.position = Config:get().sticky and A.nvim_win_get_cursor(0) or nil
return op
end
end
return api
|