Commit graph

190 commits

Author SHA1 Message Date
Paul Gauthier
85fb17710f WIP: Add prompt_toolkit style and use it in prompt. 2023-05-09 09:54:50 -07:00
Paul Gauthier
240d1fa727 Remove custom style from prompt function call in coder.py to fix prompt_toolkit rendering issue.
# Context:
USER: Traceback (most recent call last):
  File "/Users/gauthier/Projects/chatgpt/./coder.py", line 496, in <module>
    status = main()
  File "/Users/gauthier/Projects/chatgpt/main.py", line 76, in main
    coder.run()
  File "/Users/gauthier/Projects/chatgpt/coder.py", line 206, in run
    self.run_loop()
  File "/Users/gauthier/Projects/chatgpt/coder.py", line 217, in run_loop
    inp = self.get_input()
  File "/Users/gauthier/Projects/chatgpt/coder.py", line 158, in get_input
    line = prompt(
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 1420, in prompt
    return session.prompt(
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 1035, in prompt
    return self.app.run(
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 961, in run
    return loop.run_until_complete(coro)
  File "/usr/local/Cellar/python@3.9/3.9.16/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 875, in run_async
    return await _run_async(f)
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 733, in _run_async
    self._redraw()
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 548, in _redraw
    self.context.copy().run(run_in_context)
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 531, in run_in_context
    self.renderer.render(self, self.layout)
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/renderer.py", line 652, in render
    self.style.invalidation_hash() != self._last_style_hash
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/styles/style.py", line 400, in invalidation_hash
    return tuple(s.invalidation_hash() for s in self.styles)
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/styles/style.py", line 400, in <genexpr>
    return tuple(s.invalidation_hash() for s in self.styles)
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/styles/base.py", line 179, in invalidation_hash
    return (self.get_style() or self._dummy).invalidation_hash()
  File "/Users/gauthier/Projects/chatgpt/.venv/lib/python3.9/site-packages/prompt_toolkit/styles/base.py", line 179, in invalidation_hash
    return (self.get_style() or self._dummy).invalidation_hash()
AttributeError: 'str' object has no attribute 'invalidation_hash'

ASSISTANT: It seems like there is an issue with the `prompt_toolkit` library when trying to render the prompt. The error is related to the `invalidation_hash` method in the `style.py` file. To fix this issue, we can update the `get_input` method in the `coder.py` file to use a default style instead of the custom one.

Here's the change you need to make in the `coder.py` file:

```python
coder.py
<<<<<<< ORIGINAL
    line = prompt(
        show,
        completer=completer_instance,
        history=FileHistory(self.history_file),
        style="fg:green",
    )
=======
    line = prompt(
        show,
        completer=completer_instance,
        history=FileHistory(self.history_file),
    )
>>>>>>> UPDATED
```

This change removes the custom style (`style="fg:green"`) from the `prompt` function call, which should resolve the `AttributeError` you encountered.
2023-05-09 09:51:30 -07:00
Paul Gauthier
2de786a651 Change prompt text color to green.
# Context:
USER: have the prompt() call show the text in green
ASSISTANT: To change the text color of the prompt to green, you can use the `style` parameter in the `prompt()` function. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
                line = prompt(
                    show,
                    completer=completer_instance,
                    history=FileHistory(self.history_file),
                )
=======
                line = prompt(
                    show,
                    completer=completer_instance,
                    history=FileHistory(self.history_file),
                    style="fg:green",
                )
>>>>>>> UPDATED
```

This will make the text entered in the prompt appear green.
2023-05-09 09:48:59 -07:00
Paul Gauthier
8c88d0fca8 cleaned up filehistory 2023-05-09 09:48:17 -07:00
Paul Gauthier
1b28d24874 WIP: Refactor regex pattern in coder.py to include file extensions. 2023-05-09 09:44:15 -07:00
Paul Gauthier
6e9e384e5c Add FileHistory to prompt function calls in get_input method.
# Context:
USER: your change to the get_input method didn't work because you formatted it wrong. try again. no ...
ASSISTANT: I apologize for the confusion. Here's the updated change to the get_input method without using "...":

```python
coder.py
<<<<<<< ORIGINAL
                if multiline_input:
                    line = prompt(". ", completer=completer_instance)
                else:
                    line = prompt("> ", completer=completer_instance)
=======
                if multiline_input:
                    line = prompt(". ", completer=completer_instance, history=FileHistory(self.history_file))
                else:
                    line = prompt("> ", completer=completer_instance, history=FileHistory(self.history_file))
>>>>>>> UPDATED
```

This change adds the FileHistory to the prompt function calls in the get_input method.
2023-05-09 09:37:28 -07:00
Paul Gauthier
bc2c59368b Add FileHistory to get_input method in Coder class.
# Context:
USER: have get_input(self): use a FileHistory with the history_file
ASSISTANT: To use a FileHistory with the history_file in the get_input(self) method, we need to import FileHistory from prompt_toolkit.history and use it when calling the prompt function. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
=======
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.history import FileHistory
>>>>>>> UPDATED

...

class Coder:
    ...
    def get_input(self):
        ...
        while True:
            try:
                completer_instance = FileContentCompleter(self.fnames)
                if multiline_input:
                    line = prompt(". ", completer=completer_instance, history=FileHistory(self.history_file))
                else:
                    line = prompt("> ", completer=completer_instance, history=FileHistory(self.history_file))
            except EOFError:
                return
```
This change imports FileHistory and adds it as an argument to the prompt function calls in the get_input method.
2023-05-09 09:36:42 -07:00
Paul Gauthier
fe222d8943 fixed indent 2023-05-09 09:22:29 -07:00
Paul Gauthier
59e664e220 Connect FileContentCompleter to prompt() call in get_input() for autocompletion.`
# Context:
USER: connect the filecontentcompleter to the prompt() call in get_input, so that it autocompletes
ASSISTANT: To connect the `FileContentCompleter` to the `prompt()` call in the `get_input` method, you need to pass the `FileContentCompleter` instance as the `completer` argument in the `prompt()` function. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
            if multiline_input:
                line = prompt(". ")
            else:
                line = prompt("> ")
=======
            completer_instance = FileContentCompleter(self.fnames)
            if multiline_input:
                line = prompt(". ", completer=completer_instance)
            else:
                line = prompt("> ", completer=completer_instance)
>>>>>>> UPDATED
```

This change will enable autocompletion using the `FileContentCompleter` when you call `prompt()`.
2023-05-09 09:20:58 -07:00
Paul Gauthier
36d15d5f37 Add autocompletion based on the contents of the files in self.fnames.
# Context:
USER: have prompt_toolkit autocomplete based on the contents of the files in self.fnames
ASSISTANT: To add autocompletion based on the contents of the files in `self.fnames`, you can use the `Completer` class from `prompt_toolkit`. Here's how to implement it:

1. Import the necessary classes and functions from `prompt_toolkit`.
2. Create a custom completer class that inherits from `Completer`.
3. Override the `get_completions` method to provide completions based on the contents of the files.
4. Use the custom completer when calling the `prompt` function.

Here are the changes to the code:

```python
coder.py
<<<<<<< ORIGINAL
from prompt_toolkit import prompt
=======
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
>>>>>>> UPDATED
```

```python
coder.py
<<<<<<< ORIGINAL
class Coder:
    fnames = dict()
    last_modified = 0
    repo = None
=======
class FileContentCompleter(Completer):
    def __init__(self, fnames):
        self.fnames = fnames

    def get_completions(self, document, complete_event):
        text = document.text_before_cursor
        words = text.split()
        if not words:
            return

        last_word = words[-1]
        for fname in self.fnames:
            with open(fname, "r") as f:
                content = f.read()
            for word in content.split():
                if word.startswith(last_word):
                    yield Completion(word, start_position=-len(last_word))

class Coder:
    fnames = dict()
    last_modified = 0
    repo = None
>>>>>>> UPDATED
```

```python
coder.py
<<<<<<< ORIGINAL
line = prompt("> ")
=======
completer = FileContentCompleter(self.fnames)
line = prompt("> ", completer=completer)
>>>>>>> UPDATED
```

These changes will add autocompletion based on the contents of the files in `self.fnames`.
2023-05-09 09:11:29 -07:00
Paul Gauthier
18b1809159 WIP: Comment out history file write in coder.py. 2023-05-09 09:09:45 -07:00
Paul Gauthier
b2e9eb05f0 WIP: Refactor Coder class to avoid readline dependency and fix input prompt. 2023-05-09 09:09:12 -07:00
Paul Gauthier
6ba8b7d41e Switch get_input() to use prompt_toolkit for input`.
# Context:
USER: switch get_input() to use prompt_toolkit for input
ASSISTANT: To switch `get_input()` to use `prompt_toolkit` for input, you'll need to install the `prompt_toolkit` library and replace the current input method with the `prompt_toolkit`'s `prompt` function. Here's how to make the change:

1. Install `prompt_toolkit` by adding it to your project's requirements or running `pip install prompt_toolkit`.

2. Import `prompt` from `prompt_toolkit` at the beginning of the `coder.py` file.

3. Replace the current input method in the `get_input()` function with the `prompt` function from `prompt_toolkit`.

Here are the changes to the `coder.py` file:

```python
coder.py
<<<<<<< ORIGINAL
import sys
import re
import readline
import traceback
=======
import sys
import re
import traceback
from prompt_toolkit import prompt
>>>>>>> UPDATED
```

```python
coder.py
<<<<<<< ORIGINAL
while True:
    try:
        if multiline_input:
            line = input(". ")
        else:
            line = input("> ")
    except EOFError:
        return
=======
while True:
    try:
        if multiline_input:
            line = prompt(". ")
        else:
            line = prompt("> ")
    except EOFError:
        return
>>>>>>> UPDATED
```

These changes will replace the standard `input()` function with the `prompt_toolkit`'s `prompt` function in the `get_input()` method.
2023-05-09 09:03:45 -07:00
Paul Gauthier
fb12b73975 WIP: Refactor do_replace method to utils module and update references in coder module. 2023-05-09 07:31:26 -07:00
Paul Gauthier
11a5379d61 moved console print statements to indicate success or failure of applying edits. 2023-05-09 07:25:20 -07:00
Paul Gauthier
d6de4d3877 cleanup 2023-05-09 07:23:10 -07:00
Paul Gauthier
0b265d6608 colorize diff output 2023-05-09 07:17:57 -07:00
Paul Gauthier
4b56381382 strip() the before_text when looking for empty ORIGINAL 2023-05-09 07:10:40 -07:00
Paul Gauthier
cbfdd2a806 copy 2023-05-09 00:39:54 -07:00
Paul Gauthier
9d3ed13359 catch ^c in commit() and use default commit message 2023-05-09 00:38:45 -07:00
Paul Gauthier
3c1681942a WIP: Refactor commit message to show added files. 2023-05-09 00:15:39 -07:00
Paul Gauthier
71f992d1c7 linting 2023-05-09 00:14:13 -07:00
Paul Gauthier
437d735485 WIP: Import sys module in coder.py. 2023-05-09 00:13:31 -07:00
Paul Gauthier
6220dc56bf Updated initial commit message to list added files.
# Context:
USER: change the "Initial commit" message to list the files being added
ASSISTANT: ```python
coder.py
<<<<<<< ORIGINAL
                commit_message = "Initial commit: Added new files to the git repo."
=======
                commit_message = f"Initial commit: Added new files to the git repo: {', '.join(new_files)}"
>>>>>>> UPDATED
```
2023-05-09 00:12:31 -07:00
Paul Gauthier
cd2800180f Move main() function to main.py and update coder.py to call main() from main.py.
# Context:
USER: move main() to main.py
ASSISTANT: To move the `main()` function to a new file called `main.py`, you'll need to create the new file and move the `main()` function and its related imports to it. Then, you'll need to import and call the `main()` function from `main.py` in `coder.py`.

Here are the changes you need to make:

Create a new file called `main.py` and add the following content:

```python
main.py
<<<<<<< ORIGINAL
=======
import sys
import argparse
from pathlib import Path
from dotenv import load_dotenv
from coder import Coder

def main():
    load_dotenv()
    env_prefix = "CODER_"
    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files",
        metavar="FILE",
        nargs="+",
        help="a list of source code files",
    )
    parser.add_argument(
        "--history-file",
        metavar="HISTORY_FILE",
        default=os.environ.get("CODER_HISTORY_FILE", ".coder.history"),
        help="Specify the history file (default: .coder.history or value from CODER_HISTORY_FILE environment variable)",
    )
    parser.add_argument(
        "--model",
        metavar="MODEL",
        default="gpt-4",
        help="Specify the model to use for the main chat (default: gpt-4)",
    )
    parser.add_argument(
        "-3",
        action="store_const",
        dest="model",
        const="gpt-3.5-turbo",
        help="Use gpt-3.5-turbo model for the main chat",
    )
    parser.add_argument(
        "-4",
        action="store_const",
        dest="model",
        const="gpt-4",
        help="Use gpt-4 model for the main chat",
    )
    parser.add_argument(
        "--no-pretty",
        action="store_false",
        dest="pretty",
        help="Disable prettyd output of GPT responses",
        default=bool(int(os.environ.get(env_prefix + "PRETTY", 1))),
    )
    parser.add_argument(
        "--apply",
        metavar="FILE",
        help="Apply the changes from the given file instead of running the chat",
    )
    parser.add_argument(
        "--commit-dirty",
        action="store_true",
        help="Commit dirty files without confirmation",
        default=bool(int(os.environ.get(env_prefix + "COMMIT_DIRTY", 0))),
    )
    args = parser.parse_args()

    fnames = args.files
    pretty = args.pretty

    coder = Coder(args.model, fnames, pretty, args.history_file)
    coder.commit(ask=not args.commit_dirty, prefix="WIP: ")

    if args.apply:
        with open(args.apply, "r") as f:
            content = f.read()
        coder.update_files(content, inp="")
        return

    coder.run()

if __name__ == "__main__":
    status = main()
    sys.exit(status)
>>>>>>> UPDATED
```

Now, update `coder.py` to remove the `main()` function and its related imports, and call the `main()` function from `main.py`:

```python
coder.py
<<<<<<< ORIGINAL
import sys
import re
import readline
import traceback
import argparse
from rich.console import Console
from rich.prompt import Confirm, Prompt
from colorama import Fore, Style
from rich.live import Live
from rich.text import Text
from rich.markdown import Markdown
from dotenv import load_dotenv

from tqdm import tqdm

from pathlib import Path
import utils

import os
import git
import openai

from dump import dump

import prompts

openai.api_key = os.getenv("OPENAI_API_KEY")
=======
import re
import readline
import traceback
from rich.console import Console
from rich.prompt import Confirm, Prompt
from colorama import Fore, Style
from rich.live import Live
from rich.text import Text
from rich.markdown import Markdown

from tqdm import tqdm

from pathlib import Path
import utils

import os
import git
import openai

from dump import dump

import prompts

openai.api_key = os.getenv("OPENAI_API_KEY")
>>>>>>> UPDATED
```

```python
coder.py
<<<<<<< ORIGINAL
def main():
    load_dotenv()
    env_prefix = "CODER_"
    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files",
        metavar="FILE",
        nargs="+",
        help="a list of source code files",
    )
    parser.add_argument(
        "--history-file",
        metavar="HISTORY_FILE",
        default=os.environ.get("CODER_HISTORY_FILE", ".coder.history"),
        help="Specify the history file (default: .coder.history or value from CODER_HISTORY_FILE environment variable)",
    )
    parser.add_argument(
        "--model",
        metavar="MODEL",
        default="gpt-4",
        help="Specify the model to use for the main chat (default: gpt-4)",
    )
    parser.add_argument(
        "-3",
        action="store_const",
        dest="model",
        const="gpt-3.5-turbo",
        help="Use gpt-3.5-turbo model for the main chat",
    )
    parser.add_argument(
        "-4",
        action="store_const",
        dest="model",
        const="gpt-4",
        help="Use gpt-4 model for the main chat",
    )
    parser.add_argument(
        "--no-pretty",
        action="store_false",
        dest="pretty",
        help="Disable prettyd output of GPT responses",
        default=bool(int(os.environ.get(env_prefix + "PRETTY", 1))),
    )
    parser.add_argument(
        "--apply",
        metavar="FILE",
        help="Apply the changes from the given file instead of running the chat",
    )
    parser.add_argument(
        "--commit-dirty",
        action="store_true",
        help="Commit dirty files without confirmation",
        default=bool(int(os.environ.get(env_prefix + "COMMIT_DIRTY", 0))),
    )
    args = parser.parse_args()

    fnames = args.files
    pretty = args.pretty

    coder = Coder(args.model, fnames, pretty, args.history_file)
    coder.commit(ask=not args.commit_dirty, prefix="WIP: ")

    if args.apply:
        with open(args.apply, "r") as f:
            content = f.read()
        coder.update_files(content, inp="")
        return

    coder.run()

if __name__ == "__main__":
    status = main()
    sys.exit(status)
=======
if __name__ == "__main__":
    from main import main
    status = main()
    sys.exit(status)
>>>>>>> UPDATED
```

These changes will move the `main()` function to `main.py` and update `coder.py` to call the `main()` function from `main.py`.
2023-05-09 00:10:56 -07:00
Paul Gauthier
1a306d89d9 WIP: Refactor send method and remove show_send_progress method in Coder class. 2023-05-09 00:05:48 -07:00
Paul Gauthier
5c2cbd301e WIP: Fix missing newline at end of file in coder.py. 2023-05-09 00:03:09 -07:00
Paul Gauthier
85c902843a Move quoted_file function from coder.py to utils.py and update get_files_content function in coder.py to use utils.quoted_file.
# Context:
USER: move quoted_file to utils
ASSISTANT: To move the `quoted_file` function from `coder.py` to `utils.py`, we will remove it from `coder.py` and add it to `utils.py`.

```python
coder.py
<<<<<<< ORIGINAL
    def quoted_file(self, fname):
        prompt = "\n"
        prompt += fname
        prompt += "\n```\n"
        prompt += Path(fname).read_text()
        prompt += "\n```\n"
        return prompt

    def get_files_content(self):
        prompt = ""
        for fname in self.fnames:
            prompt += self.quoted_file(fname)
        return prompt
=======
    def get_files_content(self):
        prompt = ""
        for fname in self.fnames:
            prompt += utils.quoted_file(fname)
        return prompt
>>>>>>> UPDATED
```

```python
utils.py
<<<<<<< ORIGINAL
def strip_quoted_wrapping(res, fname=None):
    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 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):
    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
>>>>>>> UPDATED
```

Now the `quoted_file` function has been moved to `utils.py`, and the `get_files_content` function in `coder.py` has been updated to use `utils.quoted_file`.
2023-05-09 00:00:48 -07:00
Paul Gauthier
1b4266c33c WIP: Refactor coder.py to use utils.replace_most_similar_chunk and add utils.strip_quoted_wrapping. 2023-05-08 23:58:14 -07:00
Paul Gauthier
05c39b7329 Move strip_quoted_wrapping function from coder.py to utils.py and update its usage in coder.py.
# Context:
USER: move strip_quoted_wrapping into utils
ASSISTANT: To move the `strip_quoted_wrapping` function from `coder.py` to `utils.py`, you need to make the following changes:

In `coder.py`, remove the `strip_quoted_wrapping` function:

```python
coder.py
<<<<<<< ORIGINAL
    def strip_quoted_wrapping(self, res, fname=None):
        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
=======
>>>>>>> UPDATED
```

In `utils.py`, add the `strip_quoted_wrapping` function:

```python
utils.py
<<<<<<< ORIGINAL
=======
def strip_quoted_wrapping(res, fname=None):
    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
>>>>>>> UPDATED
```

Finally, update the usage of `strip_quoted_wrapping` in `coder.py` to use the function from `utils.py`:

```python
coder.py
<<<<<<< ORIGINAL
        before_text = self.strip_quoted_wrapping(before_text, fname)
        after_text = self.strip_quoted_wrapping(after_text, fname)
=======
        before_text = utils.strip_quoted_wrapping(before_text, fname)
        after_text = utils.strip_quoted_wrapping(after_text, fname)
>>>>>>> UPDATED
```
2023-05-08 23:54:58 -07:00
Paul Gauthier
a232adb43e Add blank line before commit prompt in coder.py. 2023-05-08 23:50:23 -07:00
Paul Gauthier
73bd751d2d WIP: Refactor import statement in coder.py. 2023-05-08 23:49:46 -07:00
Paul Gauthier
303e9742af WIP: Fix typo in coder.py commit prompt. 2023-05-08 23:48:36 -07:00
Paul Gauthier
860c2828ce WIP: Remove unused method do_gpt_powered_replace from Coder class. 2023-05-08 23:47:19 -07:00
Paul Gauthier
fd127076df Add command line argument for history file with environment variable default and pass it to Coder class.
# Context:
USER: make a cmd line arg with environ default for history_file, pass it into Coder.__init__
ASSISTANT: To add a command line argument for the history file with an environment variable default, you can update the `argparse` section in the `main()` function. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files",
        metavar="FILE",
        nargs="+",
        help="a list of source code files",
    )
=======
    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files",
        metavar="FILE",
        nargs="+",
        help="a list of source code files",
    )
    parser.add_argument(
        "--history-file",
        metavar="HISTORY_FILE",
        default=os.environ.get("CODER_HISTORY_FILE", ".coder.history"),
        help="Specify the history file (default: .coder.history or value from CODER_HISTORY_FILE environment variable)",
    )
>>>>>>> UPDATED
```

Next, pass the `history_file` argument to the `Coder` class in the `main()` function:

```python
coder.py
<<<<<<< ORIGINAL
    coder = Coder(args.model, fnames, pretty)
=======
    coder = Coder(args.model, fnames, pretty, args.history_file)
>>>>>>> UPDATED
```

Finally, update the `Coder` class to accept the `history_file` argument and use it in the `__init__` method:

```python
coder.py
<<<<<<< ORIGINAL
class Coder:
    fnames = dict()
    last_modified = 0
    repo = None
    history_file = ".coder.history"

    def __init__(self, main_model, files, pretty):
=======
class Coder:
    fnames = dict()
    last_modified = 0
    repo = None

    def __init__(self, main_model, files, pretty, history_file=".coder.history"):
        self.history_file = history_file
>>>>>>> UPDATED
```
Now, the history file can be specified using the `--history-file` command line argument or the `CODER_HISTORY_FILE` environment variable.
2023-05-08 23:45:55 -07:00
Paul Gauthier
fed71fef4c move history file into Coder 2023-05-08 23:43:54 -07:00
Paul Gauthier
81b8d193bc Move history_file from global into Coder class.
# Context:
USER: move history_file from global into Coder
ASSISTANT: To move the `history_file` variable from the global scope into the `Coder` class, you can add it as a class attribute and update its usage accordingly.

```python
coder.py
<<<<<<< ORIGINAL
history_file = ".coder.history"
try:
    readline.read_history_file(history_file)
except FileNotFoundError:
    pass
=======
class Coder:
    history_file = ".coder.history"

    def __init__(self, main_model, files, pretty):
        # ...
        try:
            readline.read_history_file(self.history_file)
        except FileNotFoundError:
            pass
        # ...
>>>>>>> UPDATED
```

```python
coder.py
<<<<<<< ORIGINAL
        readline.write_history_file(history_file)
=======
        readline.write_history_file(self.history_file)
>>>>>>> UPDATED
```
2023-05-08 23:42:55 -07:00
Paul Gauthier
782d4c3659 disabled gpt-3.5 powered edits 2023-05-08 23:40:56 -07:00
Paul Gauthier
94afa11d19 cleanup 2023-05-08 23:31:46 -07:00
Paul Gauthier
b401c803e4 Refactor check_for_local_edits to get_last_modified and update last_modified in commit method. 2023-05-08 23:28:42 -07:00
Paul Gauthier
af972538f1 WIP: Add load_dotenv import and remove unused imports in coder.py. 2023-05-08 23:19:36 -07:00
Paul Gauthier
bd88c4c40f Load environment variables from a .env file using python-dotenv package.
# Context:
USER: load dotenv
ASSISTANT: To load environment variables from a `.env` file using the `python-dotenv` package, you can add the following lines at the beginning of the `main()` function in the `coder.py` file:

```python
import os
from dotenv import load_dotenv

load_dotenv()
```

You will also need to install the `python-dotenv` package if you haven't already. You can install it using pip:

```
pip install python-dotenv
```

Here's the change to the `coder.py` file:

```python
coder.py
<<<<<<< ORIGINAL
def main():
    env_prefix = "CODER_"
=======
import os
from dotenv import load_dotenv

def main():
    load_dotenv()
    env_prefix = "CODER_"
>>>>>>> UPDATED
```
2023-05-08 23:17:25 -07:00
Paul Gauthier
50ba2136b7 fix --pretty and add console argument to Prompt.ask() method call 2023-05-08 23:16:40 -07:00
Paul Gauthier
2f06ce08a3 WIP: Refactor Coder class constructor to accept a main_model argument instead of a boolean flag, and update CLI help messages accordingly. 2023-05-08 23:12:33 -07:00
Paul Gauthier
e5e5a8e325 Add --model MODEL arg and modify -3 and -4 args to store gpt-3-5-turbo and gpt-4 in model arg.
# Context:
USER: add a --model MODEL arg, and change -3 to store 'gpt-3-5-turbo' in the model arg. add a new arg -4 which stores 'gpt-4' in the model arg.
ASSISTANT: To add a `--model MODEL` argument and modify the `-3` and `-4` arguments, you can update the `main` function as follows:

```python
coder.py
<<<<<<< ORIGINAL
    parser.add_argument(
        "-3",
        "--gpt-3-5-turbo",
        action="store_true",
        help="Only use gpt-3.5-turbo, not gpt-4",
    )
=======
    parser.add_argument(
        "--model",
        metavar="MODEL",
        default="gpt-3.5-turbo",
        help="Specify the model to use (default: gpt-3.5-turbo)",
    )
    parser.add_argument(
        "-3",
        action="store_const",
        dest="model",
        const="gpt-3.5-turbo",
        help="Use gpt-3.5-turbo model",
    )
    parser.add_argument(
        "-4",
        action="store_const",
        dest="model",
        const="gpt-4",
        help="Use gpt-4 model",
    )
>>>>>>> UPDATED
```

This change adds the `--model MODEL` argument, modifies the `-3` argument to store `'gpt-3-5-turbo'` in the `model` argument, and adds a new `-4` argument to store `'gpt-4'` in the `model` argument.
2023-05-08 23:10:25 -07:00
Paul Gauthier
1fc1fbae0c Refactor coder.py argparse defaults and remove duplicate default values. 2023-05-08 23:09:26 -07:00
Paul Gauthier
10192dddcd Add env_prefix variable and load default values from environment variables.
# Context:
USER: in main add a var called env_prefix="CODER_" then for every parser arg load the default from os.environ using that prefix and the uppercase, snakecase of the arg name as the env var name
ASSISTANT: To add an `env_prefix` variable and load the default values for each argument from the environment variables, you can update the `main` function as follows:

```python
coder.py
<<<<<<< ORIGINAL
def main():
    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files", metavar="FILE", nargs="+", help="a list of source code files"
    )
    parser.add_argument(
        "-3",
        "--gpt-3-5-turbo",
        action="store_true",
        help="Only use gpt-3.5-turbo, not gpt-4",
    )
    parser.add_argument(
        "--no-pretty",
        action="store_false",
        dest="pretty",
        default=True,
        help="Disable prettyd output of GPT responses",
    )
    parser.add_argument(
        "--apply",
        metavar="FILE",
        help="Apply the changes from the given file instead of running the chat",
    )
    parser.add_argument(
        "--commit",
        action="store_true",
        help="Commit dirty files without confirmation",
    )
=======
def main():
    env_prefix = "CODER_"

    parser = argparse.ArgumentParser(description="Chat with GPT about code")
    parser.add_argument(
        "files", metavar="FILE", nargs="+", help="a list of source code files",
        default=os.environ.get(env_prefix + "FILES", "").split()
    )
    parser.add_argument(
        "-3",
        "--gpt-3-5-turbo",
        action="store_true",
        help="Only use gpt-3.5-turbo, not gpt-4",
        default=bool(os.environ.get(env_prefix + "GPT_3_5_TURBO", False))
    )
    parser.add_argument(
        "--no-pretty",
        action="store_false",
        dest="pretty",
        default=True,
        help="Disable prettyd output of GPT responses",
        default=bool(os.environ.get(env_prefix + "NO_PRETTY", True))
    )
    parser.add_argument(
        "--apply",
        metavar="FILE",
        help="Apply the changes from the given file instead of running the chat",
        default=os.environ.get(env_prefix + "APPLY", None)
    )
    parser.add_argument(
        "--commit",
        action="store_true",
        help="Commit dirty files without confirmation",
        default=bool(os.environ.get(env_prefix + "COMMIT", False))
    )
>>>>>>> UPDATED
```

This change adds the `env_prefix` variable and sets the default values for each argument using the `os.environ.get()` function with the appropriate environment variable name.
2023-05-08 23:06:56 -07:00
Paul Gauthier
6fcf4ff0e7 lint 2023-05-08 23:02:14 -07:00
Paul Gauthier
1c881cd574 Fix f-string missing placeholders warning by converting f-string to a regular string.
# Context:
USER: coder.py:113:21: F541 f-string is missing placeholders
ASSISTANT: To fix the f-string missing placeholders warning, you can either add placeholders or convert the f-string to a regular string. In this case, it seems like a regular string is more appropriate. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
            self.console.print(f"[red]Creating {fname}")
=======
            self.console.print(f"[red]Creating {fname}")
>>>>>>> UPDATED
```

However, the code you provided does not have an f-string on line 113. Please double-check the line number and the code you want to modify.
2023-05-08 23:01:39 -07:00
Paul Gauthier
045acb96d3 Ignore invalid escape sequence warning for a specific line in coder.py.
# Context:
USER: coder.py:554:56: W605 invalid escape sequence '\[' ... add comment to ignore
ASSISTANT: To fix the invalid escape sequence warning, you can add a comment to ignore the warning for that specific line. Here's the change:

```python
coder.py
<<<<<<< ORIGINAL
            res = Prompt.ask(
                "[red]Commit before the chat proceeds? \[y/n/commit message]"
            ).strip()
=======
            res = Prompt.ask(
                "[red]Commit before the chat proceeds? \[y/n/commit message]"  # noqa: W605
            ).strip()
>>>>>>> UPDATED
```
2023-05-08 23:01:01 -07:00