Skip to content

Instantly share code, notes, and snippets.

@blixt
Created September 8, 2025 20:17
Show Gist options
  • Save blixt/52fa722f967247fa7fe5931ad0836b56 to your computer and use it in GitHub Desktop.
Save blixt/52fa722f967247fa7fe5931ad0836b56 to your computer and use it in GitHub Desktop.
If you're giving GPT-5 a findAndReplace tool, this helps work around its tendency to mix up spaces/tabs
/**
* Replaces old_string with new_string in the given code.
* Validates that old_string appears exactly once to avoid ambiguous replacements.
*/
export function findAndReplace(
code: string,
old_string: string,
new_string: string,
): { success: true; result: string } | { success: false; error: string } {
let pattern = old_string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
let occurrences = code.match(new RegExp(pattern, "g"))?.length ?? 0;
let searchValue: string | RegExp = old_string;
if (occurrences === 0) {
// Try one more time but with flexible indentation. If our more general search pattern matches exactly one place
// in the code, we will use it to replace the matching code.
//
// Note: We replace with [\t ] instead of \s here because otherwise it would also match the preceding newline.
pattern = pattern.replace(/^\s+/gm, "([\\t ]+)");
searchValue = new RegExp(pattern, "g");
occurrences = code.match(searchValue)?.length ?? 0;
if (occurrences === 0) {
return {
success: false,
error: `The string "${old_string}" was not found in the code.`,
};
}
if (occurrences > 1) {
return {
success: false,
error: `The string "${old_string}" does not appear in the code. However, a similar string with different indentation exists. Please add more context and use exact indentation to avoid ambiguous replacements.`,
};
}
}
if (occurrences > 1) {
return {
success: false,
error: `The string "${old_string}" appears ${occurrences} times in the code. Please be more specific to avoid ambiguous replacements.`,
};
}
return {
success: true,
// Note: Using a function here also avoids the default behavior of replace changing "$$" to "$".
result: code.replace(searchValue, (_, indent) => `${typeof indent === "string" ? indent : ""}${new_string}`),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment