From 53de30c1accf188fc936fcbf6d150b4f232e14a8 Mon Sep 17 00:00:00 2001 From: Joshua Vial Date: Thu, 20 Jul 2023 09:33:06 +1200 Subject: [PATCH 01/10] Add docs for commands and prompt-toolkit defaults --- README.md | 3 +++ docs/commands.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 docs/commands.md diff --git a/README.md b/README.md index 1ce123464..8fe46bc5e 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ Aider also has many additional command-line options, environment variables or configuration file to set many options. See `aider --help` for details. + ## In-chat commands Aider supports commands from within the chat, which all start with `/`. Here are some of the most useful in-chat commands: @@ -108,6 +109,8 @@ Aider supports commands from within the chat, which all start with `/`. Here are * `/run `: Run a shell command and optionally add the output to the chat. * `/help`: Show help about all commands. +See the [full command docs](https://aider.chat/docs/commands.html) for more information. + ## Tips diff --git a/docs/commands.md b/docs/commands.md new file mode 100644 index 000000000..4d4c4a8c2 --- /dev/null +++ b/docs/commands.md @@ -0,0 +1,37 @@ +# Commands + +- `/help `: Show help about all commands +- `/exit`: Exit the application + +## token/context management +- `/add `: Add matching files to the chat session using glob patterns +- `/drop `: Remove matching files from the chat session +- `/clear`: Clear the chat history +- `/ls`: List all known files and those included in the chat session +- `/tokens`: Report on the number of tokens used by the current chat context +- `/run `: Run a shell command and optionally add the output to the chat + +## git +- `/undo`: Undo the last git commit if it was done by aider +- `/diff`: Display the diff of the last aider commit +- `/commit `: Commit edits to the repo made outside the chat (commit message optional) +- `/git `: Run a git command + +# Prompt Toolkit defaults + +The interactive prompt is built with [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) which provides a lot of Emacs and Vi-style keyboard. Some emacs bindings you may find useful are + +- `Ctrl-A` : Move cursor to the start of the line. +- `Ctrl-B` : Move cursor back one character. +- `Ctrl-D` : Delete the character under the cursor. +- `Ctrl-E` : Move cursor to the end of the line. +- `Ctrl-F` : Move cursor forward one character. +- `Ctrl-K` : Delete from the cursor to the end of the line. +- `Ctrl-L` : Clear the screen. +- `Ctrl-N` : Move down to the next history entry. +- `Ctrl-P` : Move up to the previous history entry. +- `Ctrl-R` : Reverse search in command history. + +Note: aider currently exits vi normal mode after a single command, (maybe something to do with the esc keybinding?). Feel free to investigate and make a PR if you would like to see it fully supported. + +Prompt toolkit also does not provide clear documentation on the bindings they support - maybe you can take aider and help them out with that and we can then link to the authoritative docs. From 03442d3c84ab803ae98ca2a46b7c9bde42fcbe9e Mon Sep 17 00:00:00 2001 From: Joshua Vial Date: Thu, 20 Jul 2023 10:43:18 +1200 Subject: [PATCH 02/10] remove argument from /help in docs --- docs/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/commands.md b/docs/commands.md index 4d4c4a8c2..b6f676c9f 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,6 +1,6 @@ # Commands -- `/help `: Show help about all commands +- `/help`: Show help about all commands - `/exit`: Exit the application ## token/context management From d695fe103b2f0352c8b72a2b75587ec8c59bf0a9 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 08:18:34 -0300 Subject: [PATCH 03/10] aider: Switched all the os calls to use pathlib in `test_cmd_add_drop_directory`. # Aider chat conversation: USER: switch all the os calls to use pathlib in `test_cmd_add_drop_directory` ASSISTANT: To switch all the os calls to use pathlib in `test_cmd_add_drop_directory`, we need to modify the `tests/test_commands.py` file. Here are the changes: ```python tests/test_commands.py <<<<<<< ORIGINAL # Create a directory and add files to it os.mkdir("test_dir") os.mkdir("test_dir/another_dir") with open("test_dir/test_file1.txt", "w") as f: f.write("Test file 1") with open("test_dir/test_file2.txt", "w") as f: f.write("Test file 2") with open("test_dir/another_dir/test_file.txt", "w") as f: f.write("Test file 3") ======= # Create a directory and add files to it using pathlib Path("test_dir").mkdir() Path("test_dir/another_dir").mkdir() with open(Path("test_dir/test_file1.txt"), "w") as f: f.write("Test file 1") with open(Path("test_dir/test_file2.txt"), "w") as f: f.write("Test file 2") with open(Path("test_dir/another_dir/test_file.txt"), "w") as f: f.write("Test file 3") >>>>>>> UPDATED ``` This change replaces the `os.mkdir` calls with `Path().mkdir()` from the pathlib module. It also changes the file paths in the `open` calls to use `Path()`. --- tests/test_commands.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index 02f808fae..06bd10ce1 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -90,14 +90,14 @@ class TestCommands(TestCase): coder = Coder.create(models.GPT35, None, io) commands = Commands(io, coder) - # Create a directory and add files to it - os.mkdir("test_dir") - os.mkdir("test_dir/another_dir") - with open("test_dir/test_file1.txt", "w") as f: + # Create a directory and add files to it using pathlib + Path("test_dir").mkdir() + Path("test_dir/another_dir").mkdir() + with open(Path("test_dir/test_file1.txt"), "w") as f: f.write("Test file 1") - with open("test_dir/test_file2.txt", "w") as f: + with open(Path("test_dir/test_file2.txt"), "w") as f: f.write("Test file 2") - with open("test_dir/another_dir/test_file.txt", "w") as f: + with open(Path("test_dir/another_dir/test_file.txt"), "w") as f: f.write("Test file 3") # Call the cmd_add method with a directory From 47b550c62fc3b91448e5e2488635026c26b3a30f Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 08:19:17 -0300 Subject: [PATCH 04/10] aider: Switched open calls to use Path.write_text. # Aider chat conversation: USER: also swith the open calls to use Path.write_text ASSISTANT: To switch the `open` calls to use `Path.write_text` in `test_cmd_add_drop_directory`, we need to modify the `tests/test_commands.py` file. Here are the changes: ```python tests/test_commands.py <<<<<<< ORIGINAL with open(Path("test_dir/test_file1.txt"), "w") as f: f.write("Test file 1") with open(Path("test_dir/test_file2.txt"), "w") as f: f.write("Test file 2") with open(Path("test_dir/another_dir/test_file.txt"), "w") as f: f.write("Test file 3") ======= Path("test_dir/test_file1.txt").write_text("Test file 1") Path("test_dir/test_file2.txt").write_text("Test file 2") Path("test_dir/another_dir/test_file.txt").write_text("Test file 3") >>>>>>> UPDATED ``` This change replaces the `open` calls with `Path().write_text()` from the pathlib module. --- tests/test_commands.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index 06bd10ce1..26d2a14e5 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -93,12 +93,9 @@ class TestCommands(TestCase): # Create a directory and add files to it using pathlib Path("test_dir").mkdir() Path("test_dir/another_dir").mkdir() - with open(Path("test_dir/test_file1.txt"), "w") as f: - f.write("Test file 1") - with open(Path("test_dir/test_file2.txt"), "w") as f: - f.write("Test file 2") - with open(Path("test_dir/another_dir/test_file.txt"), "w") as f: - f.write("Test file 3") + Path("test_dir/test_file1.txt").write_text("Test file 1") + Path("test_dir/test_file2.txt").write_text("Test file 2") + Path("test_dir/another_dir/test_file.txt").write_text("Test file 3") # Call the cmd_add method with a directory commands.cmd_add("test_dir test_dir/test_file2.txt") From 9352bc67ca9903edbcea00bf3de6e36a5c512e12 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 08:30:11 -0300 Subject: [PATCH 05/10] Added test case for issue #139 --- tests/test_commands.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index 26d2a14e5..bca022a24 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -84,7 +84,7 @@ class TestCommands(TestCase): def test_cmd_add_drop_directory(self): # Initialize the Commands and InputOutput objects - io = InputOutput(pretty=False, yes=True) + io = InputOutput(pretty=False, yes=False) from aider.coders import Coder coder = Coder.create(models.GPT35, None, io) @@ -112,6 +112,21 @@ class TestCommands(TestCase): str(Path("test_dir/another_dir/test_file.txt").resolve()), coder.abs_fnames ) + # Issue #139 /add problems when cwd != git_root + + # remember the proper abs path to this file + abs_fname = str(Path("test_dir/another_dir/test_file.txt").resolve()) + + # chdir to someplace other than git_root + Path("side_dir").mkdir() + os.chdir("side_dir") + + # add it via it's git_root referenced name + commands.cmd_add("test_dir/another_dir/test_file.txt") + + # it should be there, but was not in v0.10.0 + self.assertIn(abs_fname, coder.abs_fnames) + def test_cmd_drop_with_glob_patterns(self): # Initialize the Commands and InputOutput objects io = InputOutput(pretty=False, yes=True) From d785d9a2e243ad6033d5e32a88a7bf02aa74642f Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 08:34:56 -0300 Subject: [PATCH 06/10] fix for #139 --- aider/commands.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/aider/commands.py b/aider/commands.py index 10e9cd740..125c91163 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -232,7 +232,9 @@ class Commands: matched_files = [] for fn in raw_matched_files: - matched_files += expand_subdir(fn.relative_to(self.coder.root)) + matched_files += expand_subdir(fn) + + matched_files = [str(Path(fn).relative_to(self.coder.root)) for fn in matched_files] # if repo, filter against it if self.coder.repo: @@ -426,6 +428,7 @@ def expand_subdir(file_path): yield file_path return - for file in file_path.rglob("*"): - if file.is_file(): - yield str(file) + if file_path.is_dir(): + for file in file_path.rglob("*"): + if file.is_file(): + yield str(file) From 450a5fff19435eb2b97ee08c3fa8f1d4860e8157 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 08:41:56 -0300 Subject: [PATCH 07/10] Added test case and fix for /drop too --- aider/commands.py | 2 +- tests/test_commands.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/aider/commands.py b/aider/commands.py index 125c91163..df58bf428 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -328,7 +328,7 @@ class Commands: self.io.tool_error(f"No files matched '{word}'") for matched_file in matched_files: - abs_fname = str(Path(matched_file).resolve()) + abs_fname = self.coder.abs_root_path(matched_file) if abs_fname in self.coder.abs_fnames: self.coder.abs_fnames.remove(abs_fname) self.io.tool_output(f"Removed {matched_file} from the chat") diff --git a/tests/test_commands.py b/tests/test_commands.py index bca022a24..a332665d0 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -127,6 +127,12 @@ class TestCommands(TestCase): # it should be there, but was not in v0.10.0 self.assertIn(abs_fname, coder.abs_fnames) + # drop it via it's git_root referenced name + commands.cmd_drop("test_dir/another_dir/test_file.txt") + + # it should be there, but was not in v0.10.0 + self.assertNotIn(abs_fname, coder.abs_fnames) + def test_cmd_drop_with_glob_patterns(self): # Initialize the Commands and InputOutput objects io = InputOutput(pretty=False, yes=True) From 0a5155e5bd5847e541f87384af20d9b508d8fc27 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 10:00:00 -0300 Subject: [PATCH 08/10] brought over test_cmd_add_from_subdir from pr #97 --- tests/test_commands.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_commands.py b/tests/test_commands.py index a332665d0..15a486a6d 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -220,3 +220,41 @@ class TestCommands(TestCase): self.assertIn("foo.txt", console_output) self.assertIn("bar.txt", console_output) + + def test_cmd_add_from_subdir(self): + repo = git.Repo.init() + repo.config_writer().set_value("user", "name", "Test User").release() + repo.config_writer().set_value("user", "email", "testuser@example.com").release() + + # Create three empty files and add them to the git repository + filenames = ["one.py", Path("subdir") / "two.py", Path("anotherdir") / "three.py"] + for filename in filenames: + file_path = Path(filename) + file_path.parent.mkdir(parents=True, exist_ok=True) + file_path.touch() + repo.git.add(str(file_path)) + repo.git.commit("-m", "added") + + filenames = [str(Path(fn).resolve()) for fn in filenames] + + ### + + os.chdir("subdir") + + io = InputOutput(pretty=False, yes=True) + coder = Coder.create(models.GPT35, None, io) + commands = Commands(io, coder) + + # this should get added + commands.cmd_add(str(Path("anotherdir") / "three.py")) + + # this should add one.py + commands.cmd_add("*.py") + + self.assertIn(filenames[0], coder.abs_fnames) + self.assertNotIn(filenames[1], coder.abs_fnames) + self.assertIn(filenames[2], coder.abs_fnames) + + del commands + del coder + del io From 699f1598fc002ed3b176c1e2c12f3eccd2fa66f7 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 10:04:18 -0300 Subject: [PATCH 09/10] Ignore errors (Windows) --- tests/test_commands.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index 15a486a6d..20787ccc9 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -25,7 +25,10 @@ class TestCommands(TestCase): def tearDown(self): os.chdir(self.original_cwd) - shutil.rmtree(self.tempdir) + try: + shutil.rmtree(self.tempdir) + except OSError: + pass # Ignore errors (Windows) def test_cmd_add(self): # Initialize the Commands and InputOutput objects @@ -254,7 +257,3 @@ class TestCommands(TestCase): self.assertIn(filenames[0], coder.abs_fnames) self.assertNotIn(filenames[1], coder.abs_fnames) self.assertIn(filenames[2], coder.abs_fnames) - - del commands - del coder - del io From 4238986991ac972520a2871fb5bc2ecad12e6db3 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sun, 23 Jul 2023 10:16:48 -0300 Subject: [PATCH 10/10] Updated HISTORY --- HISTORY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 07cd264ac..40758404a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Release history +### main branch on GitHub + +- /add and /drop always use paths relative to the git root + ### v0.10.0 - Added `/git` command to run git from inside aider chats.