applyMultiEdit function

Future<EditResult> applyMultiEdit(
  1. String filePath,
  2. List<FileEdit> edits, {
  3. bool createBackup = true,
  4. bool dryRun = false,
})

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,
  );
}