Skip to content

Commit 3d2dc15

Browse files
feat: add completion sources
## Details Adds completion source for checkboxes in list items and callouts in block quotes. Provides implementation for both `nvim-cmp` and `blink.cmp`. The latter has some issues in finishing the completion but releasing it anyway since it's better than nothing. Added documentation for how to enable the different completion sources.
1 parent 3a08669 commit 3d2dc15

File tree

10 files changed

+251
-13
lines changed

10 files changed

+251
-13
lines changed

README.md

+31
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,37 @@ use({
115115
| `:RenderMarkdown debug` | `require('render-markdown').debug()` | Prints information about marks on current line |
116116
| `:RenderMarkdown config` | `require('render-markdown').config()` | Prints difference between config and default |
117117

118+
# Completions
119+
120+
This plugin provides completions for both checkboxes and callouts provided you follow
121+
the relevant setup.
122+
123+
## nvim-cmp
124+
125+
```lua
126+
local cmp = require('cmp')
127+
cmp.setup({
128+
sources = cmp.config.sources({
129+
{ name = 'render-markdown' },
130+
}),
131+
})
132+
```
133+
134+
## blink.cmp
135+
136+
```lua
137+
require('blink.cmp').setup({
138+
sources = {
139+
completion = {
140+
enabled_providers = { 'lsp', 'path', 'snippets', 'buffer', 'markdown' },
141+
},
142+
providers = {
143+
markdown = { name = 'RenderMarkdown', module = 'render-markdown.integ.blink' },
144+
},
145+
},
146+
})
147+
```
148+
118149
# Setup
119150

120151
Checkout the [Wiki](https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki)

doc/render-markdown.txt

+45-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2024 December 07
1+
*render-markdown.txt* For 0.10.0 Last change: 2024 December 08
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -11,7 +11,10 @@ Table of Contents *render-markdown-table-of-contents*
1111
- rocks.nvim |render-markdown-install-rocks.nvim|
1212
- packer.nvim |render-markdown-install-packer.nvim|
1313
5. Commands |render-markdown-commands|
14-
6. Setup |render-markdown-setup|
14+
6. Completions |render-markdown-completions|
15+
- nvim-cmp |render-markdown-completions-nvim-cmp|
16+
- blink.cmp |render-markdown-completions-blink.cmp|
17+
7. Setup |render-markdown-setup|
1518
- Headings |render-markdown-setup-headings|
1619
- Paragraphs |render-markdown-setup-paragraphs|
1720
- Code Blocks |render-markdown-setup-code-blocks|
@@ -24,8 +27,8 @@ Table of Contents *render-markdown-table-of-contents*
2427
- Links |render-markdown-setup-links|
2528
- Signs |render-markdown-setup-signs|
2629
- Indent |render-markdown-setup-indent|
27-
7. Colors |render-markdown-colors|
28-
8. Info |render-markdown-info|
30+
8. Colors |render-markdown-colors|
31+
9. Info |render-markdown-info|
2932
- vimwiki |render-markdown-info-vimwiki|
3033
- obsidian.nvim |render-markdown-info-obsidian.nvim|
3134
- Images |render-markdown-info-images|
@@ -162,7 +165,42 @@ PACKER.NVIM *render-markdown-install-packer.nvim*
162165
-------------------------------------------------------------------------------------------------
163166

164167
==============================================================================
165-
6. Setup *render-markdown-setup*
168+
6. Completions *render-markdown-completions*
169+
170+
This plugin provides completions for both checkboxes and callouts provided you
171+
follow the relevant setup.
172+
173+
174+
NVIM-CMP *render-markdown-completions-nvim-cmp*
175+
176+
>lua
177+
local cmp = require('cmp')
178+
cmp.setup({
179+
sources = cmp.config.sources({
180+
{ name = 'render-markdown' },
181+
}),
182+
})
183+
<
184+
185+
186+
BLINK.CMP *render-markdown-completions-blink.cmp*
187+
188+
>lua
189+
require('blink.cmp').setup({
190+
sources = {
191+
completion = {
192+
enabled_providers = { 'lsp', 'path', 'snippets', 'buffer', 'markdown' },
193+
},
194+
providers = {
195+
markdown = { name = 'RenderMarkdown', module = 'render-markdown.integ.blink' },
196+
},
197+
},
198+
})
199+
<
200+
201+
202+
==============================================================================
203+
7. Setup *render-markdown-setup*
166204

167205
Checkout the Wiki
168206
<https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki> for
@@ -1214,7 +1252,7 @@ Indent Configuration ~
12141252

12151253

12161254
==============================================================================
1217-
7. Colors *render-markdown-colors*
1255+
8. Colors *render-markdown-colors*
12181256

12191257
The table below shows all the highlight groups with their default link
12201258

@@ -1305,7 +1343,7 @@ The table below shows all the highlight groups with their default link
13051343
-----------------------------------------------------------------------------------------
13061344

13071345
==============================================================================
1308-
8. Info *render-markdown-info*
1346+
9. Info *render-markdown-info*
13091347

13101348

13111349
VIMWIKI *render-markdown-info-vimwiki*

lua/render-markdown/config.lua

+13-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local Range = require('render-markdown.core.range')
55
---@field checkbox table<string, render.md.CustomCheckbox>
66

77
---@class render.md.buffer.Config: render.md.BufferConfig
8-
---@field component render.md.component.Config
8+
---@field private component render.md.component.Config
99
local Config = {}
1010
Config.__index = Config
1111

@@ -44,6 +44,18 @@ function Config:render(mode)
4444
end
4545
end
4646

47+
---@param node render.md.Node
48+
---@return render.md.CustomCallout?
49+
function Config:get_callout(node)
50+
return self.component.callout[node.text:lower()]
51+
end
52+
53+
---@param node render.md.Node
54+
---@return render.md.CustomCheckbox?
55+
function Config:get_checkbox(node)
56+
return self.component.checkbox[node.text:lower()]
57+
end
58+
4759
---@param mode string
4860
---@param row? integer
4961
---@return render.md.Range?

lua/render-markdown/health.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local state = require('render-markdown.state')
44
local M = {}
55

66
---@private
7-
M.version = '7.7.0'
7+
M.version = '7.7.1'
88

99
function M.check()
1010
M.start('version')

lua/render-markdown/integ/blink.lua

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---@module 'blink.cmp'
2+
3+
local source = require('render-markdown.integ.source')
4+
5+
---@class render.md.blink.Source: blink.cmp.Source
6+
local Source = {}
7+
Source.__index = Source
8+
9+
---@return blink.cmp.Source
10+
function Source.new()
11+
return setmetatable({}, Source)
12+
end
13+
14+
---@return boolean
15+
function Source:enabled()
16+
return source.enabled()
17+
end
18+
19+
---@return string[]
20+
function Source:get_trigger_characters()
21+
return source.trigger_characters()
22+
end
23+
24+
---@param context blink.cmp.Context
25+
---@param callback fun(response?: blink.cmp.CompletionResponse)
26+
function Source:get_completions(context, callback)
27+
local items = source.items(context.bufnr, context.cursor[1] - 1, context.cursor[2] - 1)
28+
if items == nil then
29+
callback(nil)
30+
else
31+
callback({
32+
is_incomplete_forward = false,
33+
is_incomplete_backward = false,
34+
context = context,
35+
items = items,
36+
})
37+
end
38+
end
39+
40+
return Source

lua/render-markdown/integ/cmp.lua

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
local source = require('render-markdown.integ.source')
2+
3+
---@class render.md.cmp.Source: cmp.Source
4+
local Source = {}
5+
6+
---@return string
7+
function Source:get_debug_name()
8+
return 'render-markdown'
9+
end
10+
11+
---@return boolean
12+
function Source:is_available()
13+
return source.enabled()
14+
end
15+
16+
---@return string[]
17+
function Source:get_trigger_characters()
18+
return source.trigger_characters()
19+
end
20+
21+
---@param params cmp.SourceCompletionApiParams
22+
---@param callback fun(response?: lsp.CompletionItem[])
23+
function Source:complete(params, callback)
24+
local context = params.context
25+
local items = source.items(context.bufnr, context.cursor.row - 1, context.cursor.col - 1)
26+
if items == nil then
27+
callback(nil)
28+
else
29+
callback(items)
30+
end
31+
end
32+
33+
---@class render.md.integ.Cmp
34+
local M = {}
35+
36+
---Should only be called from plugin directory
37+
function M.setup()
38+
local has_cmp, cmp = pcall(require, 'cmp')
39+
if not has_cmp then
40+
return
41+
end
42+
cmp.register_source(Source:get_debug_name(), Source)
43+
end
44+
45+
return M

lua/render-markdown/integ/source.lua

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
local manager = require('render-markdown.manager')
2+
local state = require('render-markdown.state')
3+
local util = require('render-markdown.core.util')
4+
5+
---@class render.md.Source
6+
local M = {}
7+
8+
---@return boolean
9+
function M.enabled()
10+
return manager.is_attached(util.current('buf'))
11+
end
12+
13+
---@return string[]
14+
function M.trigger_characters()
15+
return { ' ', '[' }
16+
end
17+
18+
---@param buf integer
19+
---@param row integer
20+
---@param col integer
21+
---@return lsp.CompletionItem[]?
22+
function M.items(buf, row, col)
23+
local node = vim.treesitter.get_node({
24+
bufnr = buf,
25+
pos = { row, col },
26+
})
27+
if node == nil then
28+
return nil
29+
end
30+
local node_type = node:type()
31+
local config = state.get(buf)
32+
local items = {}
33+
if vim.tbl_contains({ 'block_quote', 'block_quote_marker' }, node_type) then
34+
for _, component in pairs(config.callout) do
35+
table.insert(items, M.item(component.raw, component.rendered, nil))
36+
end
37+
elseif vim.tbl_contains({ 'list_item', 'list_marker_minus' }, node_type) then
38+
local checkbox = config.checkbox
39+
table.insert(items, M.item('[ ]', checkbox.unchecked.icon, 'unchecked'))
40+
table.insert(items, M.item('[x]', checkbox.checked.icon, 'checked'))
41+
for name, component in pairs(checkbox.custom) do
42+
table.insert(items, M.item(component.raw, component.rendered, name))
43+
end
44+
end
45+
return items
46+
end
47+
48+
---@private
49+
---@param raw string
50+
---@param rendered string
51+
---@param name? string
52+
---@return lsp.CompletionItem
53+
function M.item(raw, rendered, name)
54+
---@type lsp.CompletionItem
55+
return {
56+
label = raw,
57+
labelDetails = {
58+
detail = rendered,
59+
description = name,
60+
},
61+
kind = 12,
62+
}
63+
end
64+
65+
return M

lua/render-markdown/manager.lua

+8-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function M.setup()
3030
end
3131
for _, win in ipairs(vim.v.event.windows) do
3232
local buf = vim.fn.winbufnr(win)
33-
if vim.tbl_contains(buffers, buf) then
33+
if M.is_attached(buf) then
3434
ui.update(buf, win, args.event, true)
3535
end
3636
end
@@ -48,6 +48,12 @@ function M.set_all(enabled)
4848
end
4949
end
5050

51+
---@param buf integer
52+
---@return boolean
53+
function M.is_attached(buf)
54+
return vim.tbl_contains(buffers, buf)
55+
end
56+
5157
---@private
5258
---@param buf integer
5359
function M.attach(buf)
@@ -85,7 +91,7 @@ end
8591
function M.should_attach(buf)
8692
log.buf('info', 'attach', buf, 'start')
8793

88-
if vim.tbl_contains(buffers, buf) then
94+
if M.is_attached(buf) then
8995
log.buf('info', 'attach', buf, 'skip', 'already attached')
9096
return false
9197
end

lua/render-markdown/render/shortcut.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ function Render:setup()
1414
end
1515

1616
function Render:render()
17-
local callout = self.config.component.callout[self.node.text:lower()]
17+
local callout = self.config:get_callout(self.node)
1818
if callout ~= nil then
1919
self:callout(callout)
2020
return
2121
end
2222

23-
local checkbox = self.config.component.checkbox[self.node.text:lower()]
23+
local checkbox = self.config:get_checkbox(self.node)
2424
if checkbox ~= nil then
2525
self:checkbox(checkbox)
2626
return

plugin/render-markdown.lua

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ require('render-markdown').setup()
77
require('render-markdown.colors').setup()
88
require('render-markdown.command').setup()
99
require('render-markdown.manager').setup()
10+
require('render-markdown.integ.cmp').setup()

0 commit comments

Comments
 (0)