Intro
Being abble to change the scope of a srarch, grep or other commands gives us more control.
Finding the root dir
--- Returns project_root
--- @param bufnr number|nil Buffer
--- @return string root dir
M.root = function(bufnr)
bufnr = bufnr or 0
local markers = {
'.git',
'.hg',
'.svn',
'pyproject.toml',
'setup.py',
'requirements.txt',
'package.json',
'tsconfig.json',
'Makefile',
'CMakeLists.txt',
'.nvim-root',
}
return vim.fs.root(bufnr, markers) or vim.fn.getcwd()
end
Custom telescope find_files
This module will be called via keymap
-- File: ~/.config/nvim/lua/core/utils/telescope.lua
-- Last Change: 2025-06-23
-- Author: Sergio Araujo
local M = {}
local actions = require('telescope.actions')
local pickers = require('telescope.pickers')
local finders = require('telescope.finders')
local conf = require('telescope.config').values
local ts_utils = require('telescope.utils')
local builtin = require('telescope.builtin')
local utils = require('telescope.utils')
local get_root = require('core.utils.file_system').root
-- Função para path_display que remove prefixo Termux e mantém estilo tail+path
local function oldfiles_path_display(_, path)
local termux_prefix = '/data/data/com.termux/files/home/'
if path:sub(1, #termux_prefix) == termux_prefix then path = path:sub(#termux_prefix + 1) end
local tail = utils.path_tail(path)
local display = string.format('%s %s', tail, path)
local hl_start = #tail + 1
local hl_end = #display
return display, { { { hl_start, hl_end }, 'Comment' } }
end
-- Garante um diretório válido mesmo que buffer esteja vazio
local function get_valid_buf_dir()
local dir = ts_utils.buffer_dir()
return (dir and dir ~= '') and dir or vim.loop.cwd()
end
-- Find files com toggle de cwd
M.find_files_with_toggle = function()
local root = get_root()
if not root or root == '' then
vim.notify('Root dir não encontrado. Você está fora de um projeto?', vim.log.levels.WARN, {
title = 'Find Files',
})
return
end
local buf_dir = get_valid_buf_dir()
local current_cwd = root
local function picker()
builtin.find_files({
cwd = current_cwd,
attach_mappings = function(prompt_bufnr, map)
map('i', '<a-d>', function()
actions.close(prompt_bufnr)
local new_cwd = (current_cwd == root) and buf_dir or root
local title = 'Find Files'
if new_cwd ~= current_cwd then
current_cwd = new_cwd
vim.notify('cwd switched to: ' .. current_cwd, vim.log.levels.INFO, { title = title })
else
vim.notify('cwd não foi alterado (já em ' .. current_cwd .. ')', vim.log.levels.WARN, { title = title })
end
picker()
end)
return true
end,
})
end
picker()
end
-- Grep customizado com toggle de cwd e preservação do prompt
M.custom_grep_with_toggle = function()
local root = get_root()
if not root or root == '' then
vim.notify('Root dir não encontrado. Você está fora de um projeto?', vim.log.levels.WARN, {
title = 'Custom Grep',
})
return
end
local buf_dir = get_valid_buf_dir()
local current_cwd = root
local current_prompt = ''
local function picker()
pickers
.new({}, {
prompt_title = 'Custom Grep',
finder = finders.new_job(function(prompt)
if prompt == '' then return nil end
current_prompt = prompt
return { 'rg', '--vimgrep', '--no-heading', prompt }
end, nil, { cwd = current_cwd }),
previewer = conf.grep_previewer({}),
sorter = conf.generic_sorter({}),
default_text = current_prompt,
attach_mappings = function(prompt_bufnr, map)
map('i', '<a-d>', function()
actions.close(prompt_bufnr)
local new_cwd = (current_cwd == root) and buf_dir or root
local title = 'Custom Grep'
if new_cwd ~= current_cwd then
current_cwd = new_cwd
vim.notify('cwd switched to: ' .. current_cwd, vim.log.levels.INFO, { title = title })
else
vim.notify('cwd não foi alterado (já em ' .. current_cwd .. ')', vim.log.levels.WARN, { title = title })
end
picker()
end)
return true
end,
})
:find()
end
picker()
end
-- Oldfiles com path_display customizado para Termux
M.oldfiles_clean = function()
builtin.oldfiles({
path_display = oldfiles_path_display,
layout_strategy = 'vertical', -- ou "horizontal", conforme preferir
layout_config = {
height = 0.5, -- aqui você diminui a altura (0.3 = 30% da tela)
width = 0.7, -- opcional: ajustar largura também
prompt_position = 'top',
preview_cutoff = 1, -- para esconder preview em telas pequenas
},
})
end
return M
The keymaps
In your telescope keys table place
-- Adjust the module path to reflect you realitty
{
'<leader>ff',
function() require('core.utils.telescope').find_files_with_toggle() end,
desc = 'Find Files (toggle raiz/buffer com Alt+D)',
},
{
'<leader>fg',
function() require('core.utils.telescope').custom_grep_with_toggle() end,
desc = 'Custom Grep (rg) toggle root/buffer com <A-d>',
},
Top comments (4)
First of all, thank you for sharing your code and your ideas. Since there are different levels of users on this platform, from basic to senior, if you briefly state in the title of the article who the article is written for and how they will use it, you can help people get an idea about the article before moving on.
My second suggestion is that if you do not want to write a long article but want to explain your code; After pasting your script via ChatGPT, you can make your code more understandable for those who are not Lua literate with the help of the "Break apart the code and add line by line comments" prompt. In this way, it will be a clearer sharing and will be open to development.
ChatGPT code break apart sample for your first script:
Here's a line-by-line breakdown of your Lua function with inline comments and explanations:
bufnr
: Optional buffer number.root
in tableM
.bufnr
(buffer number).bufnr
is not provided (nil
), default to0
, which refers to the current buffer..git
,.hg
,.svn
) and build/config files for Python, Node.js, C/C++, etc.vim.fs.root(bufnr, markers)
to find the nearest ancestor directory of the buffer that contains one of the markers.vim.fn.getcwd()
.Summary
This function:
Related Keywords
neovim
,vim.fs.root
,project root detection
,lua
,vim.fn.getcwd
,LSP
,buffer
,marker files
,file system traversal
.Fantastic suggestion! I really apreciate!
Thank you for your understanding. We are here to support each other to improve our common knowledge. I'm using this special technique to analyze Github Repositories (dotfiles, Rust Repos etc.). It helps me to understand the code quickly. See you at your new article Sergio!
Keep writing, keep sharing, keep learning ;)