natecraddock / telescope-zf-native.nvim

native telescope bindings to zf for sorting results
MIT License
145 stars 5 forks source link
neovim sorter telescope zf zig

telescope-zf-native.nvim

native telescope bindings to zf for sorting results.

Try it online!

In short, zf is a filepath fuzzy finder. It is designed for better matching on filepaths than fzf or fzy. Matches on filenames are prioritized, and the strict path matching feature helps narrow down directory trees with precision. See the zf repo for full details. Some highlights:

Why

By default, telescope uses a sorter implemented in Lua. This is fine, but performance can suffer on larger lists of data.

telescope-zf-native.nvim is a telescope extension that provides a more performant natively-compiled sorter written in Zig with more accurate filename matching using the zf algorithm. Pre-compiled libzf binaries are included. See below for the current list of supported platforms and architectures.

The zf algorithm

See the zf repo for more information on the algorithm and standalone executable (a replacement for fzf or fzy). But here's a short summary:

After analyzing filenames from over 50 git repositories selected randomly from GitHub, I concluded that the majority of filenames are unique in a project. I used this in designing the zf algorithm to make a fuzzy-finder that is optimized for filtering filepaths.

With these heuristics, zf does a really good job sorting the desired file to the top of the results list. But there are plenty of files that share the same or similar names like init.lua or __init__.py for example. zf parses the query string as a list of space-delimited tokens to easily refine the search results when the first match isn't the wanted file. Simply append further terms to the query to narrow down the results.

Installation

Install in neovim with a package manager like packer.nvim or vim-plug.

--- packer
use "natecraddock/telescope-zf-native.nvim"

If you are using lazy.nvim and experience troubles installing the plugin, try something like the following (see this issue for more details):

require('lazy').setup('my_plugins', { rocks = { enabled = false } })

Then load the extension in telescope with default settings.

require("telescope").load_extension("zf-native")

The default config replaces the default telescope sorters with zf for all sorting. To confirm that the extension loaded properly, and to view the current settings, run :checkhealth zf-native.

For additional configuration, use the following:

require("telescope").setup({
    extensions = {
        ["zf-native"] = {
            -- options for sorting file-like items
            file = {
                -- override default telescope file sorter
                enable = true,

                -- highlight matching text in results
                highlight_results = true,

                -- enable zf filename match priority
                match_filename = true,

                -- optional function to define a sort order when the query is empty
                initial_sort = nil,

                -- set to false to enable case sensitive matching
                smart_case = true,
            },

            -- options for sorting all other items
            generic = {
                -- override default telescope generic item sorter
                enable = true,

                -- highlight matching text in results
                highlight_results = true,

                -- disable zf filename match priority
                match_filename = false,

                -- optional function to define a sort order when the query is empty
                initial_sort = nil,

                -- set to false to enable case sensitive matching
                smart_case = true,
            },
        }
    },
})

require("telescope").load_extension("zf-native")

The above settings are the default, so if you are satisfied with the defaults there is no need to change anything.

Example initial_sort function

The initial_sort function is used when the query is empty.

Here is an example that prioritizes .lua files

['zf-native'] = {
  file = {
    initial_sort = function (line)
      if line:match('.lua$') then
        return 0
      end
      return 1
    end
  }
}

The function accepts a line to rank and should return a number between 0 and 1, with numbers closer to 0 giving the line a higher priority.

Supported Platforms

The lib/ directory contains libzf pre-compiled libraries for:

If your OS is not supported, or there are issues loading the libraries please submit an issue. For requests of support of new platforms or any other issue, please include the output of :checkhealth zf-native in the issue.

Related

I also thank the developers who worked on these projects as my reference for using the LuaJIT FFI.