1""" 
    2Clipboard for command line interface. 
    3""" 
    4 
    5from __future__ import annotations 
    6 
    7from abc import ABCMeta, abstractmethod 
    8from typing import Callable 
    9 
    10from prompt_toolkit.selection import SelectionType 
    11 
    12__all__ = [ 
    13    "Clipboard", 
    14    "ClipboardData", 
    15    "DummyClipboard", 
    16    "DynamicClipboard", 
    17] 
    18 
    19 
    20class ClipboardData: 
    21    """ 
    22    Text on the clipboard. 
    23 
    24    :param text: string 
    25    :param type: :class:`~prompt_toolkit.selection.SelectionType` 
    26    """ 
    27 
    28    def __init__( 
    29        self, text: str = "", type: SelectionType = SelectionType.CHARACTERS 
    30    ) -> None: 
    31        self.text = text 
    32        self.type = type 
    33 
    34 
    35class Clipboard(metaclass=ABCMeta): 
    36    """ 
    37    Abstract baseclass for clipboards. 
    38    (An implementation can be in memory, it can share the X11 or Windows 
    39    keyboard, or can be persistent.) 
    40    """ 
    41 
    42    @abstractmethod 
    43    def set_data(self, data: ClipboardData) -> None: 
    44        """ 
    45        Set data to the clipboard. 
    46 
    47        :param data: :class:`~.ClipboardData` instance. 
    48        """ 
    49 
    50    def set_text(self, text: str) -> None:  # Not abstract. 
    51        """ 
    52        Shortcut for setting plain text on clipboard. 
    53        """ 
    54        self.set_data(ClipboardData(text)) 
    55 
    56    def rotate(self) -> None: 
    57        """ 
    58        For Emacs mode, rotate the kill ring. 
    59        """ 
    60 
    61    @abstractmethod 
    62    def get_data(self) -> ClipboardData: 
    63        """ 
    64        Return clipboard data. 
    65        """ 
    66 
    67 
    68class DummyClipboard(Clipboard): 
    69    """ 
    70    Clipboard implementation that doesn't remember anything. 
    71    """ 
    72 
    73    def set_data(self, data: ClipboardData) -> None: 
    74        pass 
    75 
    76    def set_text(self, text: str) -> None: 
    77        pass 
    78 
    79    def rotate(self) -> None: 
    80        pass 
    81 
    82    def get_data(self) -> ClipboardData: 
    83        return ClipboardData() 
    84 
    85 
    86class DynamicClipboard(Clipboard): 
    87    """ 
    88    Clipboard class that can dynamically returns any Clipboard. 
    89 
    90    :param get_clipboard: Callable that returns a :class:`.Clipboard` instance. 
    91    """ 
    92 
    93    def __init__(self, get_clipboard: Callable[[], Clipboard | None]) -> None: 
    94        self.get_clipboard = get_clipboard 
    95 
    96    def _clipboard(self) -> Clipboard: 
    97        return self.get_clipboard() or DummyClipboard() 
    98 
    99    def set_data(self, data: ClipboardData) -> None: 
    100        self._clipboard().set_data(data) 
    101 
    102    def set_text(self, text: str) -> None: 
    103        self._clipboard().set_text(text) 
    104 
    105    def rotate(self) -> None: 
    106        self._clipboard().rotate() 
    107 
    108    def get_data(self) -> ClipboardData: 
    109        return self._clipboard().get_data()