applyMultiEdit function
Apply multiple edits to a file atomically.
Implementation
Future<EditResult> applyMultiEdit(
String filePath,
List<FileEdit> edits, {
bool createBackup = true,
bool dryRun = false,
}) async {
final file = File(filePath);
if (!await file.exists()) {
return EditResult(
success: false,
newContent: '',
editsApplied: 0,
errors: ['File not found: $filePath'],
);
}
var content = await file.readAsString();
final errors = <String>[];
var applied = 0;
String? backupPath;
// Create backup before editing
if (createBackup && !dryRun) {
backupPath = '$filePath.bak.${DateTime.now().millisecondsSinceEpoch}';
await File(backupPath).writeAsString(content);
}
// Apply edits in order
for (var i = 0; i < edits.length; i++) {
final edit = edits[i];
if (edit.replaceAll) {
if (content.contains(edit.oldText)) {
content = content.replaceAll(edit.oldText, edit.newText);
applied++;
} else {
errors.add('Edit $i: old_text not found for replaceAll.');
}
} else {
final index = content.indexOf(edit.oldText);
if (index == -1) {
errors.add('Edit $i: old_text not found.');
} else {
// Check uniqueness
final secondIndex = content.indexOf(
edit.oldText,
index + edit.oldText.length,
);
if (secondIndex != -1) {
errors.add(
'Edit $i: old_text is ambiguous (found at offsets $index and $secondIndex).',
);
} else {
content =
content.substring(0, index) +
edit.newText +
content.substring(index + edit.oldText.length);
applied++;
}
}
}
}
if (!dryRun && applied > 0) {
await file.writeAsString(content);
}
return EditResult(
success: errors.isEmpty,
newContent: content,
editsApplied: applied,
errors: errors,
backupPath: backupPath,
);
}