feat: rename search_keyword => grep_search (#1584)
This commit is contained in:
@@ -83,8 +83,8 @@ function M.search_files(opts, on_log)
|
|||||||
return vim.json.encode(filepaths), nil
|
return vim.json.encode(filepaths), nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type AvanteLLMToolFunc<{ rel_path: string, keyword: string }>
|
---@type AvanteLLMToolFunc<{ rel_path: string, query: string, case_sensitive?: boolean, include_pattern?: string, exclude_pattern?: string }>
|
||||||
function M.search_keyword(opts, on_log)
|
function M.grep_search(opts, on_log)
|
||||||
local abs_path = get_abs_path(opts.rel_path)
|
local abs_path = get_abs_path(opts.rel_path)
|
||||||
if not has_permission_to_access(abs_path) then return "", "No permission to access path: " .. abs_path end
|
if not has_permission_to_access(abs_path) then return "", "No permission to access path: " .. abs_path end
|
||||||
if not Path:new(abs_path):exists() then return "", "No such file or directory: " .. abs_path end
|
if not Path:new(abs_path):exists() then return "", "No such file or directory: " .. abs_path end
|
||||||
@@ -99,15 +99,32 @@ function M.search_keyword(opts, on_log)
|
|||||||
---execute the search command
|
---execute the search command
|
||||||
local cmd = ""
|
local cmd = ""
|
||||||
if search_cmd:find("rg") then
|
if search_cmd:find("rg") then
|
||||||
cmd = string.format("%s --files-with-matches --ignore-case --hidden --glob '!.git'", search_cmd)
|
cmd = string.format("%s --files-with-matches --hidden", search_cmd)
|
||||||
cmd = string.format("%s '%s' %s", cmd, opts.keyword, abs_path)
|
if opts.case_sensitive then
|
||||||
|
cmd = string.format("%s --case-sensitive", cmd)
|
||||||
|
else
|
||||||
|
cmd = string.format("%s --ignore-case", cmd)
|
||||||
|
end
|
||||||
|
if opts.include_pattern then cmd = string.format("%s --glob '%s'", cmd, opts.include_pattern) end
|
||||||
|
if opts.exclude_pattern then cmd = string.format("%s --glob '!%s'", cmd, opts.exclude_pattern) end
|
||||||
|
cmd = string.format("%s '%s' %s", cmd, opts.query, abs_path)
|
||||||
elseif search_cmd:find("ag") then
|
elseif search_cmd:find("ag") then
|
||||||
cmd = string.format("%s '%s' --nocolor --nogroup --hidden --ignore .git %s", search_cmd, opts.keyword, abs_path)
|
cmd = string.format("%s --nocolor --nogroup --hidden", search_cmd)
|
||||||
|
if opts.case_sensitive then cmd = string.format("%s --case-sensitive", cmd) end
|
||||||
|
if opts.include_pattern then cmd = string.format("%s --ignore '!%s'", cmd, opts.include_pattern) end
|
||||||
|
if opts.exclude_pattern then cmd = string.format("%s --ignore '%s'", cmd, opts.exclude_pattern) end
|
||||||
|
cmd = string.format("%s '%s' %s", cmd, opts.query, abs_path)
|
||||||
elseif search_cmd:find("ack") then
|
elseif search_cmd:find("ack") then
|
||||||
cmd = string.format("%s --nocolor --nogroup --hidden --ignore-dir .git", search_cmd)
|
cmd = string.format("%s --nocolor --nogroup --hidden", search_cmd)
|
||||||
cmd = string.format("%s '%s' %s", cmd, opts.keyword, abs_path)
|
if opts.case_sensitive then cmd = string.format("%s --smart-case", cmd) end
|
||||||
|
if opts.exclude_pattern then cmd = string.format("%s --ignore-dir '%s'", cmd, opts.exclude_pattern) end
|
||||||
|
cmd = string.format("%s '%s' %s", cmd, opts.query, abs_path)
|
||||||
elseif search_cmd:find("grep") then
|
elseif search_cmd:find("grep") then
|
||||||
cmd = string.format("%s -riH --exclude-dir=.git %s %s", search_cmd, opts.keyword, abs_path)
|
cmd = string.format("cd %s && git ls-files -co --exclude-standard | xargs %s -rH", abs_path, search_cmd, abs_path)
|
||||||
|
if not opts.case_sensitive then cmd = string.format("%s -i", cmd) end
|
||||||
|
if opts.include_pattern then cmd = string.format("%s --include '%s'", cmd, opts.include_pattern) end
|
||||||
|
if opts.exclude_pattern then cmd = string.format("%s --exclude '%s'", cmd, opts.exclude_pattern) end
|
||||||
|
cmd = string.format("%s '%s'", cmd, opts.query)
|
||||||
end
|
end
|
||||||
|
|
||||||
Utils.debug("cmd", cmd)
|
Utils.debug("cmd", cmd)
|
||||||
@@ -842,8 +859,8 @@ M._tools = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "search_keyword",
|
name = "grep_search",
|
||||||
description = "Search for a keyword in a directory",
|
description = "Search for a keyword in a directory using grep",
|
||||||
param = {
|
param = {
|
||||||
type = "table",
|
type = "table",
|
||||||
fields = {
|
fields = {
|
||||||
@@ -853,10 +870,29 @@ M._tools = {
|
|||||||
type = "string",
|
type = "string",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "keyword",
|
name = "query",
|
||||||
description = "Keyword to search for",
|
description = "Query to search for",
|
||||||
type = "string",
|
type = "string",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name = "case_sensitive",
|
||||||
|
description = "Whether to search case sensitively",
|
||||||
|
type = "boolean",
|
||||||
|
default = false,
|
||||||
|
optional = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "include_pattern",
|
||||||
|
description = "Glob pattern to include files",
|
||||||
|
type = "string",
|
||||||
|
optional = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "exclude_pattern",
|
||||||
|
description = "Glob pattern to exclude files",
|
||||||
|
type = "string",
|
||||||
|
optional = true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
returns = {
|
returns = {
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ vim.g.avante_login = vim.g.avante_login
|
|||||||
---@class AvanteLLMToolParamField
|
---@class AvanteLLMToolParamField
|
||||||
---@field name string
|
---@field name string
|
||||||
---@field description string
|
---@field description string
|
||||||
---@field type 'string' | 'integer'
|
---@field type 'string' | 'integer' | 'boolean'
|
||||||
---@field optional? boolean
|
---@field optional? boolean
|
||||||
|
|
||||||
---@class AvanteLLMToolReturn
|
---@class AvanteLLMToolReturn
|
||||||
|
|||||||
@@ -767,10 +767,7 @@ function M.scan_directory(options)
|
|||||||
cmd = {
|
cmd = {
|
||||||
"bash",
|
"bash",
|
||||||
"-c",
|
"-c",
|
||||||
string.format(
|
string.format("cd %s && git ls-files -co --exclude-standard", options.directory),
|
||||||
"cd %s && cat <(git ls-files --exclude-standard) <(git ls-files --exclude-standard --others)",
|
|
||||||
options.directory
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
cmd_supports_max_depth = false
|
cmd_supports_max_depth = false
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ describe("llm_tools", function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("search_keyword", function()
|
describe("grep_search", function()
|
||||||
local original_exepath = vim.fn.exepath
|
local original_exepath = vim.fn.exepath
|
||||||
|
|
||||||
after_each(function() vim.fn.exepath = original_exepath end)
|
after_each(function() vim.fn.exepath = original_exepath end)
|
||||||
@@ -147,10 +147,35 @@ describe("llm_tools", function()
|
|||||||
file:write("this is nothing")
|
file:write("this is nothing")
|
||||||
file:close()
|
file:close()
|
||||||
|
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = ".", keyword = "searchable" })
|
local result, err = LlmTools.grep_search({ rel_path = ".", query = "Searchable", case_sensitive = false })
|
||||||
assert.is_nil(err)
|
assert.is_nil(err)
|
||||||
assert.truthy(result:find("searchable.txt"))
|
assert.truthy(result:find("searchable.txt"))
|
||||||
assert.falsy(result:find("nothing.txt"))
|
assert.falsy(result:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result2, err2 = LlmTools.grep_search({ rel_path = ".", query = "searchable", case_sensitive = true })
|
||||||
|
assert.is_nil(err2)
|
||||||
|
assert.truthy(result2:find("searchable.txt"))
|
||||||
|
assert.falsy(result2:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result3, err3 = LlmTools.grep_search({ rel_path = ".", query = "Searchable", case_sensitive = true })
|
||||||
|
assert.is_nil(err3)
|
||||||
|
assert.falsy(result3:find("searchable.txt"))
|
||||||
|
assert.falsy(result3:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result4, err4 = LlmTools.grep_search({ rel_path = ".", query = "searchable", case_sensitive = false })
|
||||||
|
assert.is_nil(err4)
|
||||||
|
assert.truthy(result4:find("searchable.txt"))
|
||||||
|
assert.falsy(result4:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result5, err5 = LlmTools.grep_search({
|
||||||
|
rel_path = ".",
|
||||||
|
query = "searchable",
|
||||||
|
case_sensitive = false,
|
||||||
|
exclude_pattern = "search*",
|
||||||
|
})
|
||||||
|
assert.is_nil(err5)
|
||||||
|
assert.falsy(result5:find("searchable.txt"))
|
||||||
|
assert.falsy(result5:find("nothing.txt"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("should search using ag when rg is not available", function()
|
it("should search using ag when rg is not available", function()
|
||||||
@@ -166,7 +191,7 @@ describe("llm_tools", function()
|
|||||||
file:write("content for ag test")
|
file:write("content for ag test")
|
||||||
file:close()
|
file:close()
|
||||||
|
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = ".", keyword = "ag test" })
|
local result, err = LlmTools.grep_search({ rel_path = ".", query = "ag test" })
|
||||||
assert.is_nil(err)
|
assert.is_nil(err)
|
||||||
assert.is_string(result)
|
assert.is_string(result)
|
||||||
assert.truthy(result:find("ag_test.txt"))
|
assert.truthy(result:find("ag_test.txt"))
|
||||||
@@ -179,27 +204,64 @@ describe("llm_tools", function()
|
|||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = ".", keyword = "test" })
|
-- Create a test file with searchable content
|
||||||
|
local file = io.open(test_dir .. "/searchable.txt", "w")
|
||||||
|
if not file then error("Failed to create test file") end
|
||||||
|
file:write("this is searchable content")
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
file = io.open(test_dir .. "/nothing.txt", "w")
|
||||||
|
if not file then error("Failed to create test file") end
|
||||||
|
file:write("this is nothing")
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
local result, err = LlmTools.grep_search({ rel_path = ".", query = "Searchable", case_sensitive = false })
|
||||||
assert.is_nil(err)
|
assert.is_nil(err)
|
||||||
assert.truthy(result:find("test.txt"))
|
assert.truthy(result:find("searchable.txt"))
|
||||||
|
assert.falsy(result:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result2, err2 = LlmTools.grep_search({ rel_path = ".", query = "searchable", case_sensitive = true })
|
||||||
|
assert.is_nil(err2)
|
||||||
|
assert.truthy(result2:find("searchable.txt"))
|
||||||
|
assert.falsy(result2:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result3, err3 = LlmTools.grep_search({ rel_path = ".", query = "Searchable", case_sensitive = true })
|
||||||
|
assert.is_nil(err3)
|
||||||
|
assert.falsy(result3:find("searchable.txt"))
|
||||||
|
assert.falsy(result3:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result4, err4 = LlmTools.grep_search({ rel_path = ".", query = "searchable", case_sensitive = false })
|
||||||
|
assert.is_nil(err4)
|
||||||
|
assert.truthy(result4:find("searchable.txt"))
|
||||||
|
assert.falsy(result4:find("nothing.txt"))
|
||||||
|
|
||||||
|
local result5, err5 = LlmTools.grep_search({
|
||||||
|
rel_path = ".",
|
||||||
|
query = "searchable",
|
||||||
|
case_sensitive = false,
|
||||||
|
exclude_pattern = "search*",
|
||||||
|
})
|
||||||
|
assert.is_nil(err5)
|
||||||
|
assert.falsy(result5:find("searchable.txt"))
|
||||||
|
assert.falsy(result5:find("nothing.txt"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("should return error when no search tool is available", function()
|
it("should return error when no search tool is available", function()
|
||||||
-- Mock exepath to return nothing
|
-- Mock exepath to return nothing
|
||||||
vim.fn.exepath = function() return "" end
|
vim.fn.exepath = function() return "" end
|
||||||
|
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = ".", keyword = "test" })
|
local result, err = LlmTools.grep_search({ rel_path = ".", query = "test" })
|
||||||
assert.equals("", result)
|
assert.equals("", result)
|
||||||
assert.equals("No search command found", err)
|
assert.equals("No search command found", err)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("should respect path permissions", function()
|
it("should respect path permissions", function()
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = "../outside_project", keyword = "test" })
|
local result, err = LlmTools.grep_search({ rel_path = "../outside_project", query = "test" })
|
||||||
assert.truthy(err:find("No permission to access path"))
|
assert.truthy(err:find("No permission to access path"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("should handle non-existent paths", function()
|
it("should handle non-existent paths", function()
|
||||||
local result, err = LlmTools.search_keyword({ rel_path = "non_existent_dir", keyword = "test" })
|
local result, err = LlmTools.grep_search({ rel_path = "non_existent_dir", query = "test" })
|
||||||
assert.equals("", result)
|
assert.equals("", result)
|
||||||
assert.truthy(err)
|
assert.truthy(err)
|
||||||
assert.truthy(err:find("No such file or directory"))
|
assert.truthy(err:find("No such file or directory"))
|
||||||
|
|||||||
Reference in New Issue
Block a user