mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-24 14:25:00 +00:00

# Context: USER: move get_input into utils. pass in history_file and fnames as params rather than referencing them with self. ASSISTANT: To move the `get_input` function into `utils.py`, we will remove it from the `Coder` class in `coder.py` and add it to `utils.py`. We will also update the function to accept `history_file` and `fnames` as parameters. ```python coder.py <<<<<<< ORIGINAL def get_input(self): inp = "" multiline_input = False style = Style.from_dict({'': 'green'}) while True: completer_instance = FileContentCompleter(self.fnames) if multiline_input: show = ". " else: show = "> " try: line = prompt( show, completer=completer_instance, history=FileHistory(self.history_file), style=style, ) except EOFError: return if line.strip() == "{" and not multiline_input: multiline_input = True continue elif line.strip() == "}" and multiline_input: break elif multiline_input: inp += line + "\n" else: inp = line break print() return inp ======= >>>>>>> UPDATED ``` ```python utils.py <<<<<<< ORIGINAL ======= def get_input(history_file, fnames): inp = "" multiline_input = False style = Style.from_dict({'': 'green'}) while True: completer_instance = FileContentCompleter(fnames) if multiline_input: show = ". " else: show = "> " try: line = prompt( show, completer=completer_instance, history=FileHistory(history_file), style=style, ) except EOFError: return if line.strip() == "{" and not multiline_input: multiline_input = True continue elif line.strip() == "}" and multiline_input: break elif multiline_input: inp += line + "\n" else: inp = line break print() return inp >>>>>>> UPDATED ``` Now, update the call to `get_input` in `coder.py` to use the new `utils.get_input` function: ```python coder.py <<<<<<< ORIGINAL inp = self.get_input() ======= inp = utils.get_input(self.history_file, self.fnames) >>>>>>> UPDATED ```
144 lines
3.5 KiB
Python
144 lines
3.5 KiB
Python
import math
|
|
|
|
from difflib import SequenceMatcher
|
|
from pathlib import Path
|
|
|
|
# from dump import dump
|
|
|
|
|
|
def replace_most_similar_chunk(whole, part, replace):
|
|
similarity_thresh = 0.8
|
|
|
|
max_similarity = 0
|
|
most_similar_chunk_start = -1
|
|
most_similar_chunk_end = -1
|
|
|
|
whole_lines = whole.splitlines()
|
|
part_lines = part.splitlines()
|
|
|
|
scale = 0.1
|
|
min_len = math.floor(len(part_lines) * (1 - scale))
|
|
max_len = math.ceil(len(part_lines) * (1 + scale))
|
|
|
|
for length in range(min_len, max_len):
|
|
for i in range(len(whole_lines) - length + 1):
|
|
chunk = whole_lines[i : i + length + 1]
|
|
chunk = "\n".join(chunk)
|
|
|
|
similarity = SequenceMatcher(None, chunk, part).ratio()
|
|
|
|
if similarity > max_similarity and similarity:
|
|
max_similarity = similarity
|
|
most_similar_chunk_start = i
|
|
most_similar_chunk_end = i + length + 1
|
|
|
|
if max_similarity < similarity_thresh:
|
|
return
|
|
|
|
replace_lines = replace.splitlines()
|
|
modified_whole = (
|
|
whole_lines[:most_similar_chunk_start]
|
|
+ replace_lines
|
|
+ whole_lines[most_similar_chunk_end:]
|
|
)
|
|
modified_whole = "\n".join(modified_whole) + "\n"
|
|
return modified_whole
|
|
|
|
|
|
def quoted_file(fname):
|
|
prompt = "\n"
|
|
prompt += fname
|
|
prompt += "\n```\n"
|
|
prompt += Path(fname).read_text()
|
|
prompt += "\n```\n"
|
|
return prompt
|
|
|
|
|
|
def strip_quoted_wrapping(res, fname=None):
|
|
"""
|
|
Given an input string which may have extra "wrapping" around it, remove the wrapping.
|
|
For example:
|
|
|
|
filename.ext
|
|
```
|
|
We just want this content
|
|
Not the filename and triple quotes
|
|
```
|
|
"""
|
|
if not res:
|
|
return res
|
|
|
|
res = res.splitlines()
|
|
|
|
if fname and res[0].strip().endswith(Path(fname).name):
|
|
res = res[1:]
|
|
|
|
if res[0].startswith("```") and res[-1].startswith("```"):
|
|
res = res[1:-1]
|
|
|
|
res = "\n".join(res)
|
|
if res and res[-1] != "\n":
|
|
res += "\n"
|
|
|
|
return res
|
|
|
|
|
|
def do_replace(fname, before_text, after_text):
|
|
before_text = strip_quoted_wrapping(before_text, fname)
|
|
after_text = strip_quoted_wrapping(after_text, fname)
|
|
fname = Path(fname)
|
|
|
|
# does it want to make a new file?
|
|
if not fname.exists() and not before_text.strip():
|
|
fname.touch()
|
|
|
|
content = fname.read_text()
|
|
|
|
if not before_text.strip():
|
|
if content:
|
|
new_content = content + after_text
|
|
else:
|
|
# first populating an empty file
|
|
new_content = after_text
|
|
else:
|
|
new_content = replace_most_similar_chunk(content, before_text, after_text)
|
|
if not new_content:
|
|
return
|
|
|
|
fname.write_text(new_content)
|
|
return True
|
|
def get_input(history_file, fnames):
|
|
inp = ""
|
|
multiline_input = False
|
|
|
|
style = Style.from_dict({'': 'green'})
|
|
|
|
while True:
|
|
completer_instance = FileContentCompleter(fnames)
|
|
if multiline_input:
|
|
show = ". "
|
|
else:
|
|
show = "> "
|
|
|
|
try:
|
|
line = prompt(
|
|
show,
|
|
completer=completer_instance,
|
|
history=FileHistory(history_file),
|
|
style=style,
|
|
)
|
|
except EOFError:
|
|
return
|
|
if line.strip() == "{" and not multiline_input:
|
|
multiline_input = True
|
|
continue
|
|
elif line.strip() == "}" and multiline_input:
|
|
break
|
|
elif multiline_input:
|
|
inp += line + "\n"
|
|
else:
|
|
inp = line
|
|
break
|
|
|
|
print()
|
|
return inp
|