Skip to content

Commit 695a7ed

Browse files
OXY2DEVSaghen
andauthored
feat: use nvim_echo for emitting errors and notifs (#1523)
* refactor(validate): Use `nvim_echo` for emitting config errors Ref: #973 * chore: Fixed spacing issue * chore: Fixed nested indentation * chore: Stylua check pass * fix(validate): Delayed config error emission for when `noice.nvim` is being used * refactor(validate): Changed how message is handled for external message UIs refactor(validate): Added `nvim-notify` to the external message UI detection function * refactor(fuzzy): Binary download related errors are now handled via a custom notification function * chore(validate): Added title to notifications in config validator * refactor(validate): Config validator now uses the same function for notification as the fuzzy downloader * feat: move to utils, adjust error wording, correctly handle failure * chore: remove `vim.api.nvim_echo` check * fix: misleading error message when not on git tag with outdated prebuilt binaries Closes #1628 * docs: update version reference to recommend `1.*` --------- Co-authored-by: Liam Dyer <[email protected]>
1 parent 2da1a61 commit 695a7ed

File tree

5 files changed

+166
-95
lines changed

5 files changed

+166
-95
lines changed

doc/configuration/fuzzy.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ If possible, it's highly recommended to use the Rust implementation of the fuzzy
2929

3030
### Prebuilt binaries (default on a release tag)
3131

32-
By default, Blink will download a prebuilt binary from the latest release, when you're on a release tag (via `version = '*'` on `lazy.nvim` for example). If you're not on a release tag, you may force a specific version via `fuzzy.prebuilt_binaries.force_version`. See [the latest release](https://github.com/saghen/blink.cmp/releases/latest) for supported systems. See `prebuilt_binaries` section of the [reference configuration](./reference.md#fuzzy) for more options.
32+
By default, Blink will download a prebuilt binary from the latest release, when you're on a release tag (via `version = '1.*'` on `lazy.nvim` for example). If you're not on a release tag, you may force a specific version via `fuzzy.prebuilt_binaries.force_version`. See [the latest release](https://github.com/saghen/blink.cmp/releases/latest) for supported systems. See `prebuilt_binaries` section of the [reference configuration](./reference.md#fuzzy) for more options.
3333

3434
You may instead install the prebuilt binaries manually by downloading the appropriate binary from the [latest release](https://github.com/saghen/blink.cmp/releases/latest) and placing it at `$data/lazy/blink.cmp/target/release/libblink_cmp_fuzzy.$ext`. Get the `$data` path via `:echo stdpath('data')`. Use `.so` for linux, `.dylib` for mac, and `.dll` for windows. If you're unsure whether you want `-musl` or `-gnu` for linux, you very likely want `-gnu`.
3535

lua/blink/cmp/config/utils.lua

+17-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,23 @@ function utils.validate(path, tbl, source)
3434

3535
-- check for erroneous fields
3636
for k, _ in pairs(source) do
37-
if tbl[k] == nil then error(path .. '.' .. k .. ': unexpected field found in configuration') end
37+
if tbl[k] == nil then
38+
---@type string[]
39+
local path_parts = vim.split(path, '.', { plain = true })
40+
local msg = {}
41+
42+
for _, part in ipairs(path_parts) do
43+
table.insert(msg, { ' ' .. part .. ' ', 'DiagnosticVirtualTextInfo' })
44+
table.insert(msg, { '' })
45+
end
46+
47+
--- Highlight the last segment in ERROR since that's
48+
--- where the issue lies.
49+
table.insert(msg, { ' ' .. k .. ' ', 'DiagnosticVirtualTextError' })
50+
table.insert(msg, { ' Unexpected field in configuration!' })
51+
52+
require('blink.cmp.lib.utils').notify(msg)
53+
end
3854
end
3955
end
4056

lua/blink/cmp/fuzzy/download/init.lua

+109-92
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local async = require('blink.cmp.lib.async')
44
local git = require('blink.cmp.fuzzy.download.git')
55
local files = require('blink.cmp.fuzzy.download.files')
66
local system = require('blink.cmp.fuzzy.download.system')
7+
local utils = require('blink.cmp.lib.utils')
78

89
local download = {}
910

@@ -33,120 +34,131 @@ function download.ensure_downloaded(callback)
3334
if version.current.sha == version.git.sha or download_config.ignore_version_mismatch then return end
3435

3536
-- out of date
36-
vim.schedule(
37-
function()
38-
vim.notify(
39-
'[blink.cmp]: Found an outdated version of the locally built fuzzy matching library',
40-
vim.log.levels.WARN,
41-
{ title = 'blink.cmp' }
42-
)
43-
end
44-
)
45-
46-
-- downloading enabled but not on a git tag, error
47-
if download_config.download and target_git_tag == nil then
48-
if target_git_tag == nil then
49-
error(
50-
"Found an outdated version of the fuzzy matching library, but can't download from github due to not being on a git tag."
51-
.. '\n!! FOR DEVELOPERS !!, set `fuzzy.prebuilt_binaries.ignore_version_mismatch = true` in config.'
52-
.. '\n!! FOR USERS !!, either run `cargo build --release` via your package manager, switch to a git tag, or set `fuzzy.prebuilt_binaries.force_version` in config.'
53-
.. '\nSee the docs for more info.'
54-
)
55-
end
37+
utils.notify({
38+
{ 'Found an ' },
39+
{ 'outdated version', 'DiagnosticWarn' },
40+
{ ' of the locally built ' },
41+
{ 'fuzzy matching library', 'DiagnosticInfo' },
42+
})
5643

5744
-- downloading is disabled, error
58-
else
59-
error(
60-
'Found an outdated version of the fuzzy matching library, but downloading from github is disabled.'
61-
.. '\n!! FOR DEVELOPERS !!, set `fuzzy.prebuilt_binaries.ignore_version_mismatch = true` in config.'
62-
.. '\n!! FOR USERS !!, either run `cargo build --release` via your package manager, or set either `fuzzy.prebuilt_binaries.download = true` or `fuzzy.prebuilt_binaries.force_version` in config.'
63-
.. '\nSee the docs for more info.'
64-
)
45+
if not download_config.download then
46+
utils.notify({
47+
{ "Couldn't update fuzzy matching library due to github downloads being disabled." },
48+
{ ' Try setting ' },
49+
{ " build = 'cargo build --release' ", 'DiagnosticVirtualTextInfo' },
50+
{ ' in your lazy.nvim spec and re-installing (requires Rust nightly), or enable ' },
51+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
52+
{ 'ignore_version_mismatch', 'DiagnosticWarn' },
53+
{ ' or set ' },
54+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
55+
{ 'force_version', 'DiagnosticWarn' },
56+
})
57+
return false
58+
59+
-- downloading enabled but not on a git tag, error
60+
elseif target_git_tag == nil then
61+
utils.notify({
62+
{ "Couldn't download the updated " },
63+
{ 'fuzzy matching library', 'DiagnosticInfo' },
64+
{ ' due to not being on a ' },
65+
{ 'git tag', 'DiagnosticInfo' },
66+
{ '. Try building from source via ' },
67+
{ " build = 'cargo build --release' ", 'DiagnosticVirtualTextInfo' },
68+
{ ' in your lazy.nvim spec and re-installing (requires Rust nightly), or switch to a ' },
69+
{ 'git tag', 'DiagnosticInfo' },
70+
{ ' via ' },
71+
{ " version = '1.*' ", 'DiagnosticVirtualTextInfo' },
72+
{ ' in your lazy.nvim spec. Or ignore this error by enabling ' },
73+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
74+
{ 'ignore_version_mismatch', 'DiagnosticWarn' },
75+
{ '. Or force a specific version via ' },
76+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
77+
{ 'force_version', 'DiagnosticWarn' },
78+
})
79+
return false
6580
end
6681
end
6782

68-
-- downloading disabled but not built locally
83+
-- downloading disabled but not built locally, error
6984
if not download_config.download then
70-
-- Fallback, just check if the shared rust library exists
71-
vim.schedule(
72-
function()
73-
vim.notify('[blink.cmp]: No fuzzy matching library found', vim.log.levels.ERROR, { title = 'blink.cmp' })
74-
end
75-
)
76-
77-
error(
78-
'No fuzzy matching library found, but downloading from github is disabled.'
79-
.. '\nEither run `cargo build --release` via your package manager, or set `fuzzy.prebuilt_binaries.download = true` in config.'
80-
.. '\nSee the docs for more info.'
81-
)
85+
utils.notify({
86+
{ 'No fuzzy matching library found!' },
87+
{ ' Try setting ' },
88+
{ " build = 'cargo build --release' ", 'DiagnosticVirtualTextInfo' },
89+
{ ' in your lazy.nvim spec and re-installing (requires Rust nightly), or enable ' },
90+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
91+
{ 'download', 'DiagnosticWarn' },
92+
})
93+
return false
8294
end
8395

84-
-- downloading enabled but not on a git tag
96+
-- downloading enabled but not on a git tag, error
8597
if target_git_tag == nil then
86-
vim.schedule(
87-
function()
88-
vim.notify('[blink.cmp]: No fuzzy matching library found', vim.log.levels.ERROR, { title = 'blink.cmp' })
89-
end
90-
)
91-
92-
error(
93-
"No fuzzy matching library found, but can't download from github due to not being on a git tag and no `fuzzy.prebuilt_binaries.force_version` is set."
94-
.. '\nEither run `cargo build --release` via your package manager, switch to a git tag, or set `fuzzy.prebuilt_binaries.force_version` in config.'
95-
.. '\nSee the docs for more info.'
96-
)
98+
utils.notify({
99+
{ 'No fuzzy matching library found!' },
100+
{ ' Try building from source via ' },
101+
{ " build = 'cargo build --release' ", 'DiagnosticVirtualTextInfo' },
102+
{ ' in your lazy.nvim spec and re-installing (requires Rust nightly), or switch to a ' },
103+
{ 'git tag', 'DiagnosticInfo' },
104+
{ ' via ' },
105+
{ " version = '1.*' ", 'DiagnosticVirtualTextInfo' },
106+
{ ' in your lazy.nvim spec, or set ' },
107+
{ 'fuzzy.prebuilt_binaries.', 'DiagnosticInfo' },
108+
{ 'force_version', 'DiagnosticWarn' },
109+
})
110+
return false
97111
end
98112

99113
-- already downloaded and the correct version, just verify the checksum, and re-download if checksum fails
100114
if version.current.tag == target_git_tag then
101115
return files.verify_checksum():catch(function(err)
102-
vim.schedule(function()
103-
vim.notify(err, vim.log.levels.WARN, { title = 'blink.cmp' })
104-
vim.notify(
105-
'[blink.cmp]: Pre-built binary failed checksum verification, re-downloading',
106-
vim.log.levels.WARN,
107-
{ title = 'blink.cmp' }
108-
)
109-
end)
116+
utils.notify({
117+
{ 'Pre-built binary checksum verification failed, ' },
118+
{ err, 'DiagnosticError' },
119+
}, vim.log.levels.ERROR)
110120
return download.download(target_git_tag)
111121
end)
112122
end
113123

114124
-- download as per usual
115-
vim.schedule(
116-
function() vim.notify('[blink.cmp]: Downloading pre-built binary', vim.log.levels.INFO, { title = 'blink.cmp' }) end
117-
)
125+
utils.notify({ { 'Downloading pre-built binary' } }, vim.log.levels.INFO)
118126
return download.download(target_git_tag)
119127
end)
120-
:map(function()
128+
:map(function(success)
129+
if success == false then
130+
-- fallback to lua implementation
131+
if fuzzy_config.implementation == 'prefer_rust' then
132+
callback(nil, 'lua')
133+
134+
-- fallback to lua implementation and emit warning
135+
elseif fuzzy_config.implementation == 'prefer_rust_with_warning' then
136+
utils.notify({
137+
{ 'Falling back to ' },
138+
{ 'Lua implementation', 'DiagnosticInfo' },
139+
{ ' due to error while downloading pre-built binary, set ' },
140+
{ 'fuzzy.', 'DiagnosticInfo' },
141+
{ 'implementation', 'DiagnosticWarn' },
142+
{ ' to ' },
143+
{ ' "prefer_rust" ', 'DiagnosticVirtualTextInfo' },
144+
{ ' or ' },
145+
{ ' "lua" ', 'DiagnosticVirtualTextInfo' },
146+
{ ' to disable this warning. See ' },
147+
{ ':messages', 'DiagnosticInfo' },
148+
{ ' for details.' },
149+
})
150+
callback(nil, 'lua')
151+
else
152+
callback('Failed to setup fuzzy matcher and rust implementation forced. See :messages for details')
153+
end
154+
return
155+
end
156+
121157
-- clear cached module first since we call it in the pcall above
122158
package.loaded['blink.cmp.fuzzy.rust'] = nil
123-
124159
callback(nil, 'rust')
125160
end)
126-
:catch(function(err)
127-
-- fallback to lua implementation
128-
if fuzzy_config.implementation == 'prefer_rust' then
129-
callback(nil, 'lua')
130-
131-
-- fallback to lua implementation and emit warning
132-
elseif fuzzy_config.implementation == 'prefer_rust_with_warning' then
133-
vim.schedule(function()
134-
vim.notify(
135-
'[blink.cmp]: Falling back to Lua implementation due to error while downloading pre-built binary:\n' .. err,
136-
vim.log.levels.WARN,
137-
{ title = 'blink.cmp' }
138-
)
139-
vim.notify(
140-
"[blink.cmp]: Set `fuzzy.implementation = 'prefer_rust' | 'lua'` to suppress this warning.",
141-
vim.log.levels.WARN,
142-
{ title = 'blink.cmp' }
143-
)
144-
end)
145-
callback(nil, 'lua')
146-
else
147-
callback(err)
148-
end
149-
end)
161+
:catch(callback)
150162
end
151163

152164
function download.download(version)
@@ -163,9 +175,14 @@ end
163175
function download.from_github(tag)
164176
return system.get_triple():map(function(system_triple)
165177
if not system_triple then
166-
return error(
167-
'Your system is not supported by pre-built binaries. You must run cargo build --release via your package manager with rust nightly. See the README for more info.'
168-
)
178+
utils.notify({
179+
{ 'Your system is not supported by ' },
180+
{ ' pre-built binaries ', 'DiagnosticVirtualTextInfo' },
181+
{ '. Try building from source via ' },
182+
{ " build = 'cargo build --release' ", 'DiagnosticVirtualTextInfo' },
183+
{ ' in your lazy.nvim spec and re-installing (requires Rust nightly)' },
184+
})
185+
return
169186
end
170187

171188
local base_url = 'https://github.com/saghen/blink.cmp/releases/download/' .. tag .. '/'

lua/blink/cmp/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function cmp.setup(opts)
2020
config.merge_with(opts)
2121

2222
require('blink.cmp.fuzzy.download').ensure_downloaded(function(err, fuzzy_implementation)
23-
if err then return vim.notify(err, vim.log.levels.ERROR) end
23+
if err then error(err) end
2424
require('blink.cmp.fuzzy').set_implementation(fuzzy_implementation)
2525

2626
-- setup highlights, keymap, completion, commands and signature help

lua/blink/cmp/lib/utils.lua

+38
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,42 @@ function utils.with_no_autocmds(cb)
163163
return result_or_err
164164
end
165165

166+
---@type boolean Have we passed UIEnter?
167+
local _ui_entered = vim.v.vim_did_enter == 1 -- technically for VimEnter, but should be good enough for when we're lazy loaded
168+
---@type function[] List of notifications.
169+
local _notification_queue = {}
170+
171+
--- Fancy notification wrapper.
172+
--- @param msg [string, string?][]
173+
--- @param lvl? number
174+
function utils.notify(msg, lvl)
175+
local header_hl = 'DiagnosticVirtualTextWarn'
176+
if lvl == vim.log.levels.ERROR then
177+
header_hl = 'DiagnosticVirtualTextError'
178+
elseif lvl == vim.log.levels.INFO then
179+
header_hl = 'DiagnosticVirtualTextInfo'
180+
end
181+
182+
table.insert(msg, 1, { ' blink.cmp ', header_hl })
183+
table.insert(msg, 2, { ' ' })
184+
185+
if _ui_entered then
186+
-- After UIEnter emit message immediately
187+
vim.api.nvim_echo(msg, true, { err = true, verbose = false })
188+
else
189+
-- Queue notification for the UIEnter event.
190+
table.insert(_notification_queue, function() vim.api.nvim_echo(msg, true, { verbose = false }) end)
191+
end
192+
end
193+
194+
vim.api.nvim_create_autocmd('UIEnter', {
195+
callback = function()
196+
_ui_entered = true
197+
198+
for _, fn in ipairs(_notification_queue) do
199+
pcall(fn)
200+
end
201+
end,
202+
})
203+
166204
return utils

0 commit comments

Comments
 (0)