From aaf7e3f94311ac6ac63ed6e1bad3db59231c64da Mon Sep 17 00:00:00 2001 From: Mir Adnan ALI Date: Wed, 11 Dec 2024 04:58:42 -0500 Subject: [PATCH] Implement multiline-mode, swaps Enter & Meta-Enter --- aider/args.py | 6 ++++ aider/coders/base_coder.py | 3 ++ aider/commands.py | 4 +++ aider/io.py | 50 +++++++++++++++++++++++++-- aider/main.py | 1 + aider/website/_includes/multi-line.md | 4 +++ 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/aider/args.py b/aider/args.py index bfd8280cb..a44cffa4c 100644 --- a/aider/args.py +++ b/aider/args.py @@ -795,6 +795,12 @@ def get_parser(default_config_files, git_root): default=True, help="Enable/disable fancy input with history and completion (default: True)", ) + group.add_argument( + "--multiline", + action=argparse.BooleanOptionalAction, + default=False, + help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False, env: AIDER_MULTILINE)", + ) group.add_argument( "--detect-urls", action=argparse.BooleanOptionalAction, diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 3ef0d21c2..ab662aebd 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -248,6 +248,9 @@ class Coder: if self.done_messages: lines.append("Restored previous conversation history.") + if self.io.multiline_mode: + lines.append("Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text") + return lines def __init__( diff --git a/aider/commands.py b/aider/commands.py index 8aa8220e7..876b0a18b 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -1363,6 +1363,10 @@ class Commands: except Exception as e: self.io.tool_error(f"Error saving commands to file: {e}") + def cmd_multiline_mode(self, args): + "Toggle multiline mode (swaps behavior of Enter and Meta+Enter)" + self.io.toggle_multiline_mode() + def cmd_copy(self, args): "Copy the last assistant message to the clipboard" all_messages = self.coder.done_messages + self.coder.cur_messages diff --git a/aider/io.py b/aider/io.py index 0d3f3c88d..391794931 100644 --- a/aider/io.py +++ b/aider/io.py @@ -202,11 +202,19 @@ class InputOutput: editingmode=EditingMode.EMACS, fancy_input=True, file_watcher=None, + multiline_mode=False, ): self.placeholder = None self.interrupted = False self.never_prompts = set() self.editingmode = editingmode + # Base multiline setting that can be temporarily overridden + # Command line argument takes precedence over environment variable + self.base_multiline_mode = multiline_mode if multiline_mode is not None else ( + os.environ.get('AIDER_MULTILINE', '').lower() in ('true', '1', 'yes', 'on') + ) + # Current multiline state that can be temporarily disabled for prompts + self.multiline_mode = self.base_multiline_mode no_color = os.environ.get("NO_COLOR") if no_color is not None and no_color != "": pretty = False @@ -412,6 +420,8 @@ class InputOutput: show = self.format_files_for_input(rel_fnames, rel_read_only_fnames) if edit_format: show += edit_format + if self.multiline_mode: + show += (" " if edit_format else "") + "multi" show += "> " inp = "" @@ -456,9 +466,25 @@ class InputOutput: "Navigate forward through history" event.current_buffer.history_forward() - @kb.add("escape", "c-m", eager=True) + @kb.add("enter", eager=True) def _(event): - event.current_buffer.insert_text("\n") + "Handle Enter key press" + if self.multiline_mode: + # In multiline mode, Enter adds a newline + event.current_buffer.insert_text("\n") + else: + # In normal mode, Enter submits + event.current_buffer.validate_and_handle() + + @kb.add("escape", "enter", eager=True) # This is Alt+Enter + def _(event): + "Handle Alt+Enter key press" + if self.multiline_mode: + # In multiline mode, Alt+Enter submits + event.current_buffer.validate_and_handle() + else: + # In normal mode, Alt+Enter adds a newline + event.current_buffer.insert_text("\n") while True: if multiline_input: @@ -629,6 +655,9 @@ class InputOutput: group=None, allow_never=False, ): + # Temporarily disable multiline mode for yes/no prompts + orig_multiline = self.multiline_mode + self.multiline_mode = False self.num_user_asks += 1 question_id = (question, subject) @@ -726,9 +755,15 @@ class InputOutput: hist = f"{question.strip()} {res}" self.append_chat_history(hist, linebreak=True, blockquote=True) + # Restore original multiline mode + self.multiline_mode = orig_multiline + return is_yes def prompt_ask(self, question, default="", subject=None): + # Temporarily disable multiline mode for prompts + orig_multiline = self.multiline_mode + self.multiline_mode = False self.num_user_asks += 1 if subject: @@ -752,6 +787,9 @@ class InputOutput: if self.yes in (True, False): self.tool_output(hist) + # Restore original multiline mode + self.multiline_mode = orig_multiline + return res def _tool_message(self, message="", strip=True, color=None): @@ -821,6 +859,14 @@ class InputOutput: def print(self, message=""): print(message) + def toggle_multiline_mode(self): + """Toggle between normal and multiline input modes""" + self.multiline_mode = not self.multiline_mode + if self.multiline_mode: + self.tool_output("Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text") + else: + self.tool_output("Multiline mode: Disabled. Alt-Enter inserts newline, Enter submits text") + def append_chat_history(self, text, linebreak=False, blockquote=False, strip=True): if blockquote: if strip: diff --git a/aider/main.py b/aider/main.py index 73a3cc9d1..51377d0fe 100644 --- a/aider/main.py +++ b/aider/main.py @@ -515,6 +515,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F llm_history_file=args.llm_history_file, editingmode=editing_mode, fancy_input=args.fancy_input, + multiline_mode=args.multiline, ) io = get_io(args.pretty) diff --git a/aider/website/_includes/multi-line.md b/aider/website/_includes/multi-line.md index 5a93562ca..c6549df96 100644 --- a/aider/website/_includes/multi-line.md +++ b/aider/website/_includes/multi-line.md @@ -5,6 +5,10 @@ You can send long, multi-line messages in the chat in a few ways: - Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments). - Use `/paste` to paste text from the clipboard into the chat. - Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info. + - Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. You can enable multiline mode in three ways: + - Use the `/multiline-mode` command to toggle it during a session + - Start aider with the `--multiline` flag + - Start aider with the environment variable AIDER\_MULTILINE=true Example with a tag: ```