Skip to content

Commit

Permalink
Support multiline inputs (#31)
Browse files Browse the repository at this point in the history
- Newlines created with Alt+Enter or Option+Enter
- Supports pasting of multiline input messages
- closes #7
  • Loading branch information
krasserm authored Jan 23, 2025
1 parent 8cefa14 commit 46aa683
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 7 deletions.
11 changes: 11 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ python -m freeact.cli --help
```

or check [quickstart](quickstart.md) and [tutorials](tutorials/index.md) for usage examples.

## Multiline input

The `freeact` CLI supports entering messages that span multiple lines in two ways:

1. **Copy-paste**: You can directly copy and paste multiline content into the CLI
2. **Manual entry**: Press `Alt+Enter` (Linux/Windows) or `Option+Enter` (macOS) to add a new line while typing

To submit a multiline message, simply press `Enter`.

![Multiline input](img/multiline.png)
Binary file added docs/img/multiline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 25 additions & 4 deletions freeact/cli/utils.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import platform
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Dict

import aiofiles
import prompt_toolkit
from dotenv import dotenv_values
from ipybox import arun
from PIL import Image
from prompt_toolkit.key_binding import KeyBindings
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Prompt
from rich.rule import Rule
from rich.syntax import Syntax
from rich.text import Text
Expand Down Expand Up @@ -51,18 +52,38 @@ async def execution_environment(


async def stream_conversation(agent: CodeActAgent, console: Console, show_token_usage: bool = False, **kwargs):
"enter"
empty_input = False

kb = KeyBindings()

@kb.add("enter")
def _(event):
"""Submit the input when Enter is pressed."""
event.app.exit(result=event.app.current_buffer.text)

@kb.add("escape", "enter")
def _(event):
"""Insert a newline when Alt+Enter or Meta+Enter is pressed."""
event.current_buffer.insert_text("\n")

session = prompt_toolkit.PromptSession(
multiline=True,
key_bindings=kb,
)

escape_key = "Option" if platform.system() == "Darwin" else "Alt"

while True:
console.print(Rule("User message", style="dodger_blue1", characters="━"))

if empty_input:
empty_input = False
prefix = "Please provide a non-empty message "
prefix = "Please enter a non-empty message"
else:
prefix = ""

user_message = await arun(Prompt.ask, f"{prefix}('q' to quit)", console=console)
user_message = await session.prompt_async(f"'q': quit, {escape_key}+Enter: newline\n\n{prefix}> ")

if not user_message.strip():
empty_input = True
Expand Down
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ nav:
- Installation: installation.md
- Building blocks: blocks.md
- Supported models: models.md
- Command line interface: cli.md
- CLI: cli.md
- Tutorials:
- Overview: tutorials/index.md
- Basic usage: tutorials/basics.md
Expand Down
29 changes: 27 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ anthropic = "^0.43.0"
google-genai = "^0.3.0"
ipybox = "^0.3.1"
openai = "^1.59"
prompt_toolkit = "^3.0"
python = "^3.11,<3.14"
python-dotenv = "^1.0"
rich = "^13.9"
Expand Down

0 comments on commit 46aa683

Please sign in to comment.