mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-01 18:25:00 +00:00
Merge pull request #59 from paul-gauthier/glob-add
Updated the /add and /drop commands to glob files
This commit is contained in:
commit
6e8695999d
3 changed files with 106 additions and 28 deletions
|
@ -954,6 +954,8 @@ class Coder:
|
|||
return full_path
|
||||
|
||||
def get_tracked_files(self):
|
||||
if not self.repo:
|
||||
return []
|
||||
# convert to appropriate os.sep, since git always normalizes to /
|
||||
files = set(self.repo.git.ls_files().splitlines())
|
||||
res = set(str(Path(PurePosixPath(path))) for path in files)
|
||||
|
|
|
@ -11,6 +11,8 @@ from prompt_toolkit.completion import Completion
|
|||
|
||||
from aider import prompts
|
||||
|
||||
from .dump import dump # noqa: F401
|
||||
|
||||
|
||||
class Commands:
|
||||
def __init__(self, io, coder):
|
||||
|
@ -219,39 +221,40 @@ class Commands:
|
|||
if partial.lower() in fname.lower():
|
||||
yield Completion(fname, start_position=-len(partial))
|
||||
|
||||
def glob_filtered_to_repo(self, pattern):
|
||||
matched_files = Path(self.coder.root).glob(pattern)
|
||||
|
||||
# if repo, filter against it
|
||||
if self.coder.repo:
|
||||
git_files = self.coder.get_tracked_files()
|
||||
matched_files = [fn for fn in matched_files if str(fn) in git_files]
|
||||
|
||||
return list(map(str, matched_files))
|
||||
|
||||
def cmd_add(self, args):
|
||||
"Add matching files to the chat session"
|
||||
"Add matching files to the chat session using glob patterns"
|
||||
|
||||
added_fnames = []
|
||||
files = self.coder.get_all_relative_files()
|
||||
git_added = []
|
||||
git_files = self.coder.get_tracked_files()
|
||||
|
||||
for word in args.split():
|
||||
matched_files = [file for file in files if word in file]
|
||||
matched_files = self.glob_filtered_to_repo(word)
|
||||
|
||||
if not matched_files:
|
||||
if self.coder.repo is not None:
|
||||
create_file = self.io.confirm_ask(
|
||||
(
|
||||
f"No files matched '{word}'. Do you want to create the file and add it"
|
||||
" to git?"
|
||||
),
|
||||
)
|
||||
else:
|
||||
create_file = self.io.confirm_ask(
|
||||
f"No files matched '{word}'. Do you want to create the file?"
|
||||
)
|
||||
|
||||
if create_file:
|
||||
if any(char in word for char in "*?[]"):
|
||||
self.io.tool_error(f"No files matched pattern: {word}")
|
||||
elif self.io.confirm_ask(
|
||||
f"No files matched '{word}'. Do you want to create the file?"
|
||||
):
|
||||
(Path(self.coder.root) / word).touch()
|
||||
|
||||
matched_files = [word]
|
||||
if self.coder.repo is not None:
|
||||
self.coder.repo.git.add(os.path.join(self.coder.root, word))
|
||||
commit_message = f"aider: Created and added {word} to git."
|
||||
self.coder.repo.git.commit("-m", commit_message, "--no-verify")
|
||||
else:
|
||||
self.io.tool_error(f"No files matched '{word}'")
|
||||
|
||||
for matched_file in matched_files:
|
||||
if self.coder.repo and matched_file not in git_files:
|
||||
self.coder.repo.git.add(os.path.join(self.coder.root, matched_file))
|
||||
git_added.append(matched_file)
|
||||
|
||||
abs_file_path = os.path.abspath(os.path.join(self.coder.root, matched_file))
|
||||
if abs_file_path not in self.coder.abs_fnames:
|
||||
content = self.io.read_text(abs_file_path)
|
||||
|
@ -262,6 +265,13 @@ class Commands:
|
|||
else:
|
||||
self.io.tool_error(f"{matched_file} is already in the chat")
|
||||
|
||||
if self.coder.repo and git_added:
|
||||
git_added = " ".join(git_added)
|
||||
commit_message = f"aider: Created {git_added}"
|
||||
self.coder.repo.git.commit("-m", commit_message, "--no-verify")
|
||||
commit_hash = self.coder.repo.head.commit.hexsha[:7]
|
||||
self.io.tool_output(f"Commit {commit_hash} {commit_message}")
|
||||
|
||||
if not added_fnames:
|
||||
return
|
||||
|
||||
|
@ -287,11 +297,8 @@ class Commands:
|
|||
self.coder.abs_fnames = set()
|
||||
|
||||
for word in args.split():
|
||||
matched_files = [
|
||||
file
|
||||
for file in self.coder.abs_fnames
|
||||
if word.lower() in os.path.relpath(file, self.coder.root).lower()
|
||||
]
|
||||
matched_files = self.glob_filtered_to_repo(word)
|
||||
|
||||
if not matched_files:
|
||||
self.io.tool_error(f"No files matched '{word}'")
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import shutil
|
|||
import sys
|
||||
import tempfile
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
from aider import models
|
||||
|
@ -38,6 +39,74 @@ class TestCommands(TestCase):
|
|||
self.assertTrue(os.path.exists("foo.txt"))
|
||||
self.assertTrue(os.path.exists("bar.txt"))
|
||||
|
||||
def test_cmd_add_with_glob_patterns(self):
|
||||
# Initialize the Commands and InputOutput objects
|
||||
io = InputOutput(pretty=False, yes=True)
|
||||
from aider.coders import Coder
|
||||
|
||||
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
|
||||
commands = Commands(io, coder)
|
||||
|
||||
# Create some test files
|
||||
with open("test1.py", "w") as f:
|
||||
f.write("print('test1')")
|
||||
with open("test2.py", "w") as f:
|
||||
f.write("print('test2')")
|
||||
with open("test.txt", "w") as f:
|
||||
f.write("test")
|
||||
|
||||
# Call the cmd_add method with a glob pattern
|
||||
commands.cmd_add("*.py")
|
||||
|
||||
# Check if the Python files have been added to the chat session
|
||||
self.assertIn(os.path.abspath("test1.py"), coder.abs_fnames)
|
||||
self.assertIn(os.path.abspath("test2.py"), coder.abs_fnames)
|
||||
|
||||
# Check if the text file has not been added to the chat session
|
||||
self.assertNotIn(os.path.abspath("test.txt"), coder.abs_fnames)
|
||||
|
||||
def test_cmd_add_no_match(self):
|
||||
# Initialize the Commands and InputOutput objects
|
||||
io = InputOutput(pretty=False, yes=True)
|
||||
from aider.coders import Coder
|
||||
|
||||
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
|
||||
commands = Commands(io, coder)
|
||||
|
||||
# Call the cmd_add method with a non-existent file pattern
|
||||
commands.cmd_add("*.nonexistent")
|
||||
|
||||
# Check if no files have been added to the chat session
|
||||
self.assertEqual(len(coder.abs_fnames), 0)
|
||||
|
||||
def test_cmd_drop_with_glob_patterns(self):
|
||||
# Initialize the Commands and InputOutput objects
|
||||
io = InputOutput(pretty=False, yes=True)
|
||||
from aider.coders import Coder
|
||||
|
||||
coder = Coder.create(models.GPT35, None, io, openai_api_key="deadbeef")
|
||||
commands = Commands(io, coder)
|
||||
|
||||
subdir = Path("subdir")
|
||||
subdir.mkdir()
|
||||
(subdir / "subtest1.py").touch()
|
||||
(subdir / "subtest2.py").touch()
|
||||
|
||||
Path("test1.py").touch()
|
||||
Path("test2.py").touch()
|
||||
|
||||
# Add some files to the chat session
|
||||
commands.cmd_add("*.py")
|
||||
|
||||
self.assertEqual(len(coder.abs_fnames), 2)
|
||||
|
||||
# Call the cmd_drop method with a glob pattern
|
||||
commands.cmd_drop("*2.py")
|
||||
|
||||
# Check if the Python files have been removed from the chat session
|
||||
self.assertIn(os.path.abspath("test1.py"), coder.abs_fnames)
|
||||
self.assertNotIn(os.path.abspath("test2.py"), coder.abs_fnames)
|
||||
|
||||
def test_cmd_add_bad_encoding(self):
|
||||
# Initialize the Commands and InputOutput objects
|
||||
io = InputOutput(pretty=False, yes=True)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue