2024-01-03 17:32:15 +08:00
|
|
|
from typing import List, Optional, Dict, Union
|
2023-12-31 22:40:34 +08:00
|
|
|
from .iobase import pipe_interaction
|
|
|
|
from .widgets import Widget, Button
|
|
|
|
|
|
|
|
|
|
|
|
class Form:
|
|
|
|
"""
|
|
|
|
A container for different widgets
|
|
|
|
|
|
|
|
Syntax:
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
2024-01-03 17:32:15 +08:00
|
|
|
components: List[Union[Widget, str]],
|
2023-12-31 22:40:34 +08:00
|
|
|
title: Optional[str] = None,
|
2024-01-05 11:48:27 +08:00
|
|
|
submit_button_name: Optional[str] = None,
|
|
|
|
cancel_button_name: Optional[str] = None
|
2023-12-31 22:40:34 +08:00
|
|
|
):
|
|
|
|
"""
|
|
|
|
components: components in the form, can be widgets (except Button) or strings
|
|
|
|
title: title of the form
|
|
|
|
"""
|
|
|
|
assert (
|
|
|
|
any(isinstance(c, Button) for c in components) is False
|
|
|
|
), "Button is not allowed in Form"
|
|
|
|
|
|
|
|
self._components = components
|
|
|
|
self._title = title
|
|
|
|
|
|
|
|
self._rendered = False
|
2024-01-05 10:35:12 +08:00
|
|
|
self._submit = submit_button_name
|
|
|
|
self._cancel = cancel_button_name
|
2023-12-31 22:40:34 +08:00
|
|
|
|
|
|
|
@property
|
2024-01-03 17:32:15 +08:00
|
|
|
def components(self) -> List[Union[Widget, str]]:
|
2023-12-31 22:40:34 +08:00
|
|
|
"""
|
|
|
|
Return the components
|
|
|
|
"""
|
|
|
|
return self._components
|
|
|
|
|
|
|
|
def _in_chatmark(self) -> str:
|
|
|
|
"""
|
|
|
|
Generate ChatMark syntax for all components
|
|
|
|
"""
|
|
|
|
lines = []
|
|
|
|
|
|
|
|
if self._title:
|
|
|
|
lines.append(self._title)
|
|
|
|
|
|
|
|
for c in self.components:
|
|
|
|
if isinstance(c, str):
|
|
|
|
lines.append(c)
|
|
|
|
elif isinstance(c, Widget):
|
|
|
|
lines.append(c._in_chatmark())
|
|
|
|
else:
|
|
|
|
raise ValueError(f"Invalid component {c}")
|
|
|
|
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
|
|
def _parse_response(self, response: Dict):
|
|
|
|
"""
|
|
|
|
Parse response from user input
|
|
|
|
"""
|
|
|
|
for c in self.components:
|
|
|
|
if isinstance(c, Widget):
|
|
|
|
c._parse_response(response)
|
|
|
|
|
|
|
|
def render(self):
|
|
|
|
"""
|
|
|
|
Render to receive user input
|
|
|
|
"""
|
|
|
|
if self._rendered:
|
|
|
|
# already rendered once
|
|
|
|
# not sure if the constraint is necessary
|
|
|
|
# could be removed if re-rendering is needed
|
|
|
|
raise RuntimeError("Widget can only be rendered once")
|
|
|
|
|
|
|
|
self._rendered = True
|
|
|
|
|
2024-01-05 11:48:27 +08:00
|
|
|
chatmark_header = "```chatmark"
|
|
|
|
chatmark_header += f" submit={self._submit}" if self._submit else ""
|
|
|
|
chatmark_header += f" cancel={self._cancel}" if self._cancel else ""
|
|
|
|
|
2023-12-31 22:40:34 +08:00
|
|
|
lines = [
|
2024-01-05 11:48:27 +08:00
|
|
|
chatmark_header,
|
2023-12-31 22:40:34 +08:00
|
|
|
self._in_chatmark(),
|
|
|
|
"```",
|
|
|
|
]
|
|
|
|
|
|
|
|
chatmark = "\n".join(lines)
|
|
|
|
response = pipe_interaction(chatmark)
|
|
|
|
self._parse_response(response)
|