Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
hyperlink.py143 linesDownload Raw Back to wcwidth
1"""2OSC 8 hyperlink parsing and measurement.3 4.. versionadded:: 0.7.05"""6 7from __future__ import annotations8 9# std imports10import re11 12import typing13 14# local15from ._width import width as _width16from .escape_sequences import _SEQUENCE_CLASSIFY17 18HYPERLINK_OPEN_RE = re.compile(r'\x1b]8;([^;]*);([^\x07\x1b]*)(\x07|\x1b\\)')19HYPERLINK_CLOSE_RE = re.compile(r'\x1b]8;;(\x07|\x1b\\)')20 21 22class HyperlinkParams(typing.NamedTuple):23    r"""24    Parsed parameters from an OSC 8 hyperlink open sequence.25 26    :param url: The hyperlink URL.27    :param params: Colon-separated metadata string (often empty).28    :param terminator: Sequence terminator (``\x07`` or ``\x1b\\``).29    """30 31    url: str32    params: str = ''33    terminator: str = '\x07'34 35    @classmethod36    def parse(cls, seq: str) -> HyperlinkParams | None:37        r"""38        Parse an OSC 8 open sequence string.39 40        Returns ``None`` if *seq* is not a valid OSC 8 open.41 42        Example::43 44            >>> HyperlinkParams.parse('\x1b]8;;http://example.com\x07')45            HyperlinkParams(url='http://example.com', params='', terminator='\\x07')46        """47        m = HYPERLINK_OPEN_RE.match(seq)48        if m is None:49            return None50        return cls(url=m.group(2), params=m.group(1), terminator=m.group(3))51 52    def make_open(self) -> str:53        """Generate the OSC 8 open escape sequence."""54        return f'\x1b]8;{self.params};{self.url}{self.terminator}'55 56    def make_close(self) -> str:57        """Generate the OSC 8 close escape sequence."""58        return f'\x1b]8;;{self.terminator}'59 60 61class Hyperlink(typing.NamedTuple):62    """63    A complete OSC 8 hyperlink with target and inner text.64 65    :param params: Parsed open sequence parameters.66    :param text: Inner text between the open and close sequences.67    """68 69    params: HyperlinkParams70    text: str71 72    @classmethod73    def find_close(cls, text: str, open_end: int) -> tuple[int, int]:74        """75        Find the matching OSC 8 close sequence.76 77        Searches 'text' starting at 'open_end', the position just past the open78        sequence.  Returns position of close sequence ``(close_start,79        close_end)`` or ``(-1, -1)`` if not found.80 81        Per the OSC 8 specification, terminal emulators treat hyperlinks as a82        state attribute, not as nested HTML anchors.  A close sequence closes83        the current hyperlink regardless of how many open sequences preceded it.84        """85        m = HYPERLINK_CLOSE_RE.search(text, open_end)86        if m is None:87            return (-1, -1)88        return (m.start(), m.end())89 90    def display_width(91        self,92        *,93        control_codes: typing.Literal['parse', 'strict', 'ignore'] = 'parse',94        tabsize: int = 8,95        ambiguous_width: int = 1,96    ) -> int:97        r"""98        Measure the display width of the hyperlink's inner text.99 100        Delegates to :func:`wcwidth.width` with the given parameters.101 102        Example::103 104            >>> hl = Hyperlink.parse('\x1b]8;;http://example.com\x07Hello\x1b]8;;\x07', 0)105            >>> hl.display_width()106            5107        """108        return _width(109            self.text,110            control_codes=control_codes,111            tabsize=tabsize,112            ambiguous_width=ambiguous_width,113        )114 115    @classmethod116    def parse(cls, text: str, start: int = 0) -> Hyperlink | None:117        r"""118        Parse a complete OSC 8 hyperlink unit from *text* at position *start*.119 120        Locates the open sequence, finds the matching close, and returns a121        ``Hyperlink`` containing the parsed parameters and inner text.  Returns122        ``None`` if the text at *start* is not a complete OSC 8 hyperlink.123 124        Example::125 126            >>> Hyperlink.parse('\x1b]8;;http://example.com\x07Hello\x1b]8;;\x07')127            Hyperlink(params=HyperlinkParams(url='http://example.com', ...), text='Hello')128        """129        m = _SEQUENCE_CLASSIFY.match(text, start)130        if m is None:131            return None132        params = HyperlinkParams.parse(m.group())133        if params is None:134            return None135        close_start, close_end = cls.find_close(text, m.end())136        if (close_start, close_end) == (-1, -1):137            return None138        return cls(params=params, text=text[m.end():close_start])139 140    def make_sequence(self) -> str:141        """Rebuild the complete OSC 8 hyperlink escape sequence."""142        return self.params.make_open() + self.text + self.params.make_close()143 
codekingpro/portable-devtools · Team Ai