Approval-Correlation: 49036599e5df8e265ad6146109634e40
Plan-SHA256: 8b8371814cb3da5d7a9f2136053f543d1f524824ce1d3f1fe307cfe56c583784
Base-SHA: d2f8326a1a
67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
"""사용자 입력을 세션 내 대화 영역에 표시하는 Textual 애플리케이션."""
|
|
|
|
from textual.app import App, ComposeResult
|
|
from textual.containers import VerticalScroll
|
|
from textual.widgets import Header, Input, Label
|
|
|
|
|
|
class ChatApp(App[None]):
|
|
"""LLM 호출 없이 사용자의 제출 입력만 표시하는 초기 TUI."""
|
|
|
|
CSS = """
|
|
Screen {
|
|
layout: vertical;
|
|
}
|
|
|
|
#conversation {
|
|
height: 1fr;
|
|
border: round $accent;
|
|
padding: 1;
|
|
}
|
|
|
|
#user-input {
|
|
margin: 1 0;
|
|
}
|
|
"""
|
|
|
|
BINDINGS = [
|
|
("ctrl+q", "quit", "종료"),
|
|
("escape", "quit", "종료"),
|
|
]
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
self.submitted_inputs: list[str] = []
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield Header(show_clock=False)
|
|
yield VerticalScroll(id="conversation")
|
|
yield Input(
|
|
placeholder="메시지를 입력하고 Enter를 누르세요.",
|
|
id="user-input",
|
|
)
|
|
|
|
def on_mount(self) -> None:
|
|
self.query_one("#user-input", Input).focus()
|
|
|
|
def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
"""제출된 입력을 기록하고 대화 영역에 누적 표시한다."""
|
|
value = event.value
|
|
if not value:
|
|
return
|
|
|
|
self.submitted_inputs.append(value)
|
|
conversation = self.query_one("#conversation", VerticalScroll)
|
|
conversation.mount(Label(value, classes="user-message"))
|
|
event.input.value = ""
|
|
conversation.scroll_end(animate=False)
|
|
|
|
|
|
def main() -> None:
|
|
"""콘솔 스크립트의 실행 진입점."""
|
|
ChatApp().run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|