Commit graph

220 commits

Author SHA1 Message Date
Paul Gauthier
143ded6722 Adopt abs_root_path 2023-07-07 17:21:31 -07:00
Paul Gauthier
1c1411b506 Adopt safe_abs_path 2023-07-07 17:19:32 -07:00
Paul Gauthier
4b3fdc0f88 switch all to resolve 2023-07-07 16:59:35 -07:00
Paul Gauthier
f266c87e59 normalize /add paths 2023-07-07 16:41:29 -07:00
Paul Gauthier
a764efa82b fix test 2023-07-07 11:25:41 -07:00
Paul Gauthier
b5c497b6a6 Allow adding of existing non-git files 2023-07-07 11:21:55 -07:00
Paul Gauthier
75b533b4c3 commit new files to git 2023-07-07 08:24:44 -07:00
Paul Gauthier
6a0cff50f8 filter against git 2023-07-06 18:09:26 -07:00
Paul Gauthier
cb2b2c5ce3 Merge branch 'main' into glob-add 2023-07-06 17:53:46 -07:00
Paul Gauthier
95a777a48c More accurate /tokens 2023-07-06 13:35:17 -07:00
Paul Gauthier
6cb4428cb7 Merge branch 'main' into encodings 2023-07-06 13:33:53 -07:00
Paul Gauthier
1291c2424a better message for no /ls output 2023-07-06 12:52:33 -07:00
Paul Gauthier
d2c13b2976 aider: Refactored cmd_drop method to match glob pattern against the filename only, not the full file path.
# Context:
USER: I ran this command:

 pytest tests/test_commands.py

And got this output:

============================= test session starts ==============================
platform darwin -- Python 3.11.3, pytest-7.3.1, pluggy-1.2.0
rootdir: /Users/gauthier/Projects/aider
configfile: pytest.ini
collected 3 items

tests/test_commands.py ..F                                               [100%]

=================================== FAILURES ===================================
________________ TestCommands.test_cmd_drop_with_glob_patterns _________________

self = <tests.test_commands.TestCommands testMethod=test_cmd_drop_with_glob_patterns>

    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)

        with open("test1.py", "w") as f:
            f.write("print('test1')")
        with open("test2.py", "w") as f:
            f.write("print('test2')")

        # Add some files to the chat session
        commands.cmd_add("*.py")

        # 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)
E       AssertionError: '/private/var/folders/49/kxrdwwbx0h9bchx99397477c0000gn/T/tmpijmz7big/test1.py' not found in set()

tests/test_commands.py:81: AssertionError
----------------------------- Captured stdout call -----------------------------
Model: gpt-3.5-turbo
Git repo: none
Repo-map: disabled
Added test1.py to the chat
Added test2.py to the chat
Removed test2.py from the chat
Removed test1.py from the chat
=========================== short test summary info ============================
FAILED tests/test_commands.py::TestCommands::test_cmd_drop_with_glob_patterns
========================= 1 failed, 2 passed in 0.98s ==========================

ASSISTANT: It seems like the test `test_cmd_drop_with_glob_patterns` is failing because the `cmd_drop` method is removing all files that match the glob pattern "*2.py", which includes "test1.py" and "test2.py". This is because the glob pattern is being matched against the full file path, not just the filename.

To fix this, we need to modify the `cmd_drop` method in the `Commands` class in the `aider/commands.py` file. Specifically, we need to change the way we match the glob pattern against the file paths.

Here are the changes:

```python
aider/commands.py
<<<<<<< ORIGINAL
    def cmd_drop(self, args):
        "Remove matching files from the chat session"

        if not args.strip():
            self.io.tool_output("Dropping all files from the chat session.")
            self.coder.abs_fnames = set()

        for word in args.split():
            matched_files = [
                file
                for file in self.coder.abs_fnames
                if any(glob.fnmatch.fnmatch(os.path.relpath(file, self.coder.root), word) for file in self.coder.abs_fnames)
            ]
            if not matched_files:
                self.io.tool_error(f"No files matched '{word}'")

            for matched_file in matched_files:
                relative_fname = os.path.relpath(matched_file, self.coder.root)
                self.coder.abs_fnames.remove(matched_file)
                self.io.tool_output(f"Removed {relative_fname} from the chat")
=======
    def cmd_drop(self, args):
        "Remove matching files from the chat session"

        if not args.strip():
            self.io.tool_output("Dropping all files from the chat session.")
            self.coder.abs_fnames = set()

        for word in args.split():
            matched_files = [
                file
                for file in self.coder.abs_fnames
                if glob.fnmatch.fnmatch(os.path.basename(file), word)
            ]
            if not matched_files:
                self.io.tool_error(f"No files matched '{word}'")

            for matched_file in matched_files:
                relative_fname = os.path.relpath(matched_file, self.coder.root)
                self.coder.abs_fnames.remove(matched_file)
                self.io.tool_output(f"Removed {relative_fname} from the chat")
>>>>>>> UPDATED
```

This change will ensure that the glob pattern is matched against the filename only, not the full file path. This should fix the failing test.
2023-07-05 21:42:36 -07:00
Paul Gauthier
ad5cdc463a aider: Refactored cmd_drop to use glob for matching files against the given word.
# Context:
USER: have `cmd_drop` also glob against the `files`
ASSISTANT: To implement this change, we need to modify the `aider/commands.py` file.

Here's the step-by-step process:

1. In the `cmd_drop` method, use the `glob.glob` function to match the word against the `files`.
2. If no files match, print an error message.
3. If files match, remove them from the chat session.

Here's the code change:

```python
aider/commands.py
<<<<<<< ORIGINAL
    def cmd_drop(self, args):
        "Remove matching files from the chat session"

        if not args.strip():
            self.io.tool_output("Dropping all files from the chat session.")
            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()
            ]
            if not matched_files:
                self.io.tool_error(f"No files matched '{word}'")

            for matched_file in matched_files:
                relative_fname = os.path.relpath(matched_file, self.coder.root)
                self.coder.abs_fnames.remove(matched_file)
                self.io.tool_output(f"Removed {relative_fname} from the chat")
=======
    def cmd_drop(self, args):
        "Remove matching files from the chat session"

        if not args.strip():
            self.io.tool_output("Dropping all files from the chat session.")
            self.coder.abs_fnames = set()

        for word in args.split():
            matched_files = [
                file
                for file in self.coder.abs_fnames
                if any(glob.fnmatch.fnmatch(os.path.relpath(file, self.coder.root), word) for file in self.coder.abs_fnames)
            ]
            if not matched_files:
                self.io.tool_error(f"No files matched '{word}'")

            for matched_file in matched_files:
                relative_fname = os.path.relpath(matched_file, self.coder.root)
                self.coder.abs_fnames.remove(matched_file)
                self.io.tool_output(f"Removed {relative_fname} from the chat")
>>>>>>> UPDATED
```
Please let me know if you need any further changes.
2023-07-05 21:38:44 -07:00
Paul Gauthier
5cd7d9d743 aider: aider: Modified cmd_add to skip file creation if word contains glob characters.
# Context:
USER: if word doesn't match anything, don't ask to add it if it contains glob characters
ASSISTANT: To implement this change, we need to modify the `aider/commands.py` file.

Here's the step-by-step process:

1. In the `cmd_add` method, before asking to create a file, check if the word contains any glob characters (`*`, `?`, `[`, `]`).
2. If it does, skip the creation process and print an error message.

Here's the code change:

```python
aider/commands.py
<<<<<<< ORIGINAL
            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:
                    with open(os.path.join(self.coder.root, word), "w"):
                        pass
                    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}'")
=======
            if not matched_files:
                if any(char in word for char in "*?[]"):
                    self.io.tool_error(f"No files matched '{word}' and it contains glob characters")
                else:
                    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:
                        with open(os.path.join(self.coder.root, word), "w"):
                            pass
                        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}'")
>>>>>>> UPDATED
```
Please let me know if you need any further changes.
2023-07-05 21:37:22 -07:00
Paul Gauthier
09605788d5 cleanup 2023-07-05 21:33:59 -07:00
Paul Gauthier
d97bf17e19 aider: Moved the import statement for the glob module to the top of the aider/commands.py file.
# Context:
USER: I ran this command:

 pytest tests/test_commands.py

And got this output:

============================= test session starts ==============================
platform darwin -- Python 3.11.3, pytest-7.3.1, pluggy-1.2.0
rootdir: /Users/gauthier/Projects/aider
configfile: pytest.ini
collected 1 item

tests/test_commands.py F                                                 [100%]

=================================== FAILURES ===================================
_________________ TestCommands.test_cmd_add_with_glob_patterns _________________

self = <tests.test_commands.TestCommands testMethod=test_cmd_add_with_glob_patterns>

    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")

tests/test_commands.py:38:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <aider.commands.Commands object at 0x1113b2250>, args = '*.py'

    def cmd_add(self, args):
        "Add matching files to the chat session using glob patterns"

        added_fnames = []
        for pattern in args.split():
>           matched_files = glob.glob(pattern, recursive=True)
E           NameError: name 'glob' is not defined

aider/commands.py:226: NameError
----------------------------- Captured stdout call -----------------------------
Model: gpt-3.5-turbo
Git repo: none
Repo-map: disabled
=========================== short test summary info ============================
FAILED tests/test_commands.py::TestCommands::test_cmd_add_with_glob_patterns
============================== 1 failed in 0.92s ===============================

ASSISTANT: The error message indicates that the `glob` module is not defined in the `cmd_add` method of the `Commands` class in the `aider/commands.py` file. This is because the `glob` module is imported inside the `Commands` class, but it should be imported at the top of the file.

Here are the changes you need to make:

```python
aider/commands.py
<<<<<<< ORIGINAL
import json
import os
import shlex
import subprocess
import sys

import git
import tiktoken
from prompt_toolkit.completion import Completion

from aider import prompts, utils

class Commands:
    import glob
=======
import json
import os
import shlex
import subprocess
import sys
import glob

import git
import tiktoken
from prompt_toolkit.completion import Completion

from aider import prompts, utils

class Commands:
>>>>>>> UPDATED
```

This change moves the `import glob` statement from inside the `Commands` class to the top of the file, which is the standard place for import statements in Python. This will make the `glob` module available to all methods in the `Commands` class.
2023-07-05 21:30:57 -07:00
Paul Gauthier
874b5f8c7a aider: The cmd_add method in the Commands class has been modified to allow the /add command to accept glob patterns.
# Context:
USER: Feature Description
Currently, the /add function accepts directory paths to add the entire directory or spefic file paths to the program's context. A useful enhancement would be to support the use of regex or glob expressions with the /add function. This would give users more flexibility and control to specify exactly which files to include.

Proposed Solution
Allow the /add function to interpret glob or regex patterns. For example, a user could use /add src/*.py to include only Python files from the src directory or /add src/[A-C]* to add only files that start with A, B, or C.

Expected Behavior
When a user runs /add with a regex or glob pattern, the program should add to the context only the files that match the pattern. The program should handle non-matching files or non-existent paths gracefully, preferably by ignoring them and printing a warning message.

Alternatives Considered
An alternative could be providing an additional function, say /addPattern, that accepts regex/glob patterns. This approach would leave the existing /add functionality unchanged for users who don't need the enhanced functionality.

Additional Context
Adding this feature would boost the flexibility of the /add function, making the program more convenient to use for a variety of tasks. Users could, for instance, exclude certain types of files or select a subset of files based on their naming conventions.
ASSISTANT: To implement this feature, we need to modify the `cmd_add` method in the `Commands` class in the `aider/commands.py` file.

The changes will involve:
1. Interpreting the input argument as a glob pattern.
2. Using the `glob` module to find all files that match the pattern.
3. Adding the matched files to the chat session.

Here is the proposed change:

```python
aider/commands.py
<<<<<<< ORIGINAL
    def cmd_add(self, args):
        "Add matching files to the chat session"

        added_fnames = []
        files = self.coder.get_all_relative_files()
        for word in args.split():
            matched_files = [file for file in files if word in file]
=======
    import glob

    def cmd_add(self, args):
        "Add matching files to the chat session using glob patterns"

        added_fnames = []
        for pattern in args.split():
            matched_files = glob.glob(pattern, recursive=True)
>>>>>>> UPDATED
```

This change will allow the `/add` command to accept glob patterns. For example, `/add src/*.py` will add all Python files in the `src` directory to the chat session.
2023-07-05 21:28:53 -07:00
Paul Gauthier
de02038a7e remove ref to quoted_file 2023-07-05 21:08:49 -07:00
Paul Gauthier
c2c80bbd3c do not /add files that fail to decode 2023-07-05 21:00:10 -07:00
Paul Gauthier
bc60e7fd1c use Path.touch() to create new files 2023-07-05 15:44:12 -07:00
Paul Gauthier
4ec3203b91 fix for issue #33 2023-07-02 17:53:40 -07:00
Paul Gauthier
dfdc6a382a /drop with no args drops all files 2023-06-23 10:14:51 -07:00
Paul Gauthier
f32580caf2 red if exhausted 2023-06-23 10:13:13 -07:00
Paul Gauthier
f9599f87a2 print -> tool_output 2023-06-23 10:12:19 -07:00
Paul Gauthier
803423cc6a prettier /tokens output 2023-06-23 10:10:45 -07:00
Paul Gauthier
151b7b2811 Merge branch 'main' into edit-formats 2023-06-21 14:55:18 -07:00
Paul Gauthier
87be865a71 Improved /tokens output 2023-06-21 14:55:13 -07:00
Paul Gauthier
2fa6c31262 Merge branch 'main' into edit-formats 2023-06-21 14:36:38 -07:00
Paul Gauthier
3974629d50 /clear should only clear history, not drop files 2023-06-21 14:36:31 -07:00
Paul Gauthier
122c1c4f6c Model.use_repo_map, Model.send_undo_reply 2023-06-20 16:13:50 -07:00
Paul Gauthier
8660d35601 More flexible models 2023-06-14 17:51:17 -07:00
Paul Gauthier
25a28e6f9c Improved support for gpt-3.5-turbo-16k 2023-06-13 12:19:56 -07:00
Paul Gauthier
b70f8ea7bc Use models...max_context_tokens 2023-06-07 12:37:10 -07:00
Paul Gauthier
a874d617d3 rename 2023-06-07 12:29:51 -07:00
Paul Gauthier
9cef379abd refac 2023-06-07 12:28:45 -07:00
Paul Gauthier
cf3bf998dd fixed commands to deal with optional repo map 2023-06-05 22:07:19 -07:00
Paul Gauthier
fcd8a6df73 Use the Models enum instead of .value 2023-06-05 17:06:34 -07:00
Paul Gauthier
130f73c864 Added /tokens cmd 2023-06-05 12:30:20 -07:00
Paul Gauthier
c17e454608 Added /clear cmd 2023-06-05 11:31:47 -07:00
Paul Gauthier
95b32a74a9 Moved all model names into an enum 2023-06-05 09:19:29 -07:00
Paul Gauthier
56d2aa59ee 3.5 prompts 2023-06-04 13:59:43 -07:00
Paul Gauthier
92cd2f3ce6 isort 2023-05-28 22:47:38 -07:00
Paul Gauthier
37e3e561f0 Fixed /run output to log 2023-05-28 11:20:08 -07:00
Paul Gauthier
67a1d7231c aider: Updated cmd_run method to ask for user approval before adding the output to the chat.
# Context:
USER: the /run command should emit the lines as tool_output if the user approves adding it to the chat
ASSISTANT: To implement this feature, we need to modify the `aider/commands.py` file. Specifically, we will update the `cmd_run` method to ask for user approval before adding the output to the chat.

Please make the `aider/commands.py` file *read-write* so I can provide the necessary changes.
USER: I added these *read-write* files: aider/commands.py
ASSISTANT: Great! Now, I will provide the necessary changes to the `aider/commands.py` file to implement the requested feature.

```python
aider/commands.py
<<<<<<< ORIGINAL
        print(combined_output)

        ok = self.io.confirm_ask("Add the output to the chat?", default="y")
        if not ok:
            return

        msg = prompts.run_output.format(
            command=args,
            output=combined_output,
        )
        return msg
=======
        if self.io.confirm_ask("Add the output to the chat?", default="y"):
            msg = prompts.run_output.format(
                command=args,
                output=combined_output,
            )
            self.io.tool_output(msg, log_only=False)
        else:
            print(combined_output)
>>>>>>> UPDATED
```

This change will ask the user for approval before adding the output to the chat. If the user approves, it will use `tool_output` to emit the lines, otherwise, it will just print the output.
2023-05-28 11:16:08 -07:00
Paul Gauthier
cc9b21df06 renamed io.tool() -> io.tool_output() 2023-05-27 15:17:33 -07:00
Paul Gauthier
4e557baad4 cleaned up /exit, normalized /help 2023-05-26 12:21:43 -07:00
Paul Gauthier
c40d763bce aider: Added /exit command to aider/commands.py.
# Context:
USER: add an /exit command which calls sys.exit
ASSISTANT: To add an `/exit` command, we need to modify the `commands.py` file to add a new command method and update the `is_command` and `run` methods to recognize and execute the new command. We also need to import `sys` to use `sys.exit()`.

Here are the changes:

```python
aider/commands.py
<<<<<<< ORIGINAL
from . import io
=======
import sys
from . import io
>>>>>>> UPDATED
```

```python
aider/commands
^C KeyboardInterrupt
USER: I added the content of these additional files: aider/commands.py
ASSISTANT: I apologize for the confusion. Here are the changes to add the `/exit` command to the `aider/commands.py` file:

```python
aider/commands.py
<<<<<<< ORIGINAL
import os
import git
import subprocess
import shlex
=======
import sys
import os
import git
import subprocess
import shlex
>>>>>>> UPDATED
```

```python
aider/commands.py
<<<<<<< ORIGINAL
        commands = ["/help"]
=======
        commands = ["/help", "/exit"]
>>>>>>> UPDATED
```

```python
aider/commands.py
<<<<<<< ORIGINAL
        else:
            self.io.tool_error(f"Error: {first_word} is not a valid command.")
=======
        elif first_word == "/exit":
            self.cmd_exit()
        else:
            self.io.tool_error(f"Error: {first_word} is not a valid command.")
>>>>>>> UPDATED
```

```python
aider/commands.py
<<<<<<< ORIGINAL
    def cmd_ls(self, args):
        "List all known files and those included in the chat session"
=======
    def cmd_exit(self):
        "Exit the application"
        sys.exit()

    def cmd_ls(self, args):
        "List all known files and those included in the chat session"
>>>>>>> UPDATED
```

These changes will add the `/exit` command to the list of commands, recognize it when entered, and call the `cmd_exit` method to exit the application using `sys.exit()`.
2023-05-26 12:16:59 -07:00
Paul Gauthier
e09b1cf2d7 Changed /commit command to commit outstanding changes to the repo instead of chat session files. 2023-05-22 09:54:37 -07:00
Paul Gauthier
1391e9de9b aider: Updated cmd_run method in aider/commands.py to use the io version of Confirm.ask().
# Context:
USER: in commands, switch the Confirm.ask() calls to use the io versions
ASSISTANT: I will update the `cmd_add` method in the `aider/commands.py` file to use the `io` versions of `Confirm.ask()`.

^C KeyboardInterrupt
USER: switch the Confirm.ask() calls to use the io versions
ASSISTANT: I will update the `cmd_add` method in the `aider/commands.py` file to use the `io` versions of `Confirm.ask()`.

```python
aider/commands.py
<<<<<<< ORIGINAL
                if self.coder.repo is not None:
                    create_file = self.io.confirm_ask(
                        (
                            f"No files matched
^C KeyboardInterrupt
USER: no, they already do. cmd_run
ASSISTANT: I apologize for the confusion. I will update the `cmd_run` method in the `aider/commands.py` file to use the `io` version of `Confirm.ask()`.

```python
aider/commands.py
<<<<<<< ORIGINAL
        ok = Confirm.ask("Add the output to the chat?", default="y")
=======
        ok = self.io.confirm_ask("Add the output to the chat?", default="y")
>>>>>>> UPDATED
```
2023-05-19 10:18:49 -07:00