Skip to content

Commit b135166

Browse files
committed
feat: add softwrap to text area
1 parent 13c2f45 commit b135166

File tree

4 files changed

+31
-27
lines changed

4 files changed

+31
-27
lines changed

src/agent_chat_cli/components/user_input.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from textual.widget import Widget
22
from textual.app import ComposeResult
3-
from textual.widgets import Input
3+
from textual.widgets import TextArea
4+
from textual.binding import Binding
45

56
from agent_chat_cli.components.caret import Caret
67
from agent_chat_cli.components.flex import Flex
@@ -11,23 +12,30 @@
1112
class UserInput(Widget):
1213
first_boot = True
1314

15+
BINDINGS = [
16+
Binding("enter", "submit", "Submit", priority=True),
17+
]
18+
1419
def __init__(self, actions: Actions) -> None:
1520
super().__init__()
1621
self.actions = actions
1722

1823
def compose(self) -> ComposeResult:
1924
with Flex():
2025
yield Caret()
21-
yield Input(
22-
placeholder="" if self.first_boot else "",
26+
yield TextArea(
27+
"",
28+
show_line_numbers=False,
29+
soft_wrap=True,
2330
)
2431

2532
def on_mount(self) -> None:
26-
input_widget = self.query_one(Input)
33+
input_widget = self.query_one(TextArea)
2734
input_widget.focus()
2835

29-
async def on_input_submitted(self, event: Input.Submitted) -> None:
30-
user_message = event.value.strip()
36+
async def action_submit(self) -> None:
37+
input_widget = self.query_one(TextArea)
38+
user_message = input_widget.text.strip()
3139

3240
if not user_message:
3341
return
@@ -36,17 +44,11 @@ async def on_input_submitted(self, event: Input.Submitted) -> None:
3644
self.actions.quit()
3745
return
3846

39-
input_widget = self.query_one(Input)
40-
input_widget.value = ""
47+
input_widget.clear()
4148

4249
if user_message.lower() == ControlCommand.CLEAR.value:
4350
await self.actions.interrupt()
4451
await self.actions.new()
4552
return
4653

4754
await self.actions.submit_user_message(user_message)
48-
49-
async def on_input_blurred(self, event: Input.Blurred) -> None:
50-
if self.display:
51-
input_widget = self.query_one(Input)
52-
input_widget.focus()

src/agent_chat_cli/core/actions.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from typing import TYPE_CHECKING
22

3-
from textual.widgets import Input
4-
53
from agent_chat_cli.utils.enums import ControlCommand
64
from agent_chat_cli.components.chat_history import ChatHistory, MessagePosted
75
from agent_chat_cli.components.messages import Message
@@ -24,15 +22,14 @@ async def query(self, user_input: str) -> None:
2422
await self.app.agent_loop.query_queue.put(user_input)
2523

2624
async def submit_user_message(self, message: str) -> None:
27-
from agent_chat_cli.components.user_input import UserInput
25+
from textual.widgets import TextArea
2826

2927
self.app.post_message(MessagePosted(Message.user(message)))
3028

3129
thinking_indicator = self.app.query_one(ThinkingIndicator)
3230
thinking_indicator.is_thinking = True
3331

34-
user_input = self.app.query_one(UserInput)
35-
input_widget = user_input.query_one(Input)
32+
input_widget = self.app.query_one(TextArea)
3633
input_widget.cursor_blink = False
3734

3835
await self.query(message)
@@ -65,6 +62,7 @@ async def new(self) -> None:
6562

6663
async def respond_to_tool_permission(self, response: str) -> None:
6764
from agent_chat_cli.components.user_input import UserInput
65+
from textual.widgets import TextArea
6866

6967
log_json(
7068
{
@@ -81,7 +79,7 @@ async def respond_to_tool_permission(self, response: str) -> None:
8179
user_input = self.app.query_one(UserInput)
8280
user_input.display = True
8381

84-
input_widget = user_input.query_one(Input)
82+
input_widget = self.app.query_one(TextArea)
8583
input_widget.focus()
8684

8785
thinking_indicator = self.app.query_one(ThinkingIndicator)

src/agent_chat_cli/core/message_bus.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import asyncio
22
from typing import TYPE_CHECKING
33

4-
from textual.widgets import Input, Markdown
4+
from textual.widgets import Markdown
55
from textual.containers import VerticalScroll
66

77
from agent_chat_cli.components.chat_history import ChatHistory, MessagePosted
88
from agent_chat_cli.components.thinking_indicator import ThinkingIndicator
99
from agent_chat_cli.components.tool_permission_prompt import ToolPermissionPrompt
10-
from agent_chat_cli.components.user_input import UserInput
1110
from agent_chat_cli.components.messages import (
1211
AgentMessage as AgentMessageWidget,
1312
Message,
@@ -122,6 +121,8 @@ async def _handle_user(self, message: AgentMessage) -> None:
122121
await self._scroll_to_bottom()
123122

124123
async def _handle_tool_permission_request(self, message: AgentMessage) -> None:
124+
from agent_chat_cli.components.user_input import UserInput
125+
125126
log_json(
126127
{
127128
"event": "showing_permission_prompt",
@@ -143,6 +144,8 @@ async def _handle_tool_permission_request(self, message: AgentMessage) -> None:
143144
await self._scroll_to_bottom()
144145

145146
async def _handle_result(self) -> None:
147+
from textual.widgets import TextArea
148+
146149
# Check if there's a queued message (e.g., from custom permission response)
147150
if not self.app.agent_loop.query_queue.empty():
148151
# Don't turn off thinking - there's more work to do
@@ -151,8 +154,7 @@ async def _handle_result(self) -> None:
151154
thinking_indicator = self.app.query_one(ThinkingIndicator)
152155
thinking_indicator.is_thinking = False
153156

154-
user_input = self.app.query_one(UserInput)
155-
input_widget = user_input.query_one(Input)
157+
input_widget = self.app.query_one(TextArea)
156158
input_widget.cursor_blink = True
157159

158160
self.current_agent_message = None

src/agent_chat_cli/core/styles.tcss

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,16 @@ Caret {
7979
opacity: 0.5;
8080
}
8181

82-
Input {
83-
height: 1;
82+
TextArea {
83+
height: auto;
84+
min-height: 1;
85+
max-height: 10;
8486
width: 1fr;
8587
border: none;
8688
background: transparent;
8789
color: white;
88-
padding-left: 0;
89-
margin-left: 0;
90+
padding: 0;
91+
margin: 0;
9092
}
9193

9294
.tool-message {

0 commit comments

Comments
 (0)