aider/utils.py
Paul Gauthier 6419e6c390 Move get_input function into utils.py and update the call to get_input in coder.py to use the new utils.get_input function.
# 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
```
2023-05-09 10:09:42 -07:00

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