Source code for wxyz.lab.widget_term

""" Terminal viewing widgets
"""
# pylint: disable=unused-argument,no-name-in-module,import-error
import re

from ipywidgets import trait_types

from .base import LabBase, T, W

DEFAULT_THEME = {
    "foreground": "#fff",
    "background": "#000",
    "cursor": "#fff",
    "cursorAccent": "#000",
    "selection": "rgba(255, 255, 255, 0.3)",
}

# this is copied from xterm.d.ts
DTS = (
    """
    /**
     * Retrieves an option's value from the terminal.
     * @param key The option key.
     */
    getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily'"""
    """ | 'fontWeight' | 'fontWeightBold'| 'rendererType' | 'termName'): string;
    /**
     * Retrieves an option's value from the terminal.
     * @param key The option key.
     */
    getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol'"""
    """ | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | """
    """ | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys'"""
    """ | 'useFlowControl' | 'visualBell'): boolean; """
    """
/**
     * Retrieves an option's value from the terminal.
     * @param key The option key.
     */
    getOption(key: 'colors'): string[];
    /**
     * Retrieves an option's value from the terminal.
     * @param key The option key.
     */
    getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight'"""
    """ | 'rows' | 'tabStopWidth' | 'scrollback'): number;
"""
)

TRAIT_MAP = {
    "number": T.Float,
    "boolean": T.Bool,
    "string[]": lambda **kwargs: trait_types.TypedTuple(T.Unicode(), **kwargs),
    "string": T.Unicode,
}


def _traits_from_dts():
    traits = {}
    for attrs, dts_type in re.findall(r"getOption\(key: (.*)\): (.*);", DTS):
        for attr in re.findall(r"'(.*?)'", attrs):
            if attr in ["rows", "cols"]:
                continue
            traits[re.sub(r"(?<!^)(?=[A-Z])", "_", attr).lower()] = TRAIT_MAP[dts_type](
                default_value=None, allow_none=True
            ).tag(sync=True)
    return traits


[docs]@W.register class Terminal(LabBase): """A basic terminal""" _model_name = T.Unicode("TerminalModel").tag(sync=True) _view_name = T.Unicode("TerminalView").tag(sync=True) locals().update(_traits_from_dts()) rows = T.Int(24).tag(sync=True) cols = T.Int(80).tag(sync=True) selection = T.Unicode("").tag(sync=True) scroll = T.Int(0).tag(sync=True) fit = T.Bool(True).tag(sync=True) local_echo = T.Bool(False).tag(sync=True) theme = T.Dict(default_value=DEFAULT_THEME).tag(sync=True) active_terminals = T.Int(0).tag(sync=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._data_handlers = W.CallbackDispatcher() self.on_msg(self._handle_terminal_msg)
[docs] def on_data(self, callback, remove=False): """register a callback which will receive a message""" self._data_handlers.register_callback(callback, remove=remove)
[docs] def data(self, content): """programmatically call all data listeners""" self._data_handlers(self, content)
[docs] def send_line(self, line): """convenience wrapper around send""" self.send({"content": f"{line}\r\n"})
def _handle_terminal_msg(self, _, content, buffers): """handler for messages""" self.data(content)