Skip to content

Commit

Permalink
WIP: display highlighting for files without treesitter parsers
Browse files Browse the repository at this point in the history
For now, this only works locally using this branch in blink:

Saghen/blink.cmp#650
  • Loading branch information
mikavilpas committed Dec 19, 2024
1 parent 24c7b5f commit 120284f
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 56 deletions.
89 changes: 82 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# blink-ripgrep.nvim

<a href="https://dotfyle.com/plugins/mikavilpas/blink-ripgrep.nvim">
<img src="https://dotfyle.com/plugins/mikavilpas/blink-ripgrep.nvim/shield?style=flat-square" alt="shield image for plugin usage"/>
<img
src="https://dotfyle.com/plugins/mikavilpas/blink-ripgrep.nvim/shield?style=flat-square"
alt="shield image for plugin usage"
/>
</a>

Ripgrep source for the [blink.cmp](/~https://github.com/Saghen/blink.cmp)
Expand All @@ -12,7 +15,7 @@ as repetitive typing.
> [!NOTE]
>
> A project root is considered to be the nearest ancestor directory containing a
> `.git` directory. If none can be found, neovim's current working directory is
> `.git` directory. If none can be found, Neovim's current working directory is
> used.
![blink-ripgrep search with a context preview](./demo/screenshot.png)
Expand Down Expand Up @@ -42,6 +45,8 @@ return {
sources = {
completion = {
enabled_providers = {
-- NOTE: blink >v0.7.6 has moved
-- `sources.completion.enabled_providers` to `sources.default`
"lsp",
"path",
"snippets",
Expand All @@ -65,18 +70,88 @@ return {
-- (if the word is shorter than this, the search will not start)
prefix_min_len = 3,

-- The number of lines to show around each match in the preview window
-- The number of lines to show around each match in the preview
-- (documentation) window. For example, 5 means to show 5 lines
-- before, then the match, and another 5 lines after the match.
context_size = 5,

-- The maximum file size that ripgrep should include in its search.
-- Useful when your project contains large files that might cause
-- performance issues.
-- Examples: "1024" (bytes by default), "200K", "1M", "1G"
-- The maximum file size of a file that ripgrep should include in
-- its search. Useful when your project contains large files that
-- might cause performance issues.
-- Examples:
-- "1024" (bytes by default), "200K", "1M", "1G", which will
-- exclude files larger than that size.
max_filesize = "1M",

-- (advanced) Any additional options you want to give to ripgrep.
-- See `rg -h` for a list of all available options. Might be
-- helpful in adjusting performance in specific situations.
-- If you have an idea for a default, please open an issue!
--
-- Not everything will work (obviously).
additional_rg_options = {},
},
},
},
keymap = {
["<c-g>"] = {
function()
-- invoke manually, requires blink >v0.7.6
require("blink-cmp").show({ sources = { "ripgrep" } })
end,
},
},
},
},
}
```

## 🏁 Performance

Depending on the size of your project and your computer's specifications, the
search can be fast or slow. Here are a few things you can do to improve
performance:

- Set the `prefix_min_len` option to a larger number avoid starting a search for
very short words. This can prevent unnecessary searches and improve
performance.
- Use the `max_filesize` option to exclude large files from the search. This can
prevent performance issues when searching in projects with large files.
- If you still experience performance issues, please open an issue for
discussion.

### Automatic mode

In this mode, the search starts automatically when typing a word that is at
least `prefix_min_len` in length.

This is enabled by including the `ripgrep` provider in blink-cmp's providers:

```lua
return {
-- ... other configuration
---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
sources = {
completion = {
enabled_providers = {
-- NOTE: blink >v0.7.6 has moved
-- `sources.completion.enabled_providers` to `sources.default`
"lsp",
"path",
"snippets",
"buffer",
"ripgrep", -- 👈🏻 including this enables automatic search
},
},
}
}
}
```

### Manual mode

If you prefer to start the search manually, you can use a keymap to invoke the
search. The example configuration includes a keymap that invokes the search when
pressing `Ctrl+g`.
28 changes: 28 additions & 0 deletions integration-tests/MyTestDirectory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ export const MyTestDirectorySchema = z.object({
}),
}),
}),
"config-modifications": z.object({
name: z.literal("config-modifications/"),
type: z.literal("directory"),
contents: z.object({
".gitkeep": z.object({
name: z.literal(".gitkeep"),
type: z.literal("file"),
extension: z.literal(""),
stem: z.literal(".gitkeep"),
}),
"use_manual_mode.lua": z.object({
name: z.literal("use_manual_mode.lua"),
type: z.literal("file"),
extension: z.literal("lua"),
stem: z.literal("use_manual_mode."),
}),
}),
}),
"initial-file.txt": z.object({
name: z.literal("initial-file.txt"),
type: z.literal("file"),
Expand Down Expand Up @@ -74,6 +92,12 @@ export const MyTestDirectorySchema = z.object({
}),
}),
}),
"line-file.lua": z.object({
name: z.literal("line-file.lua"),
type: z.literal("file"),
extension: z.literal("lua"),
stem: z.literal("line-file."),
}),
"other-file.lua": z.object({
name: z.literal("other-file.lua"),
type: z.literal("file"),
Expand All @@ -95,13 +119,17 @@ export const testDirectoryFiles = z.enum([
".config/nvim/init.lua",
".config/nvim",
".config",
"config-modifications/.gitkeep",
"config-modifications/use_manual_mode.lua",
"config-modifications",
"initial-file.txt",
"limited/main-project-file.lua",
"limited/subproject/example.clj",
"limited/subproject/file1.lua",
"limited/subproject/file2.lua",
"limited/subproject",
"limited",
"line-file.lua",
"other-file.lua",
".",
])
Expand Down
68 changes: 68 additions & 0 deletions integration-tests/cypress/e2e/blink-ripgrep/basic_spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,74 @@ describe("the basics", () => {
cy.contains(dir.contents["other-file.lua"].name)
})
})

it("allows invoking manually as a blink-cmp keymap", () => {
cy.visit("/")
cy.startNeovim({
startupScriptModifications: ["use_manual_mode.lua"],
}).then(() => {
// wait until text on the start screen is visible
cy.contains("If you see this text, Neovim is ready!")
createFakeGitDirectoriesToLimitRipgrepScope()

// clear the current line and enter insert mode
cy.typeIntoTerminal("cc")

// type some text that will match, but add a space so that we can make
// sure the completion is not shown automatically (the previous word is
// not found after a space)
cy.typeIntoTerminal("hip {backspace}")

// get back into position and invoke the completion manually
cy.typeIntoTerminal("{control+g}")
cy.contains("Hippopotamus" + "234 (rg)")
})
})
})

describe("the match context", () => {
// The match context means the lines around the matched line.
// We want to show context so that the user can see/remember where the match
// was found. Although we don't explicitly show all the matches in the
// project, this can still be very useful.
it("shows 5 lines around the match by default", () => {
cy.visit("/")
cy.startNeovim().then(() => {
cy.contains("If you see this text, Neovim is ready!")
createFakeGitDirectoriesToLimitRipgrepScope()

cy.typeIntoTerminal("cc")

// find a match that has more than 5 lines of context
cy.typeIntoTerminal("line_7")

// we should now see lines 2-12 (default 5 lines of context around the match)
cy.contains(`"This is line 1"`).should("not.exist")
assertMatchVisible(`"This is line 2"`)
assertMatchVisible(`"This is line 3"`)
assertMatchVisible(`"This is line 4"`)
assertMatchVisible(`"This is line 5"`)
assertMatchVisible(`"This is line 6"`)
assertMatchVisible(`"This is line 7"`) // the match
assertMatchVisible(`"This is line 8"`)
assertMatchVisible(`"This is line 9"`)
assertMatchVisible(`"This is line 10"`)
assertMatchVisible(`"This is line 11"`)
assertMatchVisible(`"This is line 12"`)
cy.contains(`"This is line 13"`).should("not.exist")
})
})

function assertMatchVisible(
match: string,
color?: typeof flavors.macchiato.colors.green.rgb,
) {
cy.contains(match).should(
"have.css",
"color",
rgbify(color ?? flavors.macchiato.colors.green.rgb),
)
}
})

describe("searching inside projects", () => {
Expand Down
41 changes: 19 additions & 22 deletions integration-tests/test-environment/.config/nvim/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,43 +37,33 @@ local plugins = {
dir = "/Users/mikavilpas/git/blink.cmp/",
event = "VeryLazy",
-- use a release tag to download pre-built binaries
version = "v0.*",
-- version = "v0.*",

-- to (locally) track nightly builds, use the following:
-- dir = "/Users/mikavilpas/git/blink.cmp/",
version = false,
dir = "/Users/mikavilpas/git/blink.cmp/",
build = "cargo build --release",

---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
sources = {
completion = {
enabled_providers = {
"buffer",
"ripgrep",
},
default = {
"buffer",
"ripgrep",
},
providers = {
ripgrep = {
module = "blink-ripgrep",
name = "Ripgrep",
---@type blink-ripgrep.Options
opts = {
--
},
-- opts = {
-- Keep the default options empty for tests, so that the we can
-- make sure they are supported without specifying them
-- },
},
},
},
-- configuration for the stable version of blink
windows = {
autocomplete = {
max_height = 25,
},
documentation = {
auto_show = true,
auto_show_delay_ms = 0,
-- file names need to fit the screen when testing
max_width = 200,
},
},

-- 2024-11-28 configuration for the nightly version of blink. mikavilpas
-- uses this for local development, but currently ci uses the stable
Expand All @@ -95,6 +85,13 @@ local plugins = {
max_height = 25,
},
},
keymap = {
["<c-g>"] = {
function()
require("blink-cmp").show({ providers = { "ripgrep" } })
end,
},
},
},
},
{
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
local blink_config = require("blink.cmp.config")

-- prevent showing completions automatically so that we can test invoking them
-- manually
blink_config.sources.default = { "buffer" }
20 changes: 20 additions & 0 deletions integration-tests/test-environment/line-file.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local line_1 = "This is line 1"
local line_2 = "This is line 2"
local line_3 = "This is line 3"
local line_4 = "This is line 4"
local line_5 = "This is line 5"
local line_6 = "This is line 6"
local line_7 = "This is line 7"
local line_8 = "This is line 8"
local line_9 = "This is line 9"
local line_10 = "This is line 10"
local line_11 = "This is line 11"
local line_12 = "This is line 12"
local line_13 = "This is line 13"
local line_14 = "This is line 14"
local line_15 = "This is line 15"
local line_16 = "This is line 16"
local line_17 = "This is line 17"
local line_18 = "This is line 18"
local line_19 = "This is line 19"
local line_20 = "This is line 20"
Loading

0 comments on commit 120284f

Please sign in to comment.