Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

My command-t fork #450

pchampio started this conversation in General
Nov 30, 2025 · 4 comments · 2 replies
Discussion options

Hi wincent!
I wanted to share my story about fuzzy finders, and how ultimately I'm using command-t.
Back in the days, I was a huge fan of: https://github.com/nixprime/cpsm because of it's results quality.
However, as it got harder and harder to install, to the point of now being impractical, so I got interested in other fuzzy file finder.
I tried many of them: fzf-lua,telescope,fff,LeaderF,command-t, but their matching algorithm never suited me.

Ultimately, my need might be too niche, so I decided to implement my own scoring algorithm.
Command-t is very simple to tinker with, because score.c is very much self contained.
So thanks for that!
As a bonus command-t being the fastest is a blast.

My modified score.c
In case you are interested I could open a PR, I'm just not sure it is something you want, the heuristics arn't as simplistic anymore.
And here are some cases that I my scoring algorithm boost more than the default one.

 local matcher = get_matcher({
 "impl/impl.py",
 "impl/a.py",
 })
 assert(matcher.match('impl')[1] == 'impl/impl.py', "instead: " .. matcher.match('impl')[1])
 local matcher = get_matcher({
 "nvim/lua/spec/very/log/path/to/the/cmp.lua",
 "config/mpv/mpv.conf",
 })
 assert(matcher.match('cmp')[1] == 'nvim/lua/spec/very/log/path/to/the/cmp.lua', "instead: " .. matcher.match('cmp')[1])
 local matcher = get_matcher({
 "python",
 "abpython",
 "installl/python",
 })
 assert(matcher.match('python')[1] == 'python', "instead: " .. matcher.match('python')[1])
 assert(matcher.match('python')[2] == 'installl/python', "instead: " .. matcher.match('python')[2])
 local matcher = get_matcher({
 "nvim/lua/spec/lsp.lua",
 "nvim/lua/settings/lua_ls.lua",
 })
 assert(matcher.match('luals')[1] == 'nvim/lua/settings/lua_ls.lua', "instead: " .. matcher.match('luals')[1])
You must be logged in to vote

Replies: 4 comments 2 replies

Comment options

I also made some adjustments to the UI to improve visibility.
I'm a fan of position = 'bottom', I always know where to look.
But there is a lot of text in the way (right split):
We have the statusline, the - Command-T [rg] -, the prompt, a separator line, and the first result in 5 lines, that a lot for my eyes.

image

My adjustment on the left is neater IMO.

fork.patch

You must be logged in to vote
1 reply
Comment options

Yeah, that's not unreasonable. Generally with changes like this I like to put them behind options, because people's preferences for this tend to be pretty personal/subjective. Again, if you want to put that patch into PR form we could take a look at it (if you don't want to provide options in your PR, that's fine too — me or somebody else may be able to take on that part of it).

Comment options

I have heard you multiple time talking about async. And I want to share my two cents.
On very-big project, (or on slow network drive, which is more my use case), we have to wait for the scanning to finish before the UI open and we can start typing.
It has happen multiple time, that after triggering Command-t, nvim get's blocked until the scanning finished. Which sometime breaks my flow.

Implementing live/async scanning/matching results into the search buffer isn't what I want. (And I agree with your note it isn't worth-it).

However, having the UI displayed, and being able to type the query, before the (full) scanner return would 'feel' faster, without having to implement live/async scanning/matching. Pretty much opening the UI on :CommandT, than having it wait for the scanner the return in the background before calling the matcher on the user prompt.

You must be logged in to vote
1 reply
Comment options

Yeah, I agree that would be nice, although I think the devil is in the details. Just pasting here what I said in the comment you linked to:

Async UIs are one of those things that sound good in practice, but it's actually quite hard to pull them off, as seen in the videos above: in my experience, it's far better to just make your sync operations fast enough that you can leave them sync, and for the repo sizes I'm working in, that's a viable option for now.

So, I like the idea of having some form of async scanning and there has been some prior discussion of it in various places, like these, for example:

If it can be done cleanly and non-flakily, I'm all for it — I just think it is probably harder than it sounds. 😁

Comment options

Command-t was the very simple to tinker with, because score.c is very much self contained. So thanks for that!

Yeah, that's good to hear. I tried to make it relatively modular, and with the Lua rewrite it got a bit cleaner overall because the C parts are "pure C" now as opposed to "C with references to Ruby VM types and functions sprinkled throughout".

My modified score.c In case you are interested I could open a PR, I'm just not sure it is something you want, the heuristics arn't as simplistic anymore. And here are some cases that I my scoring algorithm boost more than the default one.

I wouldn't mind seeing a PR if you care to send one (I skimmed your score.c but it would be nice to: a) see a diff; and b) run the benchmarks to see the impact on speed). I'm open to modifying the scoring algorithm if it doesn't run slower or cause existing tests to fail in bad ways (that is, if the alternative algorithm orders results in different ways, that could be ok as long as the difference is actually subjectively an improvement). The third factor to consider merging would be that it's error/warning-free, and the fourth would be readability/maintainability. All of those dimensions are easier to evaluate in a PR.

You must be logged in to vote
0 replies
Comment options

Thanks for your answers!
I’ll try to open some proper PRs sometime after Christmas—I mainly wanted to check first whether this would be of interest to you.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /