--- /dev/null
+
+local function project_search()
+ -- get identifier under the cursor
+ local word = vim.fn.expand("<cword>")
+ if word == "" then
+ vim.notify("(search-identifier) no identifier under the cursor found", vim.log.levels.WARN)
+ return
+ end
+
+ local cmd
+ local efm = "%f:%l:%c:%m" -- default error format for ripgrep
+
+ -- determine search tool (prio: ripgrep -> git grep -> grep)
+ if vim.fn.executable("rg") == 1 then
+ cmd = string.format("rg --vimgrep --smart-case --glob='!tags' %s", vim.fn.shellescape(word))
+ elseif vim.fn.executable("git") == 1 and vim.fn.system("git rev-parse --is-inside-work-tree") == "true\n" then
+ cmd = string.format("git grep -n %s -- ':!tags'", vim.fn.shellescape(word))
+ efm = "%f:%l:%m" -- error format for git grep
+ else
+ cmd = string.format("grep -rn --exclude=tags %s .", vim.fn.shellescape(word))
+ efm = "%f:%l:%m" -- error format for grep
+ end
+
+ -- execute command
+ local handle = io.popen(cmd)
+ if not handle then
+ vim.notify("(search-identifier) error while executing search command", vim.log.levels.ERROR)
+ return
+ end
+ local result = handle:read("*a")
+ handle:close()
+
+ if result == "" then
+ vim.notify("(search-identifier) no matches for '" .. word .. "' found.", vim.log.levels.INFO)
+ return
+ end
+
+ -- split results into lines
+ local lines = vim.split(result, "\n", { trimempty = true })
+
+ -- fill quickfix list
+ vim.fn.setqflist({}, "r", {
+ title = "search for: " .. word,
+ lines = lines,
+ efm = efm,
+ })
+
+ -- open quickfix window
+ vim.cmd("copen")
+ vim.notify(string.format("search for '%s' completed (%d matches).", word, #lines), vim.log.levels.INFO)
+end
+
+-- register user command (:ProjectSearch)
+vim.api.nvim_create_user_command("ProjectSearch", project_search, {})
+
+-- Tastenkombination im Normal-Modus: <leader>sw
+vim.keymap.set("n", "<leader>fi", project_search, {
+ desc = "search identifier under cursor in project",
+})
+