refactor: move clipboard context functionality to commands.py

This commit is contained in:
Paul Gauthier 2024-12-05 20:41:40 -08:00 committed by Paul Gauthier (aider)
parent 402940a215
commit 623770e24b
5 changed files with 54 additions and 52 deletions

View file

@ -5,49 +5,3 @@ from .editor_editblock_prompts import EditorEditBlockPrompts
class EditorEditBlockCoder(EditBlockCoder):
edit_format = "editor-diff"
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

View file

@ -1399,6 +1399,41 @@ class Commands:
if user_input.strip():
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):
if file_path.is_file():

View file

@ -13,6 +13,7 @@ class ClipboardWatcher:
self.stop_event = None
self.watcher_thread = None
self.last_clipboard = None
self.io.clipboard_watcher = self
def start(self):
"""Start watching clipboard for changes"""
@ -25,8 +26,8 @@ class ClipboardWatcher:
current = pyperclip.paste()
if current != self.last_clipboard:
self.last_clipboard = current
self.io.placeholder = current
self.io.interrupt_input()
self.io.placeholder = current
time.sleep(0.5)
except Exception as e:
if self.verbose:

View file

@ -176,6 +176,7 @@ class AutoCompleter(Completer):
class InputOutput:
num_error_outputs = 0
num_user_asks = 0
clipboard_watcher = None
def __init__(
self,
@ -470,8 +471,11 @@ class InputOutput:
self.placeholder = None
self.interrupted = False
if not multiline_input and self.file_watcher:
self.file_watcher.start()
if not multiline_input:
if self.file_watcher:
self.file_watcher.start()
if self.clipboard_watcher:
self.clipboard_watcher.start()
line = self.prompt_session.prompt(
show,
@ -487,8 +491,10 @@ class InputOutput:
# Check if we were interrupted by a file change
if self.interrupted:
cmd = self.file_watcher.process_changes()
return cmd
line = line or ""
if self.file_watcher:
cmd = self.file_watcher.process_changes()
return cmd
except EOFError:
return ""
@ -504,6 +510,8 @@ class InputOutput:
finally:
if self.file_watcher:
self.file_watcher.stop()
if self.clipboard_watcher:
self.clipboard_watcher.stop()
if line.strip("\r\n") and not multiline_input:
stripped = line.strip("\r\n")

View file

@ -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,
)
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:
io.tool_output("Model metadata:")
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
if args.copypaste:
coder.clipboard_watcher = ClipboardWatcher(coder.io, verbose=args.verbose)
ClipboardWatcher(coder.io, verbose=args.verbose)
coder.show_announcements()