"""Main screen and widgets for abacura"""
from __future__ import annotations
# TODO: screen and widget definitions should go under the hierarchy, not in __init__
import csv
import io
from typing import TYPE_CHECKING, Coroutine, Any
from serum import inject
from textual import log, on
from textual.app import ComposeResult
from textual.containers import Container
from textual.message import Message
from textual.screen import Screen
from textual.suggester import Suggester
from textual.widgets import Header, Input, TextLog
from abacura.config import Config
from abacura.widgets import CommsLog
from abacura.widgets.sidebar import Sidebar
from abacura.widgets.footer import AbacuraFooter
if TYPE_CHECKING:
from typing_extensions import Self
from abacura.mud.session import Session
version= "0.0.9"
[docs]@inject
class SessionScreen(Screen):
"""Default Screen for sessions"""
config: Config
session: Session
BINDINGS = [
("pageup", "pageup", "PageUp"),
("pagedown", "pagedown", "PageDown"),
("f2", "toggle_sidebar", "F2"),
("f3", "toggle_commslog", "F3")
]
AUTO_FOCUS = "InputBar"
def __init__(self, name: str):
# TODO The 0.28.0 release of textual let us assign CSS_PATH at the screen level
self.CSS_PATH = self.config.get_specific_option(self.session.name, "css_path") or "css/abacura.css"
super().__init__()
self.id = f"screen-{name}"
self.tlid = f"output-{name}"
# TODO: wrap should be a config file field option
self.tl = TextLog(highlight=False, markup=False, wrap=True,
name=self.tlid, classes="mudoutput", id=self.tlid)
[docs] def compose(self) -> ComposeResult:
"""Create child widgets for the session"""
commslog = CommsLog(id="commslog", name="commslog")
commslog.display = False
yield Header(show_clock=True, name="Abacura", id="masthead", classes="masthead")
yield commslog
with Container(id="app-grid"):
yield Sidebar(id="sidebar", name="sidebar")
with Container(id="mudoutputs"):
yield self.tl
yield InputBar(id="playerinput")
yield AbacuraFooter()
if self.session.abacura.inspector:
from abacura import Inspector
inspector = Inspector()
inspector.display = False
yield inspector
[docs] def on_mount(self) -> None:
"""Screen is mounted, launch it"""
self.session.launch_screen()
[docs] def action_toggle_dark(self) -> None:
"""Dark mode"""
self.dark = not self.dark
[docs] def action_toggle_commslog(self) -> None:
commslog = self.query_one("#commslog")
commslog.display = not commslog.display
[docs] def action_pageup(self) -> None:
self.tl.auto_scroll = False
self.tl.action_page_up()
[docs] def action_pagedown(self) -> None:
self.tl.action_page_down()
if self.tl.scroll_offset.x == 0:
self.tl.auto_scroll = True
[docs]class AbacuraSuggester(Suggester):
def __init__(self, session):
super().__init__(use_cache=False)
self.session = session
self.history = []
[docs] def add_entry(self, value) -> None:
self.history.insert(0,value)
[docs] async def get_suggestion(self, value: str) -> Coroutine[Any, Any, str | None]:
if value.startswith("@"):
value = value[1:]
for command in self.session.director.command_manager.commands:
if command.name.startswith(value):
return f"@{command.name}"
else:
try:
for cmds in self.history:
if cmds.startswith(value):
return cmds
# empty list
except TypeError:
return None
return None