forked from niuiic/blink-cmp-rg.nvim
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: change the architecture to allow different search backends
Right now this solves no issue, but I want to experiment with adding more search backends in the future. For this to be easier, it's probably good to have an idea of what a "backend" actually is 🙂 I think they can help solve performance issues in massive repositories. For example, I found out that "git grep" is much faster than ripgrep in some cases (5s vs 40s). Related to #110
- Loading branch information
1 parent
d8d4945
commit 2b6834b
Showing
7 changed files
with
225 additions
and
201 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
---@class blink-ripgrep.Backend | ||
---@field config blink-ripgrep.Options | ||
local RipgrepBackend = {} | ||
|
||
---@param config table | ||
function RipgrepBackend.new(config) | ||
local self = setmetatable({}, { __index = RipgrepBackend }) | ||
self.config = config | ||
return self --[[@as blink-ripgrep.Backend]] | ||
end | ||
|
||
function RipgrepBackend:get_matches(prefix, context, resolve) | ||
if self.config.mode ~= "on" then | ||
if self.config.debug then | ||
local debug = require("blink-ripgrep.debug") | ||
debug.add_debug_message("mode is off, skipping the search") | ||
debug.add_debug_invocation({ "ignored-because-mode-is-off" }) | ||
end | ||
resolve() | ||
return | ||
end | ||
|
||
if string.len(prefix) < self.config.prefix_min_len then | ||
resolve() | ||
return | ||
end | ||
|
||
-- builtin default command | ||
local command_module = | ||
require("blink-ripgrep.backends.ripgrep.ripgrep_command") | ||
local cmd = command_module.get_command(prefix, self.config) | ||
|
||
if cmd == nil then | ||
if self.config.debug then | ||
local debug = require("blink-ripgrep.debug") | ||
debug.add_debug_message("no command returned, skipping the search") | ||
debug.add_debug_invocation({ "ignored-because-no-command" }) | ||
end | ||
|
||
resolve() | ||
return | ||
end | ||
|
||
if vim.tbl_contains(self.config.ignore_paths, cmd.root) then | ||
if self.config.debug then | ||
local debug = require("blink-ripgrep.debug") | ||
debug.add_debug_message("skipping search in ignored path" .. cmd.root) | ||
debug.add_debug_invocation({ "ignored", cmd.root }) | ||
end | ||
resolve() | ||
|
||
return | ||
end | ||
|
||
if self.config.debug then | ||
if cmd.debugify_for_shell then | ||
cmd:debugify_for_shell() | ||
end | ||
|
||
require("blink-ripgrep.visualization").flash_search_prefix(prefix) | ||
require("blink-ripgrep.debug").add_debug_invocation(cmd) | ||
end | ||
|
||
local rg = vim.system(cmd.command, nil, function(result) | ||
vim.schedule(function() | ||
if result.code ~= 0 then | ||
resolve() | ||
return | ||
end | ||
|
||
local lines = vim.split(result.stdout, "\n") | ||
local cwd = vim.uv.cwd() or "" | ||
|
||
local parsed = | ||
require("blink-ripgrep.backends.ripgrep.ripgrep_parser").parse( | ||
lines, | ||
cwd, | ||
self.config.context_size | ||
) | ||
local kinds = require("blink.cmp.types").CompletionItemKind | ||
|
||
---@type table<string, blink.cmp.CompletionItem> | ||
local items = {} | ||
for _, file in pairs(parsed.files) do | ||
for _, match in pairs(file.matches) do | ||
local matchkey = match.match.text | ||
|
||
-- PERF: only register the match once - right now there is no useful | ||
-- way to display the same match multiple times | ||
if not items[matchkey] then | ||
local label = match.match.text | ||
local docstring = "" | ||
for _, line in ipairs(match.context_preview) do | ||
docstring = docstring .. line.text .. "\n" | ||
end | ||
|
||
local draw_docs = function(draw_opts) | ||
require("blink-ripgrep.documentation").render_item_documentation( | ||
self.config, | ||
draw_opts, | ||
file, | ||
match | ||
) | ||
end | ||
|
||
---@diagnostic disable-next-line: missing-fields | ||
items[matchkey] = { | ||
documentation = { | ||
kind = "markdown", | ||
value = docstring, | ||
draw = draw_docs, | ||
-- legacy, will be removed in a future release of blink | ||
-- https://github.com/Saghen/blink.cmp/issues/1113 | ||
render = draw_docs, | ||
}, | ||
source_id = "blink-ripgrep", | ||
kind = kinds.Text, | ||
label = label, | ||
insertText = matchkey, | ||
} | ||
end | ||
end | ||
end | ||
|
||
vim.schedule(function() | ||
resolve({ | ||
is_incomplete_forward = false, | ||
is_incomplete_backward = false, | ||
items = vim.tbl_values(items), | ||
context = context, | ||
}) | ||
end) | ||
end) | ||
end) | ||
|
||
return function() | ||
rg:kill(9) | ||
if self.config.debug then | ||
require("blink-ripgrep.debug").add_debug_message( | ||
"killed previous invocation" | ||
) | ||
end | ||
end | ||
end | ||
|
||
return RipgrepBackend |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
local documentation = {} | ||
|
||
local highlight_ns_id = 0 | ||
pcall(function() | ||
highlight_ns_id = require("blink.cmp.config").appearance.highlight_ns | ||
end) | ||
vim.api.nvim_set_hl(0, "BlinkRipgrepMatch", { link = "Search", default = true }) | ||
|
||
---@param config blink-ripgrep.Options | ||
---@param draw_opts blink.cmp.CompletionDocumentationDrawOpts | ||
---@param file blink-ripgrep.RipgrepFile | ||
---@param match blink-ripgrep.RipgrepMatch | ||
function documentation.render_item_documentation(config, draw_opts, file, match) | ||
local bufnr = draw_opts.window:get_buf() | ||
---@type string[] | ||
local text = { | ||
file.relative_to_cwd, | ||
string.rep( | ||
"─", | ||
-- TODO account for the width of the scrollbar if it's visible | ||
draw_opts.window:get_width() | ||
- draw_opts.window:get_border_size().horizontal | ||
- 1 | ||
), | ||
} | ||
for _, data in ipairs(match.context_preview) do | ||
table.insert(text, data.text) | ||
end | ||
|
||
-- TODO add extmark highlighting for the divider line like in blink | ||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, text) | ||
|
||
local filetype = vim.filetype.match({ filename = file.relative_to_cwd }) | ||
local parser_name = vim.treesitter.language.get_lang(filetype or "") | ||
local parser_installed = parser_name | ||
and pcall(function() | ||
return vim.treesitter.get_parser(nil, file.language, {}) | ||
end) | ||
|
||
if not parser_installed and config.fallback_to_regex_highlighting then | ||
-- Can't show highlighted text because no treesitter parser | ||
-- has been installed for this language. | ||
-- | ||
-- Fall back to regex based highlighting that is bundled in | ||
-- neovim. It might not be perfect but it's much better | ||
-- than no colors at all | ||
vim.schedule(function() | ||
vim.api.nvim_set_option_value("filetype", file.language, { buf = bufnr }) | ||
vim.api.nvim_buf_call(bufnr, function() | ||
vim.cmd("syntax on") | ||
end) | ||
end) | ||
else | ||
assert(parser_name, "missing parser") -- lua-language-server should narrow this but can't | ||
require("blink.cmp.lib.window.docs").highlight_with_treesitter( | ||
bufnr, | ||
parser_name, | ||
2, | ||
#text | ||
) | ||
end | ||
|
||
require("blink-ripgrep.highlighting").highlight_match_in_doc_window( | ||
bufnr, | ||
match, | ||
highlight_ns_id | ||
) | ||
end | ||
|
||
return documentation |
Oops, something went wrong.