@@ -11,8 +11,14 @@ def __init__(self, message: str):
1111 message = f"""
1212{ message }
1313---
14- Edit failed, no changes are applied. You'll have to reapply all search/replace blocks again.
15- Retry immediately with same "percentage_to_change" using search replace blocks fixing above error.
14+ Last edit failed, no changes are applied. None of the search/replace blocks applied in the last tool call.
15+ Recommendations:
16+ - Retry immediately with same "percentage_to_change" using search replace blocks fixing above error.
17+ - If you are still unsure you may re-read the file and then proceed accordingly.
18+
19+ If your search failed due to updates in the file content, remember that these
20+ are the changes that the user made and you should preserve them
21+ by updating your replace blocks too.
1622"""
1723 super ().__init__ (message )
1824
@@ -88,7 +94,7 @@ def replace_or_throw(
8894 if score > 1000 :
8995 display = (list (warnings ) + list (info ))[:max_errors ]
9096 raise SearchReplaceMatchError (
91- "Too many warnings generated, not apply the edits\n "
97+ "Too many warnings generated, not applying the edits\n "
9298 + "\n " .join (display )
9399 )
94100
@@ -123,7 +129,44 @@ def line_process_max_space_tolerance(line: str) -> str:
123129 return re .sub (r"\s" , "" , line )
124130
125131
126- REMOVE_INDENTATION = "Warning: matching after removing all spaces in lines."
132+ REMOVE_INDENTATION = (
133+ "Warning: matching without considering indentation (leading spaces)."
134+ )
135+ REMOVE_LINE_NUMS = "Warning: you gave search/replace blocks with leading line numbers, do not give them from the next time."
136+
137+ COMMON_MISTAKE_TRANSLATION = str .maketrans (
138+ {
139+ "‘" : "'" ,
140+ "’" : "'" ,
141+ "‚" : "," ,
142+ "‛" : "'" ,
143+ "′" : "'" ,
144+ "“" : '"' ,
145+ "”" : '"' ,
146+ "‟" : '"' ,
147+ "″" : '"' ,
148+ "‹" : "<" ,
149+ "›" : ">" ,
150+ "‐" : "-" ,
151+ "‑" : "-" ,
152+ "‒" : "-" ,
153+ "–" : "-" ,
154+ "—" : "-" ,
155+ "―" : "-" ,
156+ "−" : "-" ,
157+ "…" : "..." ,
158+ }
159+ )
160+
161+
162+ def remove_leading_linenums (string : str ) -> str :
163+ return re .sub (r"^\d+ " , "" , string ).rstrip ()
164+
165+
166+ def normalize_common_mistakes (string : str ) -> str :
167+ """Normalize unicode chars which are commonly confused by their ascii variants"""
168+ return string .translate (COMMON_MISTAKE_TRANSLATION ).rstrip ()
169+
127170
128171DEFAULT_TOLERANCES = [
129172 Tolerance (
@@ -136,17 +179,35 @@ def line_process_max_space_tolerance(line: str) -> str:
136179 line_process = str .lstrip ,
137180 severity_cat = "WARNING" ,
138181 score_multiplier = 10 ,
139- error_name = "Warning: matching without considering indentation (leading spaces)." ,
182+ error_name = REMOVE_INDENTATION ,
183+ ),
184+ Tolerance (
185+ line_process = remove_leading_linenums ,
186+ severity_cat = "WARNING" ,
187+ score_multiplier = 5 ,
188+ error_name = REMOVE_LINE_NUMS ,
189+ ),
190+ Tolerance (
191+ line_process = normalize_common_mistakes ,
192+ severity_cat = "WARNING" ,
193+ score_multiplier = 5 ,
194+ error_name = "Warning: matching after normalizing commonly confused characters (quotes, dashes, ellipsis)." ,
140195 ),
141196 Tolerance (
142197 line_process = line_process_max_space_tolerance ,
143198 severity_cat = "WARNING" ,
144199 score_multiplier = 50 ,
145- error_name = REMOVE_INDENTATION ,
200+ error_name = "Warning: matching after removing all spaces in lines." ,
146201 ),
147202]
148203
149204
205+ def fix_line_nums (
206+ matched_lines : list [str ], searched_lines : list [str ], replaced_lines : list [str ]
207+ ) -> list [str ]:
208+ return [remove_leading_linenums (line ) for line in replaced_lines ]
209+
210+
150211def fix_indentation (
151212 matched_lines : list [str ], searched_lines : list [str ], replaced_lines : list [str ]
152213) -> list [str ]:
@@ -312,6 +373,14 @@ def edit_file(self) -> list[FileEditOutput]:
312373 matches_with_tolerances = [(match , []) for match in matches ]
313374
314375 for match , tolerances in matches_with_tolerances :
376+ if any (
377+ tolerance .error_name == REMOVE_LINE_NUMS for tolerance in tolerances
378+ ):
379+ replace_by = fix_line_nums (
380+ self .file_lines [match .start : match .stop ],
381+ first_block [0 ],
382+ replace_by ,
383+ )
315384 if any (
316385 tolerance .error_name == REMOVE_INDENTATION for tolerance in tolerances
317386 ):
@@ -454,6 +523,9 @@ def match_with_tolerance(
454523 tolerance_index_by_content_line [search_idx ][content_idx ]
455524 ].count += 1
456525
526+ # Remove 0 counts
527+ tolerances_counts = [[x for x in y if x .count > 0 ] for y in tolerances_counts ]
528+
457529 return list (zip (matched_slices , tolerances_counts ))
458530
459531
0 commit comments