Skip to content

Commit

Permalink
Merge pull request #2601 from miradnanali/multiline-mode
Browse files Browse the repository at this point in the history
Implement /multiline-mode, swaps Enter & Meta-Enter
  • Loading branch information
paul-gauthier authored Dec 11, 2024
2 parents fbde093 + aaf7e3f commit 370e08c
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 2 deletions.
6 changes: 6 additions & 0 deletions aider/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ def get_announcements(self):
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__(
Expand Down
4 changes: 4 additions & 0 deletions aider/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,10 @@ def cmd_save(self, args):
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
Expand Down
50 changes: 48 additions & 2 deletions aider/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,19 @@ def __init__(
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
Expand Down Expand Up @@ -412,6 +420,8 @@ def get_input(
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 = ""
Expand Down Expand Up @@ -456,9 +466,25 @@ def _(event):
"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:
Expand Down Expand Up @@ -629,6 +655,9 @@ def confirm_ask(
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)
Expand Down Expand Up @@ -726,9 +755,15 @@ def is_valid_response(text):
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:
Expand All @@ -752,6 +787,9 @@ def prompt_ask(self, question, default="", subject=None):
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):
Expand Down Expand Up @@ -821,6 +859,14 @@ def set_placeholder(self, placeholder):
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:
Expand Down
1 change: 1 addition & 0 deletions aider/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ def get_io(pretty):
llm_history_file=args.llm_history_file,
editingmode=editing_mode,
fancy_input=args.fancy_input,
multiline_mode=args.multiline,
)

io = get_io(args.pretty)
Expand Down
4 changes: 4 additions & 0 deletions aider/website/_includes/multi-line.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
```
Expand Down

0 comments on commit 370e08c

Please sign in to comment.