-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_replace_content.lua
More file actions
101 lines (86 loc) · 3.14 KB
/
Copy pathfile_replace_content.lua
File metadata and controls
101 lines (86 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
-- MCP Tool: file_replace_content
-- Replace a unique occurrence of text in a file
-- The search text must appear exactly once for safety
-- Entry kind: function.lua
local json = require("json")
local projects = require("projects")
local function call(arguments)
local vol, err = projects.resolve(arguments.project)
if err then
return "Error: " .. err
end
local path = arguments.path
if not path or path == "" then
return "Error: path is required"
end
local search = arguments.search
if not search or search == "" then
return "Error: search is required — cannot replace empty content"
end
local replace = arguments.replace
if replace == nil then
return "Error: replace is required"
end
-- Read current content
local content, read_err = vol:readfile(path)
if read_err then
return "Error reading file: " .. tostring(read_err)
end
-- Find first occurrence (plain text, no patterns)
local pos = string.find(content, search, 1, true)
if not pos then
return "Error: search text not found in " .. path
.. ". Verify exact match including whitespace, tabs, and line endings."
.. " Use file_read tool to see actual file content."
end
-- Check uniqueness — must appear exactly once
local second = string.find(content, search, pos + 1, true)
if second then
local count = 2
local p = second
while true do
p = string.find(content, search, p + 1, true)
if not p then break end
count = count + 1
end
return string.format(
"Error: search text found %d times in %s."
.. " Pattern must be unique. Add more surrounding context to make it unique.",
count, path
)
end
-- Calculate line numbers for reporting
local before = string.sub(content, 1, pos - 1)
local _, newlines_before = string.gsub(before, "\n", "\n")
local line_start = newlines_before + 1
local _, search_newlines = string.gsub(search, "\n", "\n")
local _, replace_newlines = string.gsub(replace, "\n", "\n")
local line_end = line_start + search_newlines
local new_line_end = line_start + replace_newlines
-- Perform replacement
local new_content = string.sub(content, 1, pos - 1)
.. replace
.. string.sub(content, pos + #search)
local _, write_err = vol:writefile(path, new_content)
if write_err then
return "Error writing file: " .. tostring(write_err)
end
-- Build success message
local line_info = line_start == line_end
and ("line " .. line_start)
or ("lines " .. line_start .. "-" .. line_end)
local new_info = line_start == new_line_end
and ("line " .. line_start)
or ("lines " .. line_start .. "-" .. new_line_end)
return string.format(
"Successfully replaced in '%s'.\n"
.. "Original: %s (%d characters)\n"
.. "Modified: %s (%d characters)\n"
.. "Change: %+d characters",
path,
line_info, #search,
new_info, #replace,
#replace - #search
)
end
return { call = call }