No description
Find a file
Ade Attwood 91b6db9d76 feat: split out register backend so it can be used as an external API
Summary:

Split out the register backend function from being a private function. A
backend is a table that will define all of the attributes for a run function.
The attributes are as follows:

- **command** The name of the command that will be registered as a vim user command.
- **items** The callback function that will be passed to the run function that will gather the items for selection
- **callback** The callback function run when an item is selected

The following are optional:

- **keymap** The string passed to `nvim_set_keymap`, this will always be registered in normal mode
- **description** The text description that will be used in the user command
- **name** The name of the backend, this will fallback to the command if its not set

It will also allow to register a backend in a couple of different ways:

- With a backend module table
- With a backend module name
- With a backend module name and override options

This will look for for a lua module `ivy.backends.files`. The module will be
required and registered as a backend.

```lua
register_backend "ivy.backends.files"
```

This will do the same with the module string however, before the backend is
registered the keymap will be overridden

```lua
register_backend({ "ivy.backends.file", { keymap = "<C-p>" } })
```

Test Plan:

CI / Manual testing locally
2024-06-27 21:12:37 +01:00
.github test: remove all the old tests 2024-06-16 17:23:45 +01:00
assets feat: add logo 2022-10-01 11:11:38 +01:00
benches Add benchmarks and an example bin for profiling 2022-08-26 14:20:17 +01:00
examples Remove multithreading for sorting 2022-08-26 16:29:11 +01:00
fixtures feat: add benchmarks 2022-08-07 16:41:51 +01:00
lua/ivy feat: split out register backend so it can be used as an external API 2024-06-27 21:12:37 +01:00
plugin feat: split out register backend so it can be used as an external API 2024-06-27 21:12:37 +01:00
rust feat: don't search in sapling source control directories 2024-01-17 21:15:24 +00:00
scripts test: move the suite over to busted 2024-06-16 17:17:16 +01:00
.gitignore Reduce lock contention (round 1) 2022-08-26 16:01:22 +01:00
.luacheckrc test: move the suite over to busted 2024-06-16 17:17:16 +01:00
.stylua.toml chore: initial commit 2022-07-10 21:07:33 +01:00
Cargo.lock fix(deps): update rust crate rayon to 1.10.0 2024-03-25 08:48:35 +00:00
Cargo.toml fix(deps): update rust crate rayon to 1.10.0 2024-03-25 08:48:35 +00:00
post-merge.sample docs: add section about post-merge compiling 2023-03-03 07:22:08 +00:00
README.md feat: add Lazy.nvim installation to the readme 2024-06-12 07:40:11 +01:00
renovate.json chore: add renovate.json 2023-03-27 20:48:16 +01:00

ivy.vim

An ivy-mode port to neovim. Ivy is a generic completion mechanism for Emacs Nvim

Installation

Manually

git clone https://github.com/AdeAttwood/ivy.nvim ~/.config/nvim/pack/bundle/start/ivy.nvim

Plugin managers

Using lazy.nvim

{
    "AdeAttwood/ivy.nvim",
    build = "cargo build --release",
},

TODO: Add more plugin managers

Compiling

For the native searching, you will need to compile the shard library. You can do that by running the below command in the root of the plugin.

cargo build --release

You will need to have the rust toolchain installed. You can find more about that here

If you get a linker error you may need to install build-essential to get ld. This is a common issue if you are running the benchmarks in a VM

error: linker `cc` not found
  |
  = note: No such file or directory (os error 2)

To configure auto compiling you can use the post-merge git hook to compile the library automatically when you update the package. This works well if you are managing your plugins via git. For an example installation you can run the following command. NOTE: This will overwrite any post-merge hooks you have already installed.

cp ./post-merge.sample ./.git/hooks/post-merge

Features

Commands

A command can be run that will launch the completion UI

Command Key Map Description
IvyFd <leader>p Find files in your project with a custom rust file finder
IvyAg <leader>/ Find content in files using the silver searcher
IvyBuffers <leader>b Search though open buffers
IvyLines Search the lines in the current buffer
IvyWorkspaceSymbol Search for workspace symbols using the lsp workspace/symbol

Actions

Action can be run on selected candidates provide functionality

Action Description
Complete Run the completion function, usually this will be opening a file
Peek Run the completion function on a selection, but don't close the results window
Vertical Split Run the completion function in a new vertical split
Split Run the completion function in a new split

API

ivy.run

The ivy.run function is the core function in the plugin, it will launch the completion window and display the items from your items function. When the users accept one of the candidates with an action, it will call the callback function to in most cases open the item in the desired location.

  ---@param name string
  ---@param items fun(input: string): { content: string }[] | string
  ---@param callback fun(result: string, action: string)
  vim.ivy.run = function(name, items, callback) end

Name string

The name is the display name for the command and will be the name of the buffer in the completion window

Items fun(input: string): { content: string }[] | string

The items function is a function that will return the candidates to display in the completion window. This can return a string where each line will be a completion item. Or an array of tables where the content will be the completion item.

Callback fun(result: string, action: string)

The function that will run when the user selects a completion item. Generally this will open the item in the desired location. For example, in the file finder with will open the file in a new buffer. If the user selects the vertical split action it will open the buffer in a new vsplit

Example

  vim.ivy.run(
    -- The name given to the results window and displayed to the user
    "Title",
    -- Call back function to get all the candidates that will be displayed in
    -- the results window, The `input` will be passed in, so you can filter
    -- your results with the value from the prompt
    function(input)
      return {
        { content = "One" },
        { content = "Two" },
        { content = "Three" },
      }
    end,
    -- Action callback that will be called on the completion or peek actions.
    -- The currently selected item is passed in as the result.
    function(result) vim.cmd("edit " .. result) end
  )

Benchmarks

Benchmarks are of various tasks that ivy will do. The purpose of the benchmarks are to give us a baseline on where to start when trying to optimize performance in the matching and sorting, not to put ivy against other tools. When starting to optimize, you will probably need to get a baseline on your hardware.

There are fixtures provided that will create the directory structure of the kubernetes source code, from somewhere around commit sha 985c9202ccd250a5fe22c01faf0d8f83d804b9f3. This will create a directory tree of 23511 files a relative large source tree to get a good idea of performance. To create the source tree under /tmp/ivy-trees/kubernetes run the following command. This will need to be run for the benchmarks to run.

# Create the source trees
bash ./scripts/fixtures.bash

# Run the benchmark script
luajit ./scripts/benchmark.lua

Current benchmark status running on a e2-standard-2 2 vCPU + 8 GB memory VM running on GCP.

IvyRs (Lua)

Name Total Average Min Max
ivy_match(file.lua) 1000000x 04.153531 (s) 00.000004 (s) 00.000003 (s) 00.002429 (s)
ivy_files(kubernetes) 100x 03.526795 (s) 00.035268 (s) 00.021557 (s) 00.037127 (s)

IvyRs (Criterion)

Name Min Mean Max
ivy_files(kubernetes) 19.727 ms 19.784 ms 19.842 ms
ivy_match(file.lua) 2.6772 µs 2.6822 µs 2.6873 µs

CPP

Name Total Average Min Max
ivy_match(file.lua) 1000000x 01.855197 (s) 00.000002 (s) 00.000001 (s) 00.000177 (s)
ivy_files(kubernetes) 100x 14.696396 (s) 00.146964 (s) 00.056604 (s) 00.168478 (s)

Other stuff you might like

  • ivy-mode - An emacs package that was the inspiration for this nvim plugin
  • Command-T - Vim plugin I used before I started this one
  • telescope.nvim - Another competition plugin, lots of people are using