mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-24 14:25:00 +00:00
refactor: improve file watcher change detection and comment handling
This commit is contained in:
parent
f36239712f
commit
f872b20a97
1 changed files with 53 additions and 22 deletions
|
@ -51,7 +51,7 @@ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
|
||||||
if not gitignore_paths:
|
if not gitignore_paths:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
patterns = [".aider*"] # Always ignore .aider* files
|
patterns = [".aider*", ".git"] # Always ignore
|
||||||
for path in gitignore_paths:
|
for path in gitignore_paths:
|
||||||
if path.exists():
|
if path.exists():
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
|
@ -59,18 +59,18 @@ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
|
||||||
|
|
||||||
return PathSpec.from_lines(GitWildMatchPattern, patterns) if patterns else None
|
return PathSpec.from_lines(GitWildMatchPattern, patterns) if patterns else None
|
||||||
|
|
||||||
|
|
||||||
class FileWatcher:
|
class FileWatcher:
|
||||||
"""Watches source files for changes and AI comments"""
|
"""Watches source files for changes and AI comments"""
|
||||||
|
|
||||||
def __init__(self, coder, encoding="utf-8", gitignores=None, verbose=False):
|
def __init__(self, coder, encoding="utf-8", gitignores=None, verbose=False):
|
||||||
self.coder = coder
|
self.coder = coder
|
||||||
|
self.io = coder.io
|
||||||
self.encoding = encoding
|
self.encoding = encoding
|
||||||
self.root = Path(coder.root)
|
self.root = Path(coder.root)
|
||||||
self.verbose = verbose
|
self.verbose = verbose #or True
|
||||||
self.stop_event = None
|
self.stop_event = None
|
||||||
self.watcher_thread = None
|
self.watcher_thread = None
|
||||||
self.changed_files = None
|
self.changed_files = set()
|
||||||
self.gitignores = gitignores
|
self.gitignores = gitignores
|
||||||
|
|
||||||
coder.io.file_watcher = self
|
coder.io.file_watcher = self
|
||||||
|
@ -111,6 +111,7 @@ class FileWatcher:
|
||||||
return res
|
return res
|
||||||
except (IOError, UnicodeDecodeError) as err:
|
except (IOError, UnicodeDecodeError) as err:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
|
print("error")
|
||||||
dump(err)
|
dump(err)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -119,6 +120,7 @@ class FileWatcher:
|
||||||
def start(self, ignore_func=None):
|
def start(self, ignore_func=None):
|
||||||
"""Start watching for file changes"""
|
"""Start watching for file changes"""
|
||||||
self.stop_event = threading.Event()
|
self.stop_event = threading.Event()
|
||||||
|
self.changed_files = set()
|
||||||
|
|
||||||
gitignore_paths = [Path(g) for g in self.gitignores] if self.gitignores else []
|
gitignore_paths = [Path(g) for g in self.gitignores] if self.gitignores else []
|
||||||
gitignore_spec = load_gitignores(gitignore_paths)
|
gitignore_spec = load_gitignores(gitignore_paths)
|
||||||
|
@ -132,14 +134,15 @@ class FileWatcher:
|
||||||
changed_files = {str(Path(change[1])) for change in changes}
|
changed_files = {str(Path(change[1])) for change in changes}
|
||||||
result = {}
|
result = {}
|
||||||
for file in changed_files:
|
for file in changed_files:
|
||||||
if comments := get_ai_comment(file, encoding=self.encoding):
|
if comments := self.get_ai_comment(file, encoding=self.encoding):
|
||||||
result[file] = comments
|
result[file] = comments
|
||||||
|
|
||||||
|
self.changed_files.update(result)
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
dump(result)
|
dump(result)
|
||||||
|
dump(self.changed_files)
|
||||||
if result:
|
if result:
|
||||||
self.coder.abs_fnames.update(changed_files)
|
self.io.interrupt_input()
|
||||||
self.coder.io.interrupt_input()
|
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
|
@ -158,24 +161,52 @@ class FileWatcher:
|
||||||
self.watcher_thread = None
|
self.watcher_thread = None
|
||||||
self.stop_event = None
|
self.stop_event = None
|
||||||
|
|
||||||
def get_changes(self):
|
def process_changes(self):
|
||||||
"""Get any detected file changes"""
|
"""Get any detected file changes"""
|
||||||
return self.changed_files
|
|
||||||
|
|
||||||
|
for fname in self.changed_files:
|
||||||
|
if fname in self.coder.abs_fnames:
|
||||||
|
continue
|
||||||
|
self.coder.abs_fnames.add(fname)
|
||||||
|
rel_fname = self.coder.get_rel_fname(fname)
|
||||||
|
self.io.tool_output(f"Added {rel_fname} to the chat")
|
||||||
|
self.io.tool_output()
|
||||||
|
|
||||||
def get_ai_comment(filepath, encoding="utf-8"):
|
# TODO refresh all the ai comments from all the abs_fnames
|
||||||
"""Extract all AI comments from a file"""
|
return ""
|
||||||
comments = []
|
has_bangs = any(
|
||||||
try:
|
comment.strip().endswith("!")
|
||||||
with open(filepath, encoding=encoding, errors="ignore") as f:
|
for comments in self.changed_files.values()
|
||||||
for line in f:
|
if comments for comment in comments
|
||||||
if match := re.search(r"(?:#|//) *(ai\b.*|ai)", line, re.IGNORECASE):
|
)
|
||||||
comment = match.group(0).strip()
|
|
||||||
if comment:
|
if not has_bangs:
|
||||||
comments.append(comment)
|
return ""
|
||||||
except (IOError, UnicodeDecodeError):
|
|
||||||
return None
|
res = "\n".join(comment for comments in self.changed_files.values() if comments for comment in comments)
|
||||||
return comments if comments else None
|
res = """The "ai" comments below can be found in the code above.
|
||||||
|
They contain your instructions.
|
||||||
|
Make the requested changes.
|
||||||
|
Also remove all these comments from the code.
|
||||||
|
|
||||||
|
""" + res
|
||||||
|
|
||||||
|
dump(res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_ai_comment(self, filepath, encoding="utf-8"):
|
||||||
|
"""Extract all AI comments from a file"""
|
||||||
|
comments = []
|
||||||
|
try:
|
||||||
|
with open(filepath, encoding=encoding, errors="ignore") as f:
|
||||||
|
for line in f:
|
||||||
|
if match := re.search(r"(?:#|//) *(ai\b.*|ai)", line, re.IGNORECASE):
|
||||||
|
comment = match.group(0).strip()
|
||||||
|
if comment:
|
||||||
|
comments.append(comment)
|
||||||
|
except (IOError, UnicodeDecodeError):
|
||||||
|
return None
|
||||||
|
return comments if comments else None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue