2025-12-20 21:04:21 +02:00
|
|
|
# deck.chat: T-Deck generic chat UI helper library for CircuitPython
|
|
|
|
|
# Depends on tdeck_repl for providing working input on T-Decks
|
|
|
|
|
#
|
|
|
|
|
# Created by Luxferre in 2025, released into public domain
|
|
|
|
|
|
|
|
|
|
# init the tdeck_repl input where applicable
|
|
|
|
|
try:
|
|
|
|
|
from tdeck_repl import input
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
class DeckChat:
|
2025-12-20 21:19:15 +02:00
|
|
|
def __init__(self, start_state={}, chat_prefix='> ', command_prefix='/', paginate=0):
|
2025-12-20 21:04:21 +02:00
|
|
|
"""Init the chat class"""
|
|
|
|
|
self.command_prefix = command_prefix # prefix that commands start with
|
|
|
|
|
self.chat_prefix = chat_prefix # prefix to write before input
|
|
|
|
|
self.command_handlers = { # command handler storage
|
2025-12-20 21:22:06 +02:00
|
|
|
'default': lambda m,s: (m,s) # echo handler by default
|
2025-12-20 21:04:21 +02:00
|
|
|
}
|
|
|
|
|
self.state = start_state # internal state object (impl-specific)
|
2025-12-20 21:19:15 +02:00
|
|
|
self.paginate_n = paginate # paginate the responses exceeding N>0 lines
|
2025-12-20 21:04:21 +02:00
|
|
|
|
|
|
|
|
def command(self, command, handler):
|
|
|
|
|
"""
|
|
|
|
|
Register a new handler inside the chat instance.
|
2025-12-20 21:24:56 +02:00
|
|
|
The handler accepts two parameters: a message and a state object,
|
|
|
|
|
and returns the response and the new state object.
|
|
|
|
|
Non-command handler is registered under the 'default' command.
|
2025-12-20 21:04:21 +02:00
|
|
|
"""
|
|
|
|
|
cmd = command.strip().lower()
|
|
|
|
|
if cmd.startswith(self.command_prefix):
|
|
|
|
|
cmd = cmd[1:]
|
|
|
|
|
self.command_handlers[cmd] = handler
|
|
|
|
|
|
|
|
|
|
def _detect_command(self, msg):
|
|
|
|
|
"""
|
|
|
|
|
Split a chat line into the command (or None if none detected)
|
|
|
|
|
and the rest of the message.
|
|
|
|
|
"""
|
|
|
|
|
res = ('default', msg)
|
|
|
|
|
if msg.startswith(self.command_prefix):
|
|
|
|
|
parts = msg.split(maxsplit=1)
|
|
|
|
|
cmd, arg = parts[0].lower().strip()[1:], parts[1].strip() if len(parts) > 1 else None
|
|
|
|
|
if cmd in self.command_handlers:
|
|
|
|
|
res = (cmd, arg)
|
|
|
|
|
return res
|
|
|
|
|
|
2025-12-20 21:19:15 +02:00
|
|
|
def _paginate_output(self, text):
|
|
|
|
|
"""Splits output for small terminals."""
|
|
|
|
|
lines = text.split('\n')
|
|
|
|
|
for i in range(0, len(lines), self.paginate_n):
|
|
|
|
|
chunk = lines[i:i + self.paginate_n]
|
|
|
|
|
for line in chunk: print(line)
|
|
|
|
|
if i + self.paginate_n < len(lines):
|
|
|
|
|
input("-- Press Enter --")
|
|
|
|
|
|
2025-12-20 21:04:21 +02:00
|
|
|
def start(self):
|
|
|
|
|
"""Start the chat loop"""
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
2025-12-20 21:20:07 +02:00
|
|
|
input_msg = input(self.chat_prefix).strip()
|
2025-12-20 21:04:21 +02:00
|
|
|
cmd, msg = self._detect_command(input_msg)
|
2025-12-20 21:19:15 +02:00
|
|
|
output, self.state = self.command_handlers[cmd](msg, self.state)
|
|
|
|
|
if self.paginate_n > 0:
|
|
|
|
|
self._paginate_output(output.strip())
|
|
|
|
|
else:
|
|
|
|
|
print(output)
|
2025-12-20 21:04:21 +02:00
|
|
|
if self.state is None:
|
|
|
|
|
break
|
|
|
|
|
except KeyboardInterrupt: break
|