Implement multiline-mode, swaps Enter & Meta-Enter

This commit is contained in:
Mir Adnan ALI 2024-12-11 04:58:42 -05:00
parent fbde0936e7
commit aaf7e3f943
6 changed files with 66 additions and 2 deletions

View file

@ -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,

View file

@ -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__(

View file

@ -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

View file

@ -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:

View file

@ -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)

View file

@ -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:
```