Git Product home page Git Product logo

telescope-zf-native.nvim's Introduction

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:

  • a match on the filename is prioritized over a match on the full path
  • a search including path separators enables "strict path matching"
    • this means each path segment in the query must be found in a path segment of the file
    • src/ would match src/index.js but not tests/routes/client/index.js
  • the search query is space-separated to make narrowing down results easier
    • searching for init.py would find several __init__.py files in a Python project
    • but a search for init.py c would match ./config/__init__.py (or any other paths also containing c)

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.

  • Matches on filenames are highly favored over filepath matches
  • Matches on the beginning of a word are prioritized over matches in the middle of a word
  • Non-sequential character matches are penalized

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:

  • linux (x86 and arm)
  • macos (x86 and arm)
  • windows (x86)

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.

telescope-zf-native.nvim's People

Contributors

dsully avatar mrcjkb avatar natecraddock avatar ntbbloodbath avatar whoissethdaniel avatar younger-1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

telescope-zf-native.nvim's Issues

`initial_sort` should not be applied to `oldfiles`

I noticed that the initial_sort for files also affects the oldfiles picker. This is somewhat unfortunate, since oldfiles is the one picker where the initial order of files actually makes sense as they are sorted by recency.

Applying the initial sort here basically makes the oldfiles picker worse. Could the oldfiles picker therefore be excluded from initial_sort?

FR: Initial sorting when the query is empty

Thanks for this sorter, it's definitely an improvement which definitely deserves to be more popular.


So one issue I have is the initial sorting of results. It seems that when the query is empty, this sorter just passes the results from fd through without any sorting.

Showcase

This initial order is often not desirable, as this results for example in Makefile and README always being placed at the top, even though they are files that are rarely accessed in comparison to other files.

One reasonable solution would be to sort specific files further to the top, e.g. prioritizing lua, js, py files over md and Makefiles. Since there are probably quite diverse preferences for initial sorting, it might also make sense to offer an option for an initial-sorting-function, working similarly to telescope's tiebreaker.

For reference and more details, see also the issue I opened at the telescope repo: nvim-telescope/telescope.nvim#2905

Uppercase searching doesn't work

If any query string contains uppercase letters no search results are returned. From the same directory using fd -t f | zf and uppercase letters works fine, so it seems the bug is in the interface between telescope and libzf, not in zf itself.

Looking for a maintainer

Hi! I hope you are all doing well!

I no longer use Neovim regularly, but I really would like to keep this plugin alive. It's been really simple to maintain, but I worry about the long-term.

So I'm looking for someone willing to step in and maintain this plugin. Either

  1. Someone who is willing to fork and create the new official project or
  2. Someone who wants to co-maintain the project

I think the second is the simplest, and no one has to update their configs to point to a new repository.

If no one steps up, I will try my best to make sure this works for as long as possible. But I won't make any promises. If a future Neovim release would cause an unreasonable amount of work for me to update this plugin, I probably wouldn't update it.

Sorry if that's sad news for anyone, and I apologize if this breaks someone's workflow someday. I don't think this plugin will stop working anytime soon, but if it does... ๐Ÿ˜ฌ

Probably the biggest risk in this breaking is a breaking change to Telescope.

candidates re-sorted on input with frecency.nvim

hey, there

great plugin y'all got going here. I use it everyday and it works real good

One thing I noticed is that, when used with https://github.com/nvim-telescope/telescope-frecency.nvim the candidates will get re-ordered as the user types an input.

I don't exactly know the sorting algorithm that gets used, but, while prioritizing basename as expected, the relative order of candidates won't stick.

I've tried this by inputting "wiki" to match the .wiki extension and the order between wiki files changes. Matching for my input works because I have no "wiki.something" path and "/some/path/file.wiki" has priority over "/wiki/path/file.something", but "/file/I/access/a/lot.wiki" will have lower priority "/other/file/I/have/visited/once.wiki"

I hope I've described the problem ok

Cannot get same results for the telescope plugin

First of all, thank you for the zf project. I really like it!

The issue I'm facing is that I can't seem to get the same results for the Telescope plugin when searching with an additional space-delimited token. Here are the screenshots I took with ZF (git ls-files and fd) and Telescope:

fd
git ls
telescope

MacOS 14.3
nvim 0.9.5

zf-native: require("zf-native.health").check()

Installation ~
- libzf library path: .../lib/libzf-osx-arm64.so
- OK libzf path is valid

Configuration
  - zf telescope file sorter enabled
    - highlights: true
    - filename score priority: true
  - zf telescope generic sorter enabled
    - highlights: true
    - filename score priority: false ~

Picker settings:

        pickers = {
          find_files = {
            theme = "dropdown",
            find_command = {
              "fd",
              "--type",
              "f",
              "--color=never",
              "--hidden",
              "--follow",
              "-E",
              ".git/*",
            },

Thank you in advance

Better sorting

When two paths rank the same, telescope will keep the results in the same order as given. That means that results like this are possible. It is preferable to match the shorter path, and then require an extra query term to match the longer path.

no such file or directory: libzf.so

Love your algorithm, sometimes fzf gets very annoying. I'm already getting better matches in the terminal!
The zf repo generates an executable, how do I build the library?

Ability to enhance sorting (e.g. MRU/recent files first in results)

Hi, I love your sorter! Finally something which prioritizes the proper parts in paths.

But I would like to merge three pickers which I often use and I hate that I need THREE of them separately:

  • oldfiles (because I want to browse recent files but it doesn't show already opened buffers so I need the next one in the list)
  • buffers (so I can browse in opened buffers but if I don't have the demanded file open or it's not in old_files then I would like to search in all files and that is the last one in this list)
  • find_files

I think that if I can prioritize recently used buffers/files in the sorted result then I don't have to switch between pickers.

Is that already possible with your sorter or not? :) Or if you can point me to the right direction where I should investigate of how to do it..

Sorting based on proximity to open buffer

Hey, thanks so much for this plugin, it has greatly improved my telescope experience :)

This is somewhat similar to #10 requests but based on a different criteria. If say I'm working in a large repo with a large amount of files that have the same name:

dir_a/
- file_1
- file_2
dir_b/
- file_1
- file_2

I would love to configure the sorting such that if I'm in dir_b/file_1 and I open Telescope and type file_2, the closest selection in Telescope is dir_b/file_2 even though alphabetically dir_a/ might be sooner.

Is that something achievable in the current sorting configuration or will I need to drop down and fiddle with Telescope comps myself? Thanks! :)

add hint how to correctly setup luarocks for luajit in neovim xor fetch artifacts in lazy

I have system-setup with lua 5.4 (default).
The error :Lazy sync shows

  Failed (1)
    โ— telescope-zf-native.nvim 0.11ms ๎ซ“ start
        ...al/share/nvim/lazy/lazy.nvim/lua/lazy/manage/task/fs.lua:9: /home/misterspoon/.local/share/nvim/lazy/telescope-zf-native.nvim should be a directory!
        `lua` version `5.1` needed, but found `Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio`
        `lua5.1` or `lua` version `5.1` not installed

        This plugin requires `luarocks`. Try one of the following:
         - fix your `luarocks` installation
         - enable `hererocks` with `opts.rocks.hererocks = true`
         - disable `luarocks` support completely with `opts.rocks.enabled = false`

See also lazy error folke/lazy.nvim#1575

If I change my usage of lazy to require('lazy').setup('my_plugins', { pkg = { sources = "" } }), then I get

Build (1)
โ— telescope-zf-native.nvim 0.33ms ๎ซ“ start     โ–  needs build
    dir     /home/misterspoon/.local/share/nvim/lazy/telescope-zf-native.nvim
    url     https://github.com/natecraddock/telescope-zf-native.nvim
    version 1.0.0
    tag     v1.0.0
    branch  master
    commit  3f565ad
    readme  README.md
  โœ” [task] fetch 2058.41ms
    Anfordern des Submoduls zf
    Anfordern des Submoduls zf/lib/ziglyph
  โœ” [task] status 14.55ms
  โœ” [task] checkout 0.08ms

The problem was introduced with d746bfa.

After experimentation I found out this worked:

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

However is that intended how it should be solved?

Feature: allow case sensitive setting

Hey. ๐Ÿ‘‹

I've been using this sorter for quite some time, and been very happy with it. Lately, I have been wanting to turn off the default smart casing though.

Would it be possible to add an option to enforce the result to be case sensitive?

All the best!

Recent feature in `builtin.current_buffer_fuzzy_find` crashes telescope

Since nvim-telescope/telescope.nvim#2909, we will get the following error when we do :Telescope current_buffer_fuzzy_find.

E5108: Error executing lua: ...plugins/telescope.nvim/lua/telescope/builtin/__files.lua:549: bad argument #1 to 'unpack'
 (table expected, got nil)
stack traceback:
        [C]: in function 'unpack'
        ...plugins/telescope.nvim/lua/telescope/builtin/__files.lua:549: in function 'run_replace_or_original'
        ...epro/plugins/telescope.nvim/lua/telescope/actions/mt.lua:65: in function 'key_func'
        ....repro/plugins/telescope.nvim/lua/telescope/mappings.lua:269: in function <....repro/plugins/telescope.nvim/l
ua/telescope/mappings.lua:268>

To reproduce this error:

local root = vim.fn.fnamemodify('./.repro', ':p')
for _, name in ipairs({ 'config', 'data', 'state', 'cache' }) do
  vim.env[('XDG_%s_HOME'):format(name:upper())] = root .. '/' .. name
end
local lazypath = root .. '/plugins/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    'https://github.com/folke/lazy.nvim.git',
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)
local plugins = {
  'folke/tokyonight.nvim',
  {
    'nvim-telescope/telescope.nvim',
    commit = 'fac5da839e23e7a4c17a332a640541cd59ebfbd5',
    lazy = false,
    dependencies = {
      'nvim-lua/plenary.nvim',
      'natecraddock/telescope-zf-native.nvim',
    },
    config = function()
      require('telescope').setup({
        extensions = { ['zf-native'] = { generic = { enable = true } } },
      })
      require('telescope').load_extension('zf-native')
    end,
  },
}
require('lazy').setup(plugins, { root = root .. '/plugins' })
vim.cmd.colorscheme('tokyonight')

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.