Dictionary source for blink.cmp completion plugin. This makes it possible to query a dictionary without leaving the editor.
Fuzzy finding is supported by default:
Definitions of words are also supported (use wn
by default):
Note
wn
is the abbreviation of WordNet
, which is a lexical database of the English language.
If you don't know how to install wn
, you may google the keyword
how to install WordNet on ...
.
For the default configuration, you must have fzf
(or rg
) to search in the dictionary file.
And wn
must be installed to get the definitions of words. cat
for concatenating the dictionary
files. You can use checkhealth blink-cmp-dictionary
to check if the requirements are met.
If you have no cat
in your system,
see How to customize the command.
Add the plugin to your packer managers, and make sure it is loaded before blink.cmp
.
{
'saghen/blink.cmp',
dependencies = {
{
'Kaiser-Yang/blink-cmp-dictionary',
dependencies = { 'nvim-lua/plenary.nvim' }
}
-- ... Other dependencies
},
opts = {
sources = {
-- Add 'dictionary' to the list
default = { 'dictionary', 'lsp', 'path', 'luasnip', 'buffer' },
providers = {
dictionary = {
module = 'blink-cmp-dictionary',
name = 'Dict',
-- Make sure this is at least 2.
-- 3 is recommended
min_keyword_length = 3,
opts = {
-- options for blink-cmp-dictionary
}
}
},
}
}
}
Note
If you don't have a dictionary file, see english-words.
By default, your dictionary files must be like this content (every line is a word):
word1
word2
If you dictionary files are like these. You just need to specify the dictionary files' path in the configuration:
-- Specify the dictionary files' path
-- example: { vim.fn.expand('~/.config/nvim/dictionary/words.dict') }
dictionary_files = nil,
-- All .txt files in these directories will be treated as dictionary files
-- example: { vim.fn.expand('~/.config/nvim/dictionary') }
dictionary_directories = nil,
Note
All the dictionary files in dictionary_files
and dictionary_directories
will be
concatenated by cat
command. Make sure the files are different, otherwise there will be
duplicate words in the completion list. If your dictionary files are not separated by lines,
see How to customize completion items
See default.lua.
You just need use a function to determine the dictionary files for different file types, for example:
dictionary_files = function()
if vim.bo.filetype == 'markdown' then
return { vim.fn.expand('~/.config/nvim/dictionary/markdown.dict') }
end
return { vim.fn.expand('~/.config/nvim/dictionary/words.dict') }
end,
In blink-cmp-dictionary
we use get_prefix
to determine which part to search. If we do not use
fzf
, for example we use rg
, and we set min_keyword_length=3
. After inputting 'dic',
blink.cmp
will get all the words that start with 'dic', then blink.cmp
will fuzzy find on
words starting with 'dic'. The process makes it impossible to complete 'dictionary'
when inputting 'dit'. But if we use fzf
, fzf
will return 'dictionary' when inputting dit
('dit' is a sub-sequence of 'dictionary'). So the fuzzy finding feature are fully supported.
By default, blink-cmp-dictionary
treat every line in the dictionary files as a completion item.
You can update this by use separate_output
in the configuration:
separate_output = function(output)
local items = {}
-- You may need to change the pattern to match your dictionary files
for line in output:gmatch("[^\r\n]+") do
local items = {}
for line in output:gmatch("[^\r\n]+") do
table.insert(items, line)
end
return items
end
return items
end
After calling separate_output
, blink-cmp-dictionary
will call get_label
, get_insert_text
,
get_documentation
, and get_kind
for each item in the list to assemble the completion items.
Those below are the default:
get_label = function(item)
return item
end,
get_insert_text = function(item)
return item
end,
get_kind_name = function(_)
return 'Dict'
end,
get_documentation = function(item)
-- use return nil to disable the documentation
-- return nil
return {
get_command = function()
return utils.command_found('wn') and 'wn' or ''
end,
get_command_args = function()
return { item, '-over' }
end,
resolve_documentation = function(output)
return output
end,
on_error = default_on_error,
}
end,
By default, blink-cmp-dictionary
will use fzf
to read from the output of cat
. If you do not
have cat
in your system, you may have other commands to output the content of files, just create
a symbolic link named cat
to the command you use.
You may configure a new command which supports reading from files directly, for example, rg
:
-- set them with nil to pass files directly to the command
dictionary_files = nil,
dictionary_directories = nil,
get_command = 'rg',
get_command_args = function(prefix, _)
local dictionary_file1 = 'path/to/your/dictionary/file1'
local dictionary_file2 = 'path/to/your/dictionary/file2'
return {
'--color=never',
'--no-line-number',
'--no-messages',
'--no-filename',
'--smart-case',
'--',
prefix,
-- pass the dictionary files to the command
dictionary_file1,
dictionary_file2,
}
end
If you just want to customize the arguments for fzf
, for example,
those below will ignore the case:
get_command_args = function(prefix, _)
return {
'--filter=' .. prefix,
'--sync',
'--no-sort',
'-i' -- -i to ignore case, +i to respect case, with no this line is smart case
}
end,
Customize the BlinkCmpKindDict
to customize the highlight for kind icon, here is an example:
vim.api.nvim_set_hl(0, 'BlinkCmpKindDict', { default = false, fg = '#a6e3a1' })
blink-cmp-dictionary
is asynchronous by default, so it should not block other operations.
But there are something you should note:
- Make sure the
min_keyword_length
is at least 2. If your dictionary files are very large, a larger value is recommended. This is mainly becauseblink-cmp-dictionary
actually can handle this quickly, but there will be too many results return toblink.cmp
, which will makeblink.cmp
take a long time to fuzzy find the results. - Optionally, you can limit the number of items shown in the completion menu.
opts = {
sources = {
providers = {
dictionary = {
-- Add this and change the value to your own preference
max_items = 8,
}
},
}
}
The release versions are something like major.minor.patch
. When one of these numbers is increased:
patch
: bugs are fixed or docs are added. This will not break the compatibility.minor
: compatible features are added. This may cause some configurationsdeprecated
, but not break the compatibility.major
: incompatible features are added. All thedeprecated
configurations will be removed. This will break the compatibility.
Nice and fast completion plugin: blink.cmp.
Inspired by cmp-dictionary.
Learned how to write a source from blink-ripgrep.nvim.