-
-
Notifications
You must be signed in to change notification settings - Fork 856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to make file name more visible in file path #2014
Comments
After that you should be able to do -- Format path as "file.txt (path\to\file\)"
path_display = function(opts, path)
local tail = require("telescope.utils").path_tail(path)
return string.format("%s (%s)", tail, path), { { { 1, #tail }, "Constant" } }
end, |
I too require this feature implemented. Thanks |
Yes please. I would love this too! |
Bumping +1 ;) |
agreed, this would be ace! |
nice. care to share the config snipet @towry ? |
@tjex The main part is lines between comment
|
omg I'd like to use this in all my pickers. the current default causes too much overload for my brain. @towry this looks fantastic! |
@towry Any chance you can post the code snippet here? I'm getting a 404 on clicking the link (repo is taken private?). |
@SandeepTuniki the snippet is there. |
Ah yes. Looks like the comment was updated from a link to the code snippet (thanks, @towry!) |
Thank you @towry for that great snippet, it inspired me to create custom Pickers for both File finders and Grep searchers. I'll leave it here if anyone wants to change their Pickers appearance easily, simply create a lua module file inside of your Available pickers are:live_grep require('ggv.telescopePickers').prettyGrepPicker({ picker = 'live_grep' }) grep_string require('ggv.telescopePickers').prettyGrepPicker({ picker = 'grep_string' }) git_files require('ggv.telescopePickers').prettyFilesPicker({ picker = 'git_files' }) find_files require('ggv.telescopePickers').prettyFilesPicker({ picker = 'find_files' }) oldfiles require('ggv.telescopePickers').prettyFilesPicker({ picker = 'oldfiles' }) telescopePickers.lua-- Declare the module
local telescopePickers = {}
-- Store Utilities we'll use frequently
local telescopeUtilities = require('telescope.utils')
local telescopeMakeEntryModule = require('telescope.make_entry')
local plenaryStrings = require('plenary.strings')
local devIcons = require('nvim-web-devicons')
local telescopeEntryDisplayModule = require('telescope.pickers.entry_display')
-- Obtain Filename icon width
-- --------------------------
-- INSIGHT: This width applies to all icons that represent a file type
local fileTypeIconWidth = plenaryStrings.strdisplaywidth(devIcons.get_icon('fname', { default = true }))
---- Helper functions ----
-- Gets the File Path and its Tail (the file name) as a Tuple
function telescopePickers.getPathAndTail(fileName)
-- Get the Tail
local bufferNameTail = telescopeUtilities.path_tail(fileName)
-- Now remove the tail from the Full Path
local pathWithoutTail = require('plenary.strings').truncate(fileName, #fileName - #bufferNameTail, '')
-- Apply truncation and other pertaining modifications to the path according to Telescope path rules
local pathToDisplay = telescopeUtilities.transform_path({
path_display = { 'truncate' },
}, pathWithoutTail)
-- Return as Tuple
return bufferNameTail, pathToDisplay
end
---- Picker functions ----
-- Generates a Find File picker but beautified
-- -------------------------------------------
-- This is a wrapping function used to modify the appearance of pickers that provide a Find File
-- functionality, mainly because the default one doesn't look good. It does this by changing the 'display()'
-- function that Telescope uses to display each entry in the Picker.
--
-- Adapted from: https://github.com/nvim-telescope/telescope.nvim/issues/2014#issuecomment-1541423345.
--
-- @param (table) pickerAndOptions - A table with the following format:
-- {
-- picker = '<pickerName>',
-- (optional) options = { ... }
-- }
function telescopePickers.prettyFilesPicker(pickerAndOptions)
-- Parameter integrity check
if type(pickerAndOptions) ~= 'table' or pickerAndOptions.picker == nil then
print("Incorrect argument format. Correct format is: { picker = 'desiredPicker', (optional) options = { ... } }")
-- Avoid further computation
return
end
-- Ensure 'options' integrity
options = pickerAndOptions.options or {}
-- Use Telescope's existing function to obtain a default 'entry_maker' function
-- ----------------------------------------------------------------------------
-- INSIGHT: Because calling this function effectively returns an 'entry_maker' function that is ready to
-- handle entry creation, we can later call it to obtain the final entry table, which will
-- ultimately be used by Telescope to display the entry by executing its 'display' key function.
-- This reduces our work by only having to replace the 'display' function in said table instead
-- of having to manipulate the rest of the data too.
local originalEntryMaker = telescopeMakeEntryModule.gen_from_file(options)
-- INSIGHT: 'entry_maker' is the hardcoded name of the option Telescope reads to obtain the function that
-- will generate each entry.
-- INSIGHT: The paramenter 'line' is the actual data to be displayed by the picker, however, its form is
-- raw (type 'any) and must be transformed into an entry table.
options.entry_maker = function(line)
-- Generate the Original Entry table
local originalEntryTable = originalEntryMaker(line)
-- INSIGHT: An "entry display" is an abstract concept that defines the "container" within which data
-- will be displayed inside the picker, this means that we must define options that define
-- its dimensions, like, for example, its width.
local displayer = telescopeEntryDisplayModule.create({
separator = ' ', -- Telescope will use this separator between each entry item
items = {
{ width = fileTypeIconWidth },
{ width = nil },
{ remaining = true },
},
})
-- LIFECYCLE: At this point the "displayer" has been created by the create() method, which has in turn
-- returned a function. This means that we can now call said function by using the
-- 'displayer' variable and pass it actual entry values so that it will, in turn, output
-- the entry for display.
--
-- INSIGHT: We now have to replace the 'display' key in the original entry table to modify the way it
-- is displayed.
-- INSIGHT: The 'entry' is the same Original Entry Table but is is passed to the 'display()' function
-- later on the program execution, most likely when the actual display is made, which could
-- be deferred to allow lazy loading.
--
-- HELP: Read the 'make_entry.lua' file for more info on how all of this works
originalEntryTable.display = function(entry)
-- Get the Tail and the Path to display
local tail, pathToDisplay = telescopePickers.getPathAndTail(entry.value)
-- Add an extra space to the tail so that it looks nicely separated from the path
local tailForDisplay = tail .. ' '
-- Get the Icon with its corresponding Highlight information
local icon, iconHighlight = telescopeUtilities.get_devicons(tail)
-- INSIGHT: This return value should be a tuple of 2, where the first value is the actual value
-- and the second one is the highlight information, this will be done by the displayer
-- internally and return in the correct format.
return displayer({
{ icon, iconHighlight },
tailForDisplay,
{ pathToDisplay, 'TelescopeResultsComment' },
})
end
return originalEntryTable
end
-- Finally, check which file picker was requested and open it with its associated options
if pickerAndOptions.picker == 'find_files' then
require('telescope.builtin').find_files(options)
elseif pickerAndOptions.picker == 'git_files' then
require('telescope.builtin').git_files(options)
elseif pickerAndOptions.picker == 'oldfiles' then
require('telescope.builtin').oldfiles(options)
elseif pickerAndOptions.picker == '' then
print("Picker was not specified")
else
print("Picker is not supported by Pretty Find Files")
end
end
-- Generates a Grep Search picker but beautified
-- ----------------------------------------------
-- This is a wrapping function used to modify the appearance of pickers that provide Grep Search
-- functionality, mainly because the default one doesn't look good. It does this by changing the 'display()'
-- function that Telescope uses to display each entry in the Picker.
--
-- @param (table) pickerAndOptions - A table with the following format:
-- {
-- picker = '<pickerName>',
-- (optional) options = { ... }
-- }
function telescopePickers.prettyGrepPicker(pickerAndOptions)
-- Parameter integrity check
if type(pickerAndOptions) ~= 'table' or pickerAndOptions.picker == nil then
print("Incorrect argument format. Correct format is: { picker = 'desiredPicker', (optional) options = { ... } }")
-- Avoid further computation
return
end
-- Ensure 'options' integrity
options = pickerAndOptions.options or {}
-- Use Telescope's existing function to obtain a default 'entry_maker' function
-- ----------------------------------------------------------------------------
-- INSIGHT: Because calling this function effectively returns an 'entry_maker' function that is ready to
-- handle entry creation, we can later call it to obtain the final entry table, which will
-- ultimately be used by Telescope to display the entry by executing its 'display' key function.
-- This reduces our work by only having to replace the 'display' function in said table instead
-- of having to manipulate the rest of the data too.
local originalEntryMaker = telescopeMakeEntryModule.gen_from_vimgrep(options)
-- INSIGHT: 'entry_maker' is the hardcoded name of the option Telescope reads to obtain the function that
-- will generate each entry.
-- INSIGHT: The paramenter 'line' is the actual data to be displayed by the picker, however, its form is
-- raw (type 'any) and must be transformed into an entry table.
options.entry_maker = function(line)
-- Generate the Original Entry table
local originalEntryTable = originalEntryMaker(line)
-- INSIGHT: An "entry display" is an abstract concept that defines the "container" within which data
-- will be displayed inside the picker, this means that we must define options that define
-- its dimensions, like, for example, its width.
local displayer = telescopeEntryDisplayModule.create({
separator = ' ', -- Telescope will use this separator between each entry item
items = {
{ width = fileTypeIconWidth },
{ width = nil },
{ width = nil }, -- Maximum path size, keep it short
{ remaining = true },
},
})
-- LIFECYCLE: At this point the "displayer" has been created by the create() method, which has in turn
-- returned a function. This means that we can now call said function by using the
-- 'displayer' variable and pass it actual entry values so that it will, in turn, output
-- the entry for display.
--
-- INSIGHT: We now have to replace the 'display' key in the original entry table to modify the way it
-- is displayed.
-- INSIGHT: The 'entry' is the same Original Entry Table but is is passed to the 'display()' function
-- later on the program execution, most likely when the actual display is made, which could
-- be deferred to allow lazy loading.
--
-- HELP: Read the 'make_entry.lua' file for more info on how all of this works
originalEntryTable.display = function(entry)
---- Get File columns data ----
-------------------------------
-- Get the Tail and the Path to display
local tail, pathToDisplay = telescopePickers.getPathAndTail(entry.filename)
-- Get the Icon with its corresponding Highlight information
local icon, iconHighlight = telescopeUtilities.get_devicons(tail)
---- Format Text for display ----
---------------------------------
-- Add coordinates if required by 'options'
local coordinates = ""
if not options.disable_coordinates then
if entry.lnum then
if entry.col then
coordinates = string.format(" -> %s:%s", entry.lnum, entry.col)
else
coordinates = string.format(" -> %s", entry.lnum)
end
end
end
-- Append coordinates to tail
tail = tail .. coordinates
-- Add an extra space to the tail so that it looks nicely separated from the path
local tailForDisplay = tail .. ' '
-- Encode text if necessary
local text = options.file_encoding and vim.iconv(entry.text, options.file_encoding, "utf8") or entry.text
-- INSIGHT: This return value should be a tuple of 2, where the first value is the actual value
-- and the second one is the highlight information, this will be done by the displayer
-- internally and return in the correct format.
return displayer({
{ icon, iconHighlight },
tailForDisplay,
{ pathToDisplay, 'TelescopeResultsComment' },
text
})
end
return originalEntryTable
end
-- Finally, check which file picker was requested and open it with its associated options
if pickerAndOptions.picker == 'live_grep' then
require('telescope.builtin').live_grep(options)
elseif pickerAndOptions.picker == 'grep_string' then
require('telescope.builtin').grep_string(options)
elseif pickerAndOptions.picker == '' then
print("Picker was not specified")
else
print("Picker is not supported by Pretty Grep Picker")
end
end
-- Return the module for use
return telescopePickers |
Awesome, will be default for https://github.com/otavioschwanck/mood-nvim |
@towry do you have a buffers picker too? |
Here's an addition to @towry's for Can be used like so: vim.keymap.set('n', '<leader>fb', function() pickers.prettyBuffersPicker() end, opts)
vim.keymap.set('n', '<leader>fs', function() pickers.prettyDocumentSymbols() end, opts)
vim.keymap.set('n', '<leader>ws', function() pickers.prettyWorkspaceSymbols() end, opts) Append the below snippet to your local kind_icons = {
Text = "",
String = "",
Array = "",
Object = "",
Namespace = "",
Method = "m",
Function = "",
Constructor = "",
Field = "",
Variable = "",
Class = "",
Interface = "",
Module = "",
Property = "",
Unit = "",
Value = "",
Enum = "",
Keyword = "",
Snippet = "",
Color = "",
File = "",
Reference = "",
Folder = "",
EnumMember = "",
Constant = "",
Struct = "",
Event = "",
Operator = "",
TypeParameter = "",
Copilot = "🤖",
Boolean = "",
}
function telescopePickers.prettyDocumentSymbols(localOptions)
if localOptions ~= nil and type(localOptions) ~= 'table' then
print("Options must be a table.")
return
end
options = localOptions or {}
local originalEntryMaker = telescopeMakeEntryModule.gen_from_lsp_symbols(options)
options.entry_maker = function(line)
local originalEntryTable = originalEntryMaker(line)
local displayer = telescopeEntryDisplayModule.create({
separator = ' ',
items = {
{ width = fileTypeIconWidth },
{ width = 20 },
{ remaining = true },
},
})
originalEntryTable.display = function(entry)
return displayer {
string.format("%s", kind_icons[(entry.symbol_type:lower():gsub("^%l", string.upper))]),
{ entry.symbol_type:lower(), 'TelescopeResultsVariable' },
{ entry.symbol_name, 'TelescopeResultsConstant' },
}
end
return originalEntryTable
end
require('telescope.builtin').lsp_document_symbols(options)
end
function telescopePickers.prettyWorkspaceSymbols(localOptions)
if localOptions ~= nil and type(localOptions) ~= 'table' then
print("Options must be a table.")
return
end
options = localOptions or {}
local originalEntryMaker = telescopeMakeEntryModule.gen_from_lsp_symbols(options)
options.entry_maker = function(line)
local originalEntryTable = originalEntryMaker(line)
local displayer = telescopeEntryDisplayModule.create({
separator = ' ',
items = {
{ width = fileTypeIconWidth },
{ width = 15 },
{ width = 30 },
{ width = nil },
{ remaining = true },
},
})
originalEntryTable.display = function(entry)
local tail, _ = telescopePickers.getPathAndTail(entry.filename)
local tailForDisplay = tail .. ' '
local pathToDisplay = telescopeUtilities.transform_path({
path_display = { shorten = { num = 2, exclude = {-2, -1} }, 'truncate' },
}, entry.value.filename)
return displayer {
string.format("%s", kind_icons[(entry.symbol_type:lower():gsub("^%l", string.upper))]),
{ entry.symbol_type:lower(), 'TelescopeResultsVariable' },
{ entry.symbol_name, 'TelescopeResultsConstant' },
tailForDisplay,
{ pathToDisplay, 'TelescopeResultsComment' },
}
end
return originalEntryTable
end
require('telescope.builtin').lsp_dynamic_workspace_symbols(options)
end
function telescopePickers.prettyBuffersPicker(localOptions)
if localOptions ~= nil and type(localOptions) ~= 'table' then
print("Options must be a table.")
return
end
options = localOptions or {}
local originalEntryMaker = telescopeMakeEntryModule.gen_from_buffer(options)
options.entry_maker = function(line)
local originalEntryTable = originalEntryMaker(line)
local displayer = telescopeEntryDisplayModule.create {
separator = " ",
items = {
{ width = fileTypeIconWidth },
{ width = nil },
{ width = nil },
{ remaining = true },
},
}
originalEntryTable.display = function(entry)
local tail, path = telescopePickers.getPathAndTail(entry.filename)
local tailForDisplay = tail .. ' '
local icon, iconHighlight = telescopeUtilities.get_devicons(tail)
return displayer {
{ icon, iconHighlight },
tailForDisplay,
{ '(' .. entry.bufnr .. ')', "TelescopeResultsNumber" },
{ path, "TelescopeResultsComment" },
}
end
return originalEntryTable
end
require('telescope.builtin').buffers(options)
end |
maybe turn this into a proper extension and get easy stars 😁 |
@ClintWinter would be awesome to have a git_status too |
I'm using telescope a lot for lsp references and definitions and it's really hard to see what files are affected. Would be very cool if we had something similar for the lsp stuff too :) |
Love all the custom pickers shared here, but the snippets were all so large, making it daunting to customize them. So I came up with a much simpler solution. Works by coloring everything after two tabs in the telescope result window, though any other unique string will also work. (I checked, and apparently no telescope picker uses two consecutive tabs, so this does not seem to have any undesired side effects.) vim.api.nvim_create_autocmd("FileType", {
pattern = "TelescopeResults",
callback = function(ctx)
vim.api.nvim_buf_call(ctx.buf, function()
vim.fn.matchadd("TelescopeParent", "\t\t.*$")
vim.api.nvim_set_hl(0, "TelescopeParent", { link = "Comment" })
end)
end,
})
local function filenameFirst(_, path)
local tail = vim.fs.basename(path)
local parent = vim.fs.dirname(path)
if parent == "." then return tail end
return string.format("%s\t\t%s", tail, parent)
end
require("telescope").setup {
pickers = {
find_files = {
path_display = filenameFirst,
}
}
} |
Tried already. Doesn't work. Seems like this is a known bug though. |
This should be one of the default options, it looks great |
Thanks, can you please explain where this snippet should go? I'm new to both neovim and lua. |
Hi Itamar, https://github.com/silicakes/dotfiles/blob/main/.config/nvim/plugin/telescope.lua |
Files in results list now show filenames first, followed by file path, slightly but dimmed. This thanks to nvim-telescope/telescope.nvim#2014 (comment).
would it be possible to do something similar for LSP workspace diagnostics ? |
@kronolynx I actually got this entry maker going for a couple of days. It also shows the symbol icon and its qualifier then shows it instead of filepath if possible. Take a look: local M = {}
local entry_display = require('telescope.pickers.entry_display')
local symbol_to_icon_map = {
['class'] = { icon = ' ', hi = 'TelescopeResultClass' },
['type'] = { icon = ' ', hi = 'TelescopeResultClass' },
['struct'] = { icon = ' ', hi = 'TelescopeResultStruct' },
['enum'] = { icon = ' ', hi = 'TelescopeResultClass' },
['union'] = { icon = ' ', hi = 'TelescopeResultClass' },
['interface'] = { icon = ' ', hi = 'TelescopeResultMethod' },
['method'] = { icon = ' ', hi = 'TelescopeResultMethod' },
['function'] = { icon = 'ƒ ', hi = 'TelescopeResultFunction' },
['constant'] = { icon = ' ', hi = 'TelescopeResultConstant' },
['field'] = { icon = ' ', hi = 'TelescopeResultField' },
['property'] = { icon = ' ', hi = 'TelescopeResultField' }
}
local displayer = entry_display.create({
separator = ' ',
items = {
{ width = 2 },
{ remaining = true }
}
})
function M.maker()
local entry_maker = require('telescope.make_entry').gen_from_lsp_symbols({})
return function(line)
local originalEntryTable = entry_maker(line)
originalEntryTable.display = function (entry)
local kind_and_higr = symbol_to_icon_map[entry.symbol_type:lower()] or { icon = ' ', hi = 'TelescopeResultsNormal' }
local dot_idx = entry.symbol_name:reverse():find("%.") or entry.symbol_name:reverse():find("::")
local symbol, qualifiier
if dot_idx == nil then
symbol = entry.symbol_name
qualifiier = entry.filename
else
symbol = entry.symbol_name:sub(1 - dot_idx)
qualifiier = entry.symbol_name:sub(1, #entry.symbol_name - #symbol - 1)
end
return displayer({
{ kind_and_higr.icon, kind_and_higr.hi },
string.format("%s\t\tin %s", symbol, qualifiier)
})
end
return originalEntryTable
end
end
return M; And its used like this: require('telescope').setup({
pickers = {
lsp_dynamic_workspace_symbols = {
entry_maker = require('twoty.custom.telescope-symbol-entry-maker').maker()
}
},
}) Feel free to use this. And if anyone thinks of a way to make this better, please share and post it smiley face |
Here's one I made for grapple.nvim: function telescopePickers.prettyGrapplePicker(localOptions)
local Grapple = require("grapple")
if localOptions ~= nil and type(localOptions) ~= "table" then
print("Options must be a table.")
return
end
local options = localOptions or {}
local generate_finder = function()
local tags, err = Grapple.tags()
if not tags then
---@diagnostic disable-next-line: param-type-mismatch
return vim.notify(err, vim.log.levels.ERROR)
end
local results = {}
for i, tag in ipairs(tags) do
---@class grapple.telescope.result
local result = {
i,
tag.path,
tag.cursor and tag.cursor[1],
tag.cursor and tag.cursor[2],
}
table.insert(results, result)
end
local displayer = telescopeEntryDisplayModule.create({
separator = " ",
items = {
{ width = fileTypeIconWidth },
{ width = nil },
{ remaining = true },
},
})
return finders.new_table({
results = results,
---@param result grapple.telescope.result
entry_maker = function(result)
local filename = result[2]
local lnum = result[3]
local entry = {
value = result,
ordinal = filename,
filename = filename,
lnum = lnum,
display = function(entry)
local tail, pathToDisplay = telescopePickers.getPathAndTail(entry.value[2])
local icon, iconHighlight = telescopeUtilities.get_devicons(tail)
return displayer({
{ icon, iconHighlight },
{ tail },
{ pathToDisplay, "TelescopeResultsComment" },
})
end,
}
return entry
end,
})
end
local function delete_tag(prompt_bufnr)
local selection = action_state.get_selected_entry()
Grapple.untag({ path = selection.filename })
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:refresh(generate_finder(), { reset_prompt = true })
end
pickers
.new(options, {
prompt_title = "Grapple",
finder = generate_finder(),
sorter = conf.generic_sorter({}),
previewer = conf.file_previewer({}),
results_title = "Grapple Tags",
attach_mappings = function(_, map)
map("i", "<C-X>", delete_tag)
map("n", "<C-X>", delete_tag)
return true
end,
})
:find()
end |
Thank you @Twotyth but I was looking for workspace diagnostics |
Anyone here knows how to fix this? |
@marcelarie Here's what mine looks like and the code for it: function telescopePickers.prettyLspReferences(localOptions)
if localOptions ~= nil and type(localOptions) ~= "table" then
print("Options must be a table.")
return
end
local options = localOptions or {}
local originalEntryMaker = telescopeMakeEntryModule.gen_from_quickfix(options)
options.entry_maker = function(line)
local originalEntryTable = originalEntryMaker(line)
local displayer = telescopeEntryDisplayModule.create({
separator = " ", -- Telescope will use this separator between each entry item
items = {
{ width = fileTypeIconWidth },
{ width = nil },
{ remaining = true },
},
})
originalEntryTable.display = function(entry)
local tail, pathToDisplay = telescopePickers.getPathAndTail(entry.filename)
local tailForDisplay = tail .. " "
local icon, iconHighlight = telescopeUtilities.get_devicons(tail)
local coordinates = string.format(" %s:%s ", entry.lnum, entry.col)
return displayer({
{ icon, iconHighlight },
tailForDisplay .. coordinates,
{ pathToDisplay, "TelescopeResultsComment" },
})
end
return originalEntryTable
end
require("telescope.builtin").lsp_references(options)
end
|
Thanks @simeonoff, where should this function go in the telescope setup? |
@alycklama has put together a PR (#3010) for this. Does this sound good to everyone? Emote with 🚀 if you think it's reasonable or you can offer an alternative. |
I would rather suggest |
I agree, it's something I struggled with as the directory structure is actually reserved. Should it be called |
what speaks against |
I have nothing against the name, it's just not what my PR has implemented. Given the input What filename first would do
What reverse / inverse does
The reason I want to inverse the directory structure is because I work with deeply nested code, and I'm not interested in the top directories at all. What about calling it |
Oh that wasn't clear to me, as you mentioned in the PR text that you aimed for something similar to Intelij's UI, and I believe there it is not inverting the entire path, just putting the file name first, followed by the directory/package it is in. I think that's a bit more intuitive than inverting the entire path, what do you think? |
This sounds good to me. |
For anyone who also use fzf-lua: https://www.reddit.com/r/neovim/comments/1c1id24/vscode_like_path_display_in_fzfluas_files_picker/ |
Is your feature request related to a problem? Please describe.
When I use git_files or find_files on large project with a lot of directories, it is sometimes a bit hard to spot the filename from the rest of the path.
Describe the solution you'd like
I would really love to have a built-in option to bolden/put a colot emphasis on the file name in the results so I can quickly spot out the file name.
Describe alternatives you've considered
I've considered
But I am not sure how to handle coloring/bolding output in lua, I am a bit unfamiliar with the language.
Additional context
I would love to open a PR for this if you would have this feature, I may need a bit of help to get started though.
Thanks for the awesome work you guys have been doing !
The text was updated successfully, but these errors were encountered: