Closed bengolds closed 9 months ago
Not sure if it helps, but there is a plugin called telescope-frecency: https://github.com/nvim-telescope/telescope-frecency.nvim
Ohhhhhh, I also want to show off oldfiles
first when I use find_files
, It's really convenience for quick navigation to recent used files.
I found a hidden API named on_input_filter_cb
in telescope's source code. The on_input_filter_cb
accepts a query string parameter named prompt. So you can do some logic in this callback function. When prompt is empty, you can use oldfiles
's results. When prompt is not empty, you can use find_files
's results. You can also find a use case in @tjdevries 's repo.
The draft code is as follows, But it is not complete, You can find the missing functionality in telescope's source code.
local pickers = require "telescope.pickers"
local finders = require "telescope.finders"
local make_entry = require "telescope.make_entry"
local enhance_find_files = function(opts)
local results = {} -- telescope oldfiles results
pickers
.new(opts, {
prompt_title = "OOOOOOOO",
finder = finders.new_table {
results = results,
entry_maker = opts.entry_maker or make_entry.gen_from_file(opts),
},
sorter = conf.file_sorter(opts),
previewer = conf.file_previewer(opts),
on_input_filter_cb = function(prompt)
local is_empty = prompt == nil or prompt == ""
if is_empty then
return {
prompt = prompt,
updated_finder = finders.new_table {
results = results,
entry_maker = opts.entry_maker or make_entry.gen_from_file(opts),
},
}
end
-- use telescope built-in find_files.
return {
prompt = prompt,
updated_finder = finders.new_oneshot_job(find_command, opts),
}
end,
})
:find()
end
I simply copied Telescope's source code to make an extension and that works pretty well. Hope this works for you.
@trickstival -- sadly, that extension doesn't quite work. Its fallback to searching the whole directory is super slow right now.
@iwfan -- I'll give that a try -- thanks for sharing the code!
See this comment in the ripgrep repo for info on how to sort the results correctly: https://github.com/BurntSushi/ripgrep/issues/2243#issuecomment-1622559768
Using that ripgrep patch, I got exactly the expected results with good performance. If you want to preserve the order when searching, try a non-fuzzy sorter.
Using the sorter function defined here, you get priority for recent files.
@bengolds Have you found a way to do this?
Hi all. I cobbled together a custom file sorter for find_files
based on Telescope's default fzy sorter that simply doubles the score if the file is open (i.e. matches an open buffer).
It seems to work a little like VS Code's file picker.
Let me know your thoughts. I'm sure it could be improved. :)
https://github.com/gbroques/neovim-configuration/commit/e8a434d6ba0f97205517873fe3f224d14f893154
local telescope = require('telescope')
local sorters = require('telescope.sorters')
local fzy_sorter = sorters.get_fzy_sorter()
local filter = vim.tbl_filter
-- Copied from:
-- https://github.com/nvim-telescope/telescope.nvim/blob/dc192faceb2db64231ead71539761e055df66d73/lua/telescope/builtin/__internal.lua#L17-L29
local function apply_cwd_only_aliases(opts)
local has_cwd_only = opts.cwd_only ~= nil
local has_only_cwd = opts.only_cwd ~= nil
if has_only_cwd and not has_cwd_only then
-- Internally, use cwd_only
opts.cwd_only = opts.only_cwd
opts.only_cwd = nil
end
return opts
end
-- Copied from:
-- https://github.com/nvim-telescope/telescope.nvim/blob/dc192faceb2db64231ead71539761e055df66d73/lua/telescope/builtin/__internal.lua#L872-L923
local get_buffers = function(opts)
opts = opts or {}
opts = apply_cwd_only_aliases(opts)
local bufnrs = filter(function(b)
if 1 ~= vim.fn.buflisted(b) then
return false
end
-- only hide unloaded buffers if opts.show_all_buffers is false, keep them listed if true or nil
if opts.show_all_buffers == false and not vim.api.nvim_buf_is_loaded(b) then
return false
end
if opts.ignore_current_buffer and b == vim.api.nvim_get_current_buf() then
return false
end
if opts.cwd_only and not string.find(vim.api.nvim_buf_get_name(b), vim.loop.cwd(), 1, true) then
return false
end
if not opts.cwd_only and opts.cwd and not string.find(vim.api.nvim_buf_get_name(b), opts.cwd, 1, true) then
return false
end
return true
end, vim.api.nvim_list_bufs())
if not next(bufnrs) then
return
end
if opts.sort_mru then
table.sort(bufnrs, function(a, b)
return vim.fn.getbufinfo(a)[1].lastused > vim.fn.getbufinfo(b)[1].lastused
end)
end
local buffers = {}
for _, bufnr in ipairs(bufnrs) do
local flag = bufnr == vim.fn.bufnr "" and "%" or (bufnr == vim.fn.bufnr "#" and "#" or " ")
local element = {
bufnr = bufnr,
flag = flag,
info = vim.fn.getbufinfo(bufnr)[1],
}
if opts.sort_lastused and (flag == "#" or flag == "%") then
local idx = ((buffers[1] ~= nil and buffers[1].flag == "%") and 2 or 1)
table.insert(buffers, idx, element)
else
table.insert(buffers, element)
end
end
return buffers
end
local is_file_open = function(line)
local buffers = get_buffers()
if not buffers then
return false
end
-- TODO: This may not be performant if there are many open buffers.
-- We could implement a map / lookup table instead.
for _, buffer in ipairs(buffers) do
local buffer_name = buffer.info.name
if vim.endswith(buffer_name, line) then
return true
end
end
return false
end
-- Copied from:
-- https://github.com/nvim-telescope/telescope.nvim/blob/dc192faceb2db64231ead71539761e055df66d73/lua/telescope/sorters.lua#L437-L466
-- Sorter using the fzy algorithm
local file_sorter = function(opts)
opts = opts or {}
local fzy = opts.fzy_mod or require "telescope.algos.fzy"
local OFFSET = -fzy.get_score_floor()
return sorters.Sorter:new {
discard = fzy_sorter.discard,
scoring_function = function(_, prompt, line)
-- Check for actual matches before running the scoring alogrithm.
if not fzy.has_match(prompt, line) then
return -1
end
local fzy_score = fzy.score(prompt, line)
-- The fzy score is -inf for empty queries and overlong strings. Since
-- this function converts all scores into the range (0, 1), we can
-- convert these to 1 as a suitable "worst score" value.
if fzy_score == fzy.get_score_min() then
return 1
end
-- CUSTOM CODE ADDED HERE 👇
-- Double score if file is open.
-- TODO: Score boost could take into account sort order of buffers.
-- Like which one was last used.
if is_file_open(line) then
fzy_score = fzy_score * 2
end
-- END CUSTOM CODE
-- Poor non-empty matches can also have negative values. Offset the score
-- so that all values are positive, then invert to match the
-- telescope.Sorter "smaller is better" convention. Note that for exact
-- matches, fzy returns +inf, which when inverted becomes 0.
return 1 / (fzy_score + OFFSET)
end,
highlighter = fzy_sorter.highlighter
}
end
telescope.setup {
defaults = {
file_sorter = file_sorter,
-- config omitted for brevity ...
},
-- config omitted for brevity ...
}
This is what you are looking for https://github.com/danielfalk/smart-open.nvim
This is what you are looking for https://github.com/danielfalk/smart-open.nvim
Just started playing with this plugin and it's really good.
I'm going to mark this as closed. I don't think there's any intention to add this to telescope core especially considering there are a few telescope extensions tackling this.
Hi, I made an extension to solve this. Might document it later. https://github.com/mollerhoj/telescope-recent-files.nvim
Install with
{
'nvim-telescope/telescope.nvim',
tag = '0.1.5',
dependencies = {
'mollerhoj/telescope-recent-files.nvim',
},
config = function()
require("telescope").load_extension("recent-files")
end
},
-- A keymap
vim.keymap.set('n', '<leader>f', function()
require('telescope').extensions['recent-files'].recent_files({})
end, { noremap = true, silent = true })
When I do a file search, it'd be great if information on my recently opened files was included in order to: 1) Speed up the file fuzzy search 2) Sort recently opened files to the top.
I believe this is the default behavior of the VSCode file picker.
I can't figure out how to do this, so I'm not sure if I'm missing something -- do I need to combine picker sources?
fzf-frecency
seems to sort of do this, but is deadly slow when you try to include the files in the current workspace.