Skip to content

Commit e343b08

Browse files
committed
Add dot identifier for assistant messages
1 parent f8990d2 commit e343b08

1 file changed

Lines changed: 64 additions & 5 deletions

File tree

aider/tui/widgets/output.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Output widget for Aider TUI using Textual's RichLog widget."""
22

33
import re
4+
import textwrap
45

56
from rich.markdown import Markdown
67
from rich.padding import Padding
@@ -41,6 +42,8 @@ def __init__(self, **kwargs):
4142
super().__init__(**kwargs)
4243
# Line buffer for streaming text to avoid word-per-line issue
4344
self._line_buffer = ""
45+
# Track if we're on the first line of the current response
46+
self._first_line_of_response = True
4447

4548
# Enable markup for rich formatting
4649
self.highlight = True
@@ -51,6 +54,33 @@ async def start_response(self):
5154
"""Start a new LLM response section with streaming support."""
5255
# Clear the line buffer for new response
5356
self._line_buffer = ""
57+
# Reset first line flag
58+
self._first_line_of_response = True
59+
60+
def _wrap_text_with_prefix(self, text: str, prefix: str = "• ") -> str:
61+
"""Wrap text with prefix and proper indentation.
62+
63+
Args:
64+
text: The text to wrap
65+
prefix: The prefix to use for the first line
66+
67+
Returns:
68+
Wrapped text with prefix and indentation
69+
"""
70+
if not text.strip():
71+
return ""
72+
73+
# Get available width for wrapping
74+
# Subtract 2 to account for potential borders or scrollbars
75+
width = self.content_size.width - 2 if self.content_size.width else 80
76+
indent = " " * len(prefix)
77+
78+
# Wrap the text using textwrap
79+
wrapped_text = textwrap.fill(
80+
text, width=width, initial_indent=prefix, subsequent_indent=indent
81+
)
82+
83+
return wrapped_text
5484

5585
async def stream_chunk(self, text: str):
5686
"""Stream a chunk of markdown text."""
@@ -66,10 +96,21 @@ async def stream_chunk(self, text: str):
6696
# Process complete lines from buffer
6797
while "\n" in self._line_buffer:
6898
line, self._line_buffer = self._line_buffer.split("\n", 1)
69-
# self.write(Padding(line.strip(), (0, 0, 0, 1)))
7099
if line.rstrip():
71100
self.set_last_write_type("assistant")
72-
self.output(line.rstrip(), render_markdown=True)
101+
# Format with prefix on first line, proper indentation on subsequent lines
102+
if self._first_line_of_response:
103+
wrapped_line = self._wrap_text_with_prefix(line.rstrip(), prefix="• ")
104+
self._first_line_of_response = False
105+
else:
106+
# For subsequent lines, we need to wrap with proper indentation
107+
# but without the bullet prefix
108+
wrapped_line = self._wrap_text_with_prefix(line.rstrip(), prefix=" ")
109+
110+
# Output each wrapped line
111+
for wrapped in wrapped_line.split("\n"):
112+
if wrapped.strip():
113+
self.output(wrapped, render_markdown=True)
73114

74115
async def end_response(self):
75116
"""End the current LLM response."""
@@ -79,15 +120,32 @@ async def _stop_stream(self):
79120
"""Stop the current markdown stream."""
80121
# Flush any remaining buffer content
81122
if self._line_buffer.rstrip():
82-
self.output(self._line_buffer.rstrip(), render_markdown=True)
123+
# Format remaining content based on whether it's first line or not
124+
if self._first_line_of_response:
125+
wrapped_line = self._wrap_text_with_prefix(self._line_buffer.rstrip(), prefix="• ")
126+
else:
127+
wrapped_line = self._wrap_text_with_prefix(self._line_buffer.rstrip(), prefix=" ")
128+
129+
# Output each wrapped line
130+
for wrapped in wrapped_line.split("\n"):
131+
if wrapped.strip():
132+
self.output(wrapped, render_markdown=True)
83133
self._line_buffer = ""
84134

85135
def add_user_message(self, text: str):
86136
"""Add a user message (displayed differently from LLM output)."""
87137
# User messages shown with > prefix in green color
88138
self.auto_scroll = True
89139
self.set_last_write_type("user")
90-
self.output(f"[bold medium_spring_green]> {text}[/bold medium_spring_green]")
140+
141+
# Wrap the entire user message with "> " prefix
142+
wrapped_text = self._wrap_text_with_prefix(text, prefix="> ")
143+
144+
# Output each wrapped line with green styling
145+
for line in wrapped_text.split("\n"):
146+
if line.strip():
147+
self.output(f"[bold medium_spring_green]{line}[/bold medium_spring_green]")
148+
91149
self.scroll_end(animate=False)
92150

93151
def add_system_message(self, text: str, dim=True):
@@ -158,8 +216,9 @@ def add_tool_call(self, lines: list):
158216
arg_string_list = re.split(r"(^\S+:)", clean_line, maxsplit=1)[1:]
159217

160218
if len(arg_string_list) > 1:
219+
tool_property = arg_string_list[0].replace("_", " ").title()
161220
content = Text()
162-
content.append(f"ᴸ{arg_string_list[0]}", style="dim bright_cyan")
221+
content.append(f"ᴸ{tool_property}", style="dim bright_cyan")
163222
content.append(arg_string_list[1], style="dim")
164223
self.output(Padding(content, (0, 0, 0, 2)))
165224
else:

0 commit comments

Comments
 (0)