mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-29 08:44:59 +00:00
refactor: move clipboard context functionality to commands.py
This commit is contained in:
parent
402940a215
commit
623770e24b
5 changed files with 54 additions and 52 deletions
|
@ -5,49 +5,3 @@ from .editor_editblock_prompts import EditorEditBlockPrompts
|
||||||
class EditorEditBlockCoder(EditBlockCoder):
|
class EditorEditBlockCoder(EditBlockCoder):
|
||||||
edit_format = "editor-diff"
|
edit_format = "editor-diff"
|
||||||
gpt_prompts = EditorEditBlockPrompts()
|
gpt_prompts = EditorEditBlockPrompts()
|
||||||
|
|
||||||
def format_chat_markdown(self):
|
|
||||||
chunks = self.format_chat_chunks()
|
|
||||||
|
|
||||||
markdown = ""
|
|
||||||
|
|
||||||
# Only include specified chunks in order
|
|
||||||
for messages in [chunks.repo, chunks.readonly_files, chunks.chat_files, chunks.cur]:
|
|
||||||
for msg in messages:
|
|
||||||
# Only include user messages
|
|
||||||
if msg["role"] != "user":
|
|
||||||
continue
|
|
||||||
|
|
||||||
content = msg["content"]
|
|
||||||
|
|
||||||
# Handle image/multipart content
|
|
||||||
if isinstance(content, list):
|
|
||||||
for part in content:
|
|
||||||
if part.get("type") == "text":
|
|
||||||
markdown += part["text"] + "\n\n"
|
|
||||||
else:
|
|
||||||
markdown += content + "\n\n"
|
|
||||||
|
|
||||||
return markdown.strip()
|
|
||||||
|
|
||||||
def format_chat_chunks(self):
|
|
||||||
chunks = super().format_chat_chunks()
|
|
||||||
# Only add reminder if there are current messages
|
|
||||||
if chunks.cur:
|
|
||||||
final = chunks.cur[-1]
|
|
||||||
if self.main_model.reminder == "sys" and self.gpt_prompts.system_reminder:
|
|
||||||
chunks.reminder = [
|
|
||||||
dict(
|
|
||||||
role="system",
|
|
||||||
content=self.fmt_system_prompt(self.gpt_prompts.system_reminder),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
elif self.main_model.reminder == "user" and final["role"] == "user":
|
|
||||||
# stuff it into the user message
|
|
||||||
new_content = (
|
|
||||||
final["content"]
|
|
||||||
+ "\n\n"
|
|
||||||
+ self.fmt_system_prompt(self.gpt_prompts.system_reminder)
|
|
||||||
)
|
|
||||||
chunks.cur[-1] = dict(role=final["role"], content=new_content)
|
|
||||||
return chunks
|
|
||||||
|
|
|
@ -1399,6 +1399,41 @@ class Commands:
|
||||||
if user_input.strip():
|
if user_input.strip():
|
||||||
self.io.set_placeholder(user_input.rstrip())
|
self.io.set_placeholder(user_input.rstrip())
|
||||||
|
|
||||||
|
def cmd_copy_context(self, args=None):
|
||||||
|
"""Copy the current chat context as markdown, suitable to paste into a web UI"""
|
||||||
|
|
||||||
|
chunks = self.coder.format_chat_chunks()
|
||||||
|
|
||||||
|
markdown = ""
|
||||||
|
|
||||||
|
# Only include specified chunks in order
|
||||||
|
for messages in [chunks.repo, chunks.readonly_files, chunks.chat_files]:
|
||||||
|
for msg in messages:
|
||||||
|
# Only include user messages
|
||||||
|
if msg["role"] != "user":
|
||||||
|
continue
|
||||||
|
|
||||||
|
content = msg["content"]
|
||||||
|
|
||||||
|
# Handle image/multipart content
|
||||||
|
if isinstance(content, list):
|
||||||
|
for part in content:
|
||||||
|
if part.get("type") == "text":
|
||||||
|
markdown += part["text"] + "\n\n"
|
||||||
|
else:
|
||||||
|
markdown += content + "\n\n"
|
||||||
|
|
||||||
|
markdown += """
|
||||||
|
Just tell me how to edit the files to make the changes.
|
||||||
|
Don't give me back entire files.
|
||||||
|
Just show me the edits I need to make.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
pyperclip.copy(markdown)
|
||||||
|
self.io.tool_output("Copied context to clipboard.")
|
||||||
|
|
||||||
|
|
||||||
def expand_subdir(file_path):
|
def expand_subdir(file_path):
|
||||||
if file_path.is_file():
|
if file_path.is_file():
|
||||||
|
|
|
@ -13,6 +13,7 @@ class ClipboardWatcher:
|
||||||
self.stop_event = None
|
self.stop_event = None
|
||||||
self.watcher_thread = None
|
self.watcher_thread = None
|
||||||
self.last_clipboard = None
|
self.last_clipboard = None
|
||||||
|
self.io.clipboard_watcher = self
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start watching clipboard for changes"""
|
"""Start watching clipboard for changes"""
|
||||||
|
@ -25,8 +26,8 @@ class ClipboardWatcher:
|
||||||
current = pyperclip.paste()
|
current = pyperclip.paste()
|
||||||
if current != self.last_clipboard:
|
if current != self.last_clipboard:
|
||||||
self.last_clipboard = current
|
self.last_clipboard = current
|
||||||
self.io.placeholder = current
|
|
||||||
self.io.interrupt_input()
|
self.io.interrupt_input()
|
||||||
|
self.io.placeholder = current
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
|
|
16
aider/io.py
16
aider/io.py
|
@ -176,6 +176,7 @@ class AutoCompleter(Completer):
|
||||||
class InputOutput:
|
class InputOutput:
|
||||||
num_error_outputs = 0
|
num_error_outputs = 0
|
||||||
num_user_asks = 0
|
num_user_asks = 0
|
||||||
|
clipboard_watcher = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -470,8 +471,11 @@ class InputOutput:
|
||||||
self.placeholder = None
|
self.placeholder = None
|
||||||
|
|
||||||
self.interrupted = False
|
self.interrupted = False
|
||||||
if not multiline_input and self.file_watcher:
|
if not multiline_input:
|
||||||
self.file_watcher.start()
|
if self.file_watcher:
|
||||||
|
self.file_watcher.start()
|
||||||
|
if self.clipboard_watcher:
|
||||||
|
self.clipboard_watcher.start()
|
||||||
|
|
||||||
line = self.prompt_session.prompt(
|
line = self.prompt_session.prompt(
|
||||||
show,
|
show,
|
||||||
|
@ -487,8 +491,10 @@ class InputOutput:
|
||||||
|
|
||||||
# Check if we were interrupted by a file change
|
# Check if we were interrupted by a file change
|
||||||
if self.interrupted:
|
if self.interrupted:
|
||||||
cmd = self.file_watcher.process_changes()
|
line = line or ""
|
||||||
return cmd
|
if self.file_watcher:
|
||||||
|
cmd = self.file_watcher.process_changes()
|
||||||
|
return cmd
|
||||||
|
|
||||||
except EOFError:
|
except EOFError:
|
||||||
return ""
|
return ""
|
||||||
|
@ -504,6 +510,8 @@ class InputOutput:
|
||||||
finally:
|
finally:
|
||||||
if self.file_watcher:
|
if self.file_watcher:
|
||||||
self.file_watcher.stop()
|
self.file_watcher.stop()
|
||||||
|
if self.clipboard_watcher:
|
||||||
|
self.clipboard_watcher.stop()
|
||||||
|
|
||||||
if line.strip("\r\n") and not multiline_input:
|
if line.strip("\r\n") and not multiline_input:
|
||||||
stripped = line.strip("\r\n")
|
stripped = line.strip("\r\n")
|
||||||
|
|
|
@ -688,6 +688,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||||
editor_edit_format=args.editor_edit_format,
|
editor_edit_format=args.editor_edit_format,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if args.copypaste and args.edit_format is None:
|
||||||
|
if main_model.edit_format in ("diff", "whole"):
|
||||||
|
main_model.edit_format = "editor-" + main_model.edit_format
|
||||||
|
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
io.tool_output("Model metadata:")
|
io.tool_output("Model metadata:")
|
||||||
io.tool_output(json.dumps(main_model.info, indent=4))
|
io.tool_output(json.dumps(main_model.info, indent=4))
|
||||||
|
@ -828,7 +832,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||||
coder.file_watcher = file_watcher
|
coder.file_watcher = file_watcher
|
||||||
|
|
||||||
if args.copypaste:
|
if args.copypaste:
|
||||||
coder.clipboard_watcher = ClipboardWatcher(coder.io, verbose=args.verbose)
|
ClipboardWatcher(coder.io, verbose=args.verbose)
|
||||||
|
|
||||||
coder.show_announcements()
|
coder.show_announcements()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue