Пример #1
0
    def get_completions(self, document, complete_event):
        if not document.current_line.strip():
            return

        used, matches = self.ipy_completer.complete(
                            line_buffer=document.current_line,
                            cursor_pos=document.cursor_position_col
        )
        start_pos = -len(used)
        for m in matches:
            m = unicodedata.normalize('NFC', m)

            # When the first character of the completion has a zero length,
            # then it's probably a decomposed unicode character. E.g. caused by
            # the "\dot" completion. Try to compose again with the previous
            # character.
            if wcwidth(m[0]) == 0:
                if document.cursor_position + start_pos > 0:
                    char_before = document.text[document.cursor_position + start_pos - 1]
                    m = unicodedata.normalize('NFC', char_before + m)

                    # Yield the modified completion instead, if this worked.
                    if wcwidth(m[0:1]) == 1:
                        yield Completion(m, start_position=start_pos - 1)
                        continue

            yield Completion(m, start_position=start_pos)
Пример #2
0
    def get_completions(self, document, complete_event):
        if not document.current_line.strip():
            return

        used, matches = self.ipy_completer.complete(
            line_buffer=document.current_line, cursor_pos=document.cursor_position_col
        )
        start_pos = -len(used)
        for m in matches:
            if not m:
                # Guard against completion machinery giving us an empty string.
                continue

            m = unicodedata.normalize("NFC", m)

            # When the first character of the completion has a zero length,
            # then it's probably a decomposed unicode character. E.g. caused by
            # the "\dot" completion. Try to compose again with the previous
            # character.
            if wcwidth(m[0]) == 0:
                if document.cursor_position + start_pos > 0:
                    char_before = document.text[document.cursor_position + start_pos - 1]
                    m = unicodedata.normalize("NFC", char_before + m)

                    # Yield the modified completion instead, if this worked.
                    if wcwidth(m[0:1]) == 1:
                        yield Completion(m, start_position=start_pos - 1)
                        continue

            # TODO: Use Jedi to determine meta_text
            # (Jedi currently has a bug that results in incorrect information.)
            # meta_text = ''
            # yield Completion(m, start_position=start_pos,
            #                  display_meta=meta_text)
            yield Completion(m, start_position=start_pos)
Пример #3
0
    def _get_completions(body, offset, cursor_position, ipyc):
        """
        Private equivalent of get_completions() use only for unit_testing.
        """
        debug = getattr(ipyc, 'debug', False)
        completions = _deduplicate_completions(
            body, ipyc.completions(body, offset))
        for c in completions:
            if not c.text:
                # Guard against completion machinery giving us an empty string.
                continue
            text = unicodedata.normalize('NFC', c.text)
            # When the first character of the completion has a zero length,
            # then it's probably a decomposed unicode character. E.g. caused by
            # the "\dot" completion. Try to compose again with the previous
            # character.
            if wcwidth(text[0]) == 0:
                if cursor_position + c.start > 0:
                    char_before = body[c.start - 1]
                    fixed_text = unicodedata.normalize(
                        'NFC', char_before + text)

                    # Yield the modified completion instead, if this worked.
                    if wcwidth(text[0:1]) == 1:
                        yield Completion(fixed_text, start_position=c.start - offset - 1)
                        continue

            # TODO: Use Jedi to determine meta_text
            # (Jedi currently has a bug that results in incorrect information.)
            # meta_text = ''
            # yield Completion(m, start_position=start_pos,
            #                  display_meta=meta_text)
            yield Completion(c.text, start_position=c.start - offset, display_meta=c.type)
Пример #4
0
    def draw(self):

        columns, lines = shutil.get_terminal_size((80, 20))

        text = '\r'
        text += format_time(self.cur_pos) + '/' + format_time(
            self.duration) + ' | '
        text += self.player_status.value
        text += ' current: '
        text_columns = sum(wcwidth(c) for c in text)
        remain_columns = columns - text_columns - 5
        if remain_columns > 0:

            msg = self._video_file_name

            if self._exception is not None:
                msg = str(self._exception)

            name_columns = sum(wcwidth(c) for c in msg)
            if name_columns <= remain_columns:
                text += msg
                text += ' ' * (remain_columns - name_columns)
            else:
                # 剩余空间太小就不显示
                if remain_columns > 5:
                    # 截取头部和尾部显示
                    part_len = int((remain_columns - 2) / 2)
                    text += msg[:part_len - 1] + '..' + msg[-part_len + 1:]
                else:
                    text += ' ' * (remain_columns - name_columns)

        stdout.write(text)
Пример #5
0
    def get_completions(self, document, complete_event):
        if not document.current_line.strip():
            return

        used, matches = self.ipy_completer.complete(
            line_buffer=document.current_line,
            cursor_pos=document.cursor_position_col)
        start_pos = -len(used)
        for m in matches:
            m = unicodedata.normalize('NFC', m)

            # When the first character of the completion has a zero length,
            # then it's probably a decomposed unicode character. E.g. caused by
            # the "\dot" completion. Try to compose again with the previous
            # character.
            if wcwidth(m[0]) == 0:
                if document.cursor_position + start_pos > 0:
                    char_before = document.text[document.cursor_position +
                                                start_pos - 1]
                    m = unicodedata.normalize('NFC', char_before + m)

                    # Yield the modified completion instead, if this worked.
                    if wcwidth(m[0:1]) == 1:
                        yield Completion(m, start_position=start_pos - 1)
                        continue

            # TODO: Use Jedi to determine meta_text
            # (Jedi currently has a bug that results in incorrect information.)
            # meta_text = ''
            # yield Completion(m, start_position=start_pos,
            #                  display_meta=meta_text)
            yield Completion(m, start_position=start_pos)
Пример #6
0
    def __missing__(self, string):
        # Note: We use the `max(0, ...` because some non printable control
        #       characters, like e.g. Ctrl-underscore get a -1 wcwidth value.
        #       It can be possible that these characters end up in the input
        #       text.
        if len(string) == 1:
            result = max(0, wcwidth(string))
        else:
            result = sum(max(0, wcwidth(c)) for c in string)

        self[string] = result
        return result
Пример #7
0
    def __missing__(self, string):
        # Note: We use the `max(0, ...` because some non printable control
        #       characters, like e.g. Ctrl-underscore get a -1 wcwidth value.
        #       It can be possible that these characters end up in the input
        #       text.
        if len(string) == 1:
            result = max(0, wcwidth(string))
        else:
            result = sum(max(0, wcwidth(c)) for c in string)

        self[string] = result
        return result
Пример #8
0
def chop(line, width=None):
    if width is None:
        width = term.width
    nline = list(blessed.sequences.iter_parse(term, line))
    length = sum(max(wcwidth(text), 0) for text, cap in nline if cap is None)
    endcaps = []
    while length > width and nline:
        text, cap = nline.pop()
        if cap is None:
            length -= max(wcwidth(text), 0)
        else:
            endcaps.insert(0, text)
    return ''.join(text for text, _ in nline) + ''.join(endcaps)
Пример #9
0
    def _get_completions(body, offset, cursor_position, ipyc):
        """
        Private equivalent of get_completions() use only for unit_testing.
        """
        debug = getattr(ipyc, "debug", False)
        completions = _deduplicate_completions(body,
                                               ipyc.completions(body, offset))
        for c in completions:
            if not c.text:
                # Guard against completion machinery giving us an empty string.
                continue
            text = unicodedata.normalize("NFC", c.text)
            # When the first character of the completion has a zero length,
            # then it's probably a decomposed unicode character. E.g. caused by
            # the "\dot" completion. Try to compose again with the previous
            # character.
            if wcwidth(text[0]) == 0:
                if cursor_position + c.start > 0:
                    char_before = body[c.start - 1]
                    fixed_text = unicodedata.normalize("NFC",
                                                       char_before + text)

                    # Yield the modified completion instead, if this worked.
                    if wcwidth(text[0:1]) == 1:
                        yield Completion(fixed_text,
                                         start_position=c.start - offset - 1)
                        continue

            # TODO: Use Jedi to determine meta_text
            # (Jedi currently has a bug that results in incorrect information.)
            # meta_text = ''
            # yield Completion(m, start_position=start_pos,
            #                  display_meta=meta_text)
            display_text = c.text

            adjusted_text = _adjust_completion_text_based_on_context(
                c.text, body, offset)
            if c.type == "function":
                yield Completion(
                    adjusted_text,
                    start_position=c.start - offset,
                    display=_elide(display_text + "()"),
                    display_meta=c.type + c.signature,
                )
            else:
                yield Completion(
                    adjusted_text,
                    start_position=c.start - offset,
                    display=_elide(display_text),
                    display_meta=c.type,
                )
Пример #10
0
def make_widths_table() -> List[Tuple[int, int, int]]:
    table: List[Tuple[int, int, int]] = []
    append = table.append

    make_table_task = progress.add_task("Calculating table...")

    widths = ((codepoint, wcwidth(chr(codepoint)))
              for codepoint in range(0, sys.maxunicode + 1))

    _widths = [(codepoint, width) for codepoint, width in widths if width != 1]
    iter_widths = iter(_widths)

    endpoint, group_cell_size = next(iter_widths)
    start_codepoint = end_codepoint = endpoint
    for codepoint, cell_size in progress.track(iter_widths,
                                               task_id=make_table_task,
                                               total=len(_widths) - 1):
        if cell_size != group_cell_size or codepoint != end_codepoint + 1:
            append((start_codepoint, end_codepoint, group_cell_size))
            start_codepoint = end_codepoint = codepoint
            group_cell_size = cell_size
        else:
            end_codepoint = codepoint
    append((start_codepoint, end_codepoint, group_cell_size))
    return table
Пример #11
0
 def on_config_changed(self, update):
     if "system_name" in update:
         self._all_keys = "".join(key.strip("-") for key in system.KEYS)
         self._all_keys_filler = [" " * wcwidth(k) for k in self._all_keys]
         self._numbers = set(system.NUMBERS.values())
         # needs +2 to account for the Frame edges
         self.container.width = len(self._all_keys) + 2
Пример #12
0
def post():
    if request.json['pwd'] != pwd:
        abort(403)

    channel = re.sub(' - Topic$', '', request.json['channel'])
    output = f"{channel} - {request.json['song']}"

    if request.json['chapter']:
        output += f" - {request.json['chapter']}"

    if wcswidth(output) > MAX_LENGTH:
        trimmed = []
        count = 1

        for c in reversed(output[-MAX_LENGTH:]):
            count += wcwidth(c)

            if count > MAX_LENGTH:
                break

            trimmed.append(c)

        output = f'…{"".join(reversed(trimmed))}'

    output = f'♫ {output}'

    with open('song.txt', 'w') as f:
        f.write(output)

    with open('url.txt', 'w') as f:
        f.write(f"{channel} - {request.json['song']} {request.json['url']}")

    return ''
Пример #13
0
def _enforce_width(text, width, unicode_aware=True):
    """
    Enforce a displayed piece of text to be a certain number of cells wide.  This takes into
    account double-width characters used in CJK languages.

    :param text: The text to be truncated
    :param width: The screen cell width to enforce
    :return: The resulting truncated text
    """
    # Double-width strings cannot be more than twice the string length, so no need to try
    # expensive truncation if this upper bound isn't an issue.
    if (2 * len(text) < width) or (len(text) < width and not unicode_aware):
        return text

    # Can still optimize performance if we are not handling unicode characters.
    if unicode_aware:
        size = 0
        for i, char in enumerate(str(text)):
            c_width = wcwidth(char) if ord(char) >= 256 else 1
            if size + c_width > width:
                return text[0:i]
            size += c_width
    elif len(text) + 1 > width:
        return text[0:width]
    return text
Пример #14
0
    def update(self, frame_no):
        for i in range(self._h):
            self._frame.canvas.print_at(" " * self.width, self._x, self._y + i,
                                        self._flush_brush.fg,
                                        self._flush_brush.att,
                                        self._flush_brush.bg)

        max_x = self._w + self._x - 1
        max_y = self._h + self._y - 1
        x = self._x
        y = self._y

        for l in self._value[self._scrl_offset:]:
            if y > max_y:
                break

            for c in l:
                w = wcwidth(c.ch)

                if x + w - 1 > max_x:
                    break

                self._frame.canvas.print_at(c.ch, x, y, c.brush.fg,
                                            c.brush.att, c.brush.bg)
                x += w

            x = self._x
            y += 1
Пример #15
0
def ansilen_unicode(s):
    if isinstance(s, string_types):
        s_without_ansi = unicodedata.normalize('NFC', ANSIRE.sub('', s))
        s_without_ansi = s_without_ansi.replace("\n", "_")
        return sum(map(lambda c: max(wcwidth.wcwidth(c), 0), s_without_ansi))
    else:
        return len(s)
Пример #16
0
    def length(self):
        r"""
        Return the printable length of string containing sequences.

        Strings containing ``term.left`` or ``\b`` will cause "overstrike",
        but a length less than 0 is not ever returned. So ``_\b+`` is a
        length of 1 (displays as ``+``), but ``\b`` alone is simply a
        length of 0.

        Some characters may consume more than one cell, mainly those CJK
        Unified Ideographs (Chinese, Japanese, Korean) defined by Unicode
        as half or full-width characters.

        For example:

            >>> from blessed import Terminal
            >>> from blessed.sequences import Sequence
            >>> term = Terminal()
            >>> msg = term.clear + term.red(u'コンニチハ')
            >>> Sequence(msg, term).length()
            10

        .. note:: Although accounted for, strings containing sequences such
            as ``term.clear`` will not give accurate returns, it is not
            considered lengthy (a length of 0).
        """
        # because control characters may return -1, "clip" their length to 0.
        return sum(max(wcwidth(w_char), 0) for w_char in self.padd(strip=True))
Пример #17
0
def trunc(text, length):
    """
    Truncates text to given length, taking into account wide characters.

    If truncated, the last char is replaced by an elipsis.
    """
    if length < 1:
        raise ValueError("length should be 1 or larger")

    # Remove whitespace first so no unneccesary truncation is done.
    text = text.strip()
    text_length = wcswidth(text)

    if text_length <= length:
        return text

    # We cannot just remove n characters from the end since we don't know how
    # wide these characters are and how it will affect text length.
    # Use wcwidth to determine how many characters need to be truncated.
    chars_to_truncate = 0
    trunc_length = 0
    for char in reversed(text):
        chars_to_truncate += 1
        trunc_length += wcwidth(char)
        if text_length - trunc_length <= length:
            break

    # Additional char to make room for elipsis
    n = chars_to_truncate + 1
    return text[:-n].strip() + '…'
    def __missing__(self, string: str) -> int:
        # Note: We use the `max(0, ...` because some non printable control
        #       characters, like e.g. Ctrl-underscore get a -1 wcwidth value.
        #       It can be possible that these characters end up in the input
        #       text.
        result: int
        if len(string) == 1:
            result = max(0, wcwidth(string))
        else:
            result = sum(self[c] for c in string)

        # Store in cache.
        self[string] = result

        # Rotate long strings.
        # (It's hard to tell what we can consider short...)
        if len(string) > self.LONG_STRING_MIN_LEN:
            long_strings = self._long_strings
            long_strings.append(string)

            if len(long_strings) > self.MAX_LONG_STRINGS:
                key_to_remove = long_strings.popleft()
                if key_to_remove in self:
                    del self[key_to_remove]

        return result
Пример #19
0
def segment_buffer_line(buffer_line):
    """
    segment a buffer line based on bg and fg colors
    """
    is_wide_char = False
    text = ""
    start = 0
    counter = 0
    fg = "default"
    bg = "default"
    for i in buffer_line:
        if is_wide_char:
            is_wide_char = False
            continue
        char = buffer_line[i]
        is_wide_char = wcwidth(char.data) == 2

        if counter == 0:
            counter = i
            text = " " * i

        if fg != char.fg or bg != char.bg:
            yield text, start, counter, fg, bg
            fg = char.fg
            bg = char.bg
            text = char.data
            start = counter
        else:
            text += char.data

        counter += 1

    yield text, start, counter, fg, bg
Пример #20
0
    def length(self):
        """S.length() -> int

        Returns printable length of unicode string ``S`` that may contain
        terminal sequences.

        Although accounted for, strings containing sequences such as
        ``term.clear`` will not give accurate returns, it is not
        considered lengthy (a length of 0). Combining characters,
        are also not considered lengthy.

        Strings containing ``term.left`` or ``\b`` will cause "overstrike",
        but a length less than 0 is not ever returned. So ``_\b+`` is a
        length of 1 (``+``), but ``\b`` is simply a length of 0.

        Some characters may consume more than one cell, mainly those CJK
        Unified Ideographs (Chinese, Japanese, Korean) defined by Unicode
        as half or full-width characters.

        For example:
            >>> from blessed import Terminal
            >>> from blessed.sequences import Sequence
            >>> term = Terminal()
            >>> Sequence(term.clear + term.red(u'コンニチハ')).length()
            5
        """
        # because combining characters may return -1, "clip" their length to 0.
        clip = functools.partial(max, 0)
        return sum(
            clip(wcwidth.wcwidth(w_char)) for w_char in self.strip_seqs())
Пример #21
0
 def width(self) -> float:
     # assume monospace
     glyph: fontforge.glyph
     for glyph in self.open().glyphs():
         if glyph.unicode > 0:
             return glyph.width / wcwidth(chr(glyph.unicode))
     raise "No valid glyph found in {}".format(self.uri)
Пример #22
0
    def length(self):
        """S.length() -> int

        Returns printable length of unicode string ``S`` that may contain
        terminal sequences.

        Although accounted for, strings containing sequences such as
        ``term.clear`` will not give accurate returns, it is not
        considered lengthy (a length of 0). Combining characters,
        are also not considered lengthy.

        Strings containing ``term.left`` or ``\b`` will cause "overstrike",
        but a length less than 0 is not ever returned. So ``_\b+`` is a
        length of 1 (``+``), but ``\b`` is simply a length of 0.

        Some characters may consume more than one cell, mainly those CJK
        Unified Ideographs (Chinese, Japanese, Korean) defined by Unicode
        as half or full-width characters.

        For example:
            >>> from blessed import Terminal
            >>> from blessed.sequences import Sequence
            >>> term = Terminal()
            >>> Sequence(term.clear + term.red(u'コンニチハ')).length()
            5
        """
        # because combining characters may return -1, "clip" their length to 0.
        clip = functools.partial(max, 0)
        return sum(clip(wcwidth.wcwidth(w_char))
                   for w_char in self.strip_seqs())
Пример #23
0
 def __init__(self, width=2):
     """
     ``cjk``
       Treat ambiguous-width characters as double-width
     """
     self.characters = (unichr(idx) for idx in xrange(LIMIT_UCS)
                        if wcwidth(unichr(idx)) == width)
Пример #24
0
    def __missing__(self, string: str) -> int:
        # Note: We use the `max(0, ...` because some non printable control
        #       characters, like e.g. Ctrl-underscore get a -1 wcwidth value.
        #       It can be possible that these characters end up in the input
        #       text.
        result: int
        if len(string) == 1:
            result = max(0, wcwidth(string))
        else:
            result = sum(self[c] for c in string)

        # Store in cache.
        self[string] = result

        # Rotate long strings.
        # (It's hard to tell what we can consider short...)
        if len(string) > self.LONG_STRING_MIN_LEN:
            long_strings = self._long_strings
            long_strings.append(string)

            if len(long_strings) > self.MAX_LONG_STRINGS:
                key_to_remove = long_strings.popleft()
                if key_to_remove in self:
                    del self[key_to_remove]

        return result
Пример #25
0
    def __init__(self, string):
        self._string = []
        self._state = []
        self._width = []
        self._termwidth = 0

        state = set()

        for token in re.split(self.ANSI_REGEX, to_unicode(string)):
            if token:
                if re.match(self.ANSI_REGEX, token):
                    if token == self.ANSI_RESET:
                        state.clear()
                    else:
                        state.add(token)
                else:
                    s_copy = set(state)
                    for char in token:
                        w = wcwidth(char)
                        if w == -1:
                            raise ValueError(
                                ("Unsupported Literal {} in "
                                 "string {}").format(repr(char), repr(token)))
                        self._termwidth += w
                        self._string.append(char)
                        self._width.append(w)
                        self._state.append(s_copy)
Пример #26
0
    def truncate(self, width):
        """
        Truncate a string in a sequence-aware manner.

        Any printable characters beyond ``width`` are removed, while all
        sequences remain in place. Horizontal Sequences are first expanded
        by :meth:`padd`.

        :arg int width: The printable width to truncate the string to.
        :rtype: str
        :returns: String truncated to at most ``width`` printable characters.
        """
        output = ""
        current_width = 0
        target_width = width.__index__()
        parsed_seq = iter_parse(self._term, self.padd())

        # Retain all text until non-cap width reaches desired width
        for text, cap in parsed_seq:
            if not cap:
                # use wcwidth clipped to 0 because it can sometimes return -1
                current_width += max(wcwidth(text), 0)
                if current_width > target_width:
                    break
            output += text

        # Return with remaining caps appended
        return output + ''.join(text for text, cap in parsed_seq if cap)
Пример #27
0
def wctrim(s, max_w):
    """Return pair s, w which is a string and the cell width of that string. The
    string is trimmed so that w <= max_w. Characters which wcwidth() reports as
    having negative width are removed.

    """
    assert max_w >= 0

    # Common case: string needs no trimming
    w = wcswidth(s)
    if w >= 0 and w <= max_w:
        return s, w

    # Otherwise, walk character by character
    w, chs = 0, []
    for ch in s:
        ch_w = wcwidth(ch)
        if ch_w < 0:
            continue

        if w + ch_w > max_w:
            return ''.join(chs), w

        chs.append(ch)
        w += ch_w
    return ''.join(chs), w
Пример #28
0
    def widthof(self, text):
        if isinstance(text, Markup):
            if isinstance(text, Text):
                return self.widthof(text.string)

            elif isinstance(text, (CSI, ControlCharacter)):
                return -1

            elif isinstance(text, (Group, SGR)):
                width = 0
                for child in text.children:
                    w = self.widthof(child)
                    if w == -1:
                        return -1
                    width += w
                return width

            else:
                raise TypeError(f"unknown markup type: {type(text)}")

        else:
            width = 0
            for ch in text:
                w = wcwidth.wcwidth(ch, self.unicode_version)
                if w == -1:
                    return -1
                width += w
            return width
Пример #29
0
def draw_regions(win, regions, y=None, x=None, max_w=None, starting_at=None):
    # pylint: disable=too-many-locals,too-many-branches,too-many-arguments
    # Get cursor position and window size
    cy, cx = win.getyx()
    nl, nc = win.getmaxyx()

    # Set default values
    if y is None:
        y = cy
    if x is None:
        x = cx
    if starting_at is None:
        starting_at = 0
    if max_w is None:
        max_w = max(0, nc - x)

    # Use max_w to set nc
    nc = min(nc, x + max_w)

    # Abort if x or y outside of window
    if x < 0 or x >= nc or y < 0 or y >= nl:
        return

    # Otherwise, let's go
    for region in regions:
        text, style = region
        attr = style_attr(style)

        # Get width of region in cells and remaining space
        region_w = wcswidth(text)
        w_remaining = nc - x
        assert w_remaining >= 0

        if region_w != -1 and w_remaining >= region_w:
            # If this text fits in the remaining space, just use addstr. Note
            # that we need to silently ignore any errors from addstr as per
            # https://bugs.python.org/issue8243
            try:
                win.addstr(y, x, text, attr)
            except curses.error:
                pass
            x += region_w
        else:
            # The remaining space is too small, add character-by-character
            for c in text:
                c_w = wcwidth(c)
                if c_w == -1:
                    continue
                if w_remaining >= c_w:
                    try:
                        win.addstr(y, x, c, attr)
                    except curses.error:
                        pass
                x += c_w
                w_remaining -= c_w

        # We're done if we're past the end of the line
        if x >= nc:
            break
Пример #30
0
 def on_config_changed(self, config):
     if 'system_name' in config:
         self._strokes = []
         self._all_keys = ''.join(key.strip('-') for key in system.KEYS)
         self._all_keys_filler = [' ' * wcwidth(k) for k in self._all_keys]
         self._numbers = set(system.NUMBERS.values())
         self.header.setText(self._all_keys)
         self.on_style_changed(self._style)
Пример #31
0
Файл: ui.py Проект: grawity/code
def wctruncate(text, width=80):
    for i, c in enumerate(text):
        w = wcwidth(c)
        if w > 0:
            width -= w
        if width < 0:
            return text[:i]
    return text
Пример #32
0
 def reset(self):
     self.modelAboutToBeReset.emit()
     self._all_keys = ''.join(key.strip('-') for key in system.KEYS)
     self._all_keys_filler = [' ' * wcwidth(k) for k in self._all_keys]
     self._numbers = set(system.NUMBERS.values())
     self._stroke_list.clear()
     self.modelReset.emit()
     return self._all_keys
Пример #33
0
def _get_width(c):
    """
    Return width of character. Wrapper around ``wcwidth``.
    """
    try:
        return _CHAR_SIZES_CACHE[ord(c)]
    except IndexError:
        return wcwidth(c)
Пример #34
0
def _get_width(c):
    """
    Return width of character. Wrapper around ``wcwidth``.
    """
    try:
        return _CHAR_SIZES_CACHE[ord(c)]
    except IndexError:
        return wcwidth(c)
Пример #35
0
def wctruncate(text, width=80):
    for i, c in enumerate(text):
        w = wcwidth(c)
        if w > 0:
            width -= w
        if width < 0:
            return text[:i]
    return text
Пример #36
0
def wcfilter(ch):
    """Return x/X for non-printable characters."""
    width = wcwidth.wcwidth(ch)
    if width == -1:
        return 'x'
    elif width == 0:
        return 'X'
    else:
        return ch
Пример #37
0
def which_char(text, cursor_position):
    w = 0
    i = 0
    # loop over to check for double width chars
    for i, c in enumerate(text):
        w += wcwidth(c)
        if w >= cursor_position:
            break
    return i
Пример #38
0
 def __init__(self, width=2):
     """
     ``cjk``
       Treat ambiguous-width characters as double-width
     """
     self.characters = (unichr(idx)
                        for idx in xrange(LIMIT_UCS)
                        if wcwidth(unichr(idx)) == width
                        )
Пример #39
0
def wcfilter(ch):
    """Return x/X for non-printable characters."""
    width = wcwidth.wcwidth(ch)
    if width == -1:
        return 'x'
    elif width == 0:
        return 'X'
    else:
        return ch
Пример #40
0
def test(widths_table):
    for codepoint in progress.track(range(0, sys.maxunicode + 1),
                                    description="Testing..."):
        character = chr(codepoint)
        width1 = get_cell_size(widths_table, character)
        width2 = wcwidth(character)
        if width1 != width2:
            print(f"{width1} != {width2}")
            break
Пример #41
0
 def render(line):
     it = iter(line)
     while True:
         char = next(it).data
         assert sum(map(wcwidth, char[1:])) == 0
         char_width = wcwidth(char[0])
         if char_width == 1:
             yield char
         elif char_width == 2:
             yield char
             next(it)  # Skip stub.
Пример #42
0
    def __init__(self, width=2):
        """
        Class constructor.

        :param width: generate characters of given width.
        :type width: int
        """
        self.characters = (unichr(idx)
                           for idx in xrange(LIMIT_UCS)
                           if wcwidth(unichr(idx)) == width
                           )
Пример #43
0
 def on_config_changed(self, config):
     if 'system_name' in config:
         self._strokes = []
         self._all_keys = ''.join(key.strip('-') for key in system.KEYS)
         self._all_keys_filler = [
             ' ' * wcwidth(k)
             for k in self._all_keys
         ]
         self._numbers = set(system.NUMBERS.values())
         self.header.setText(self._all_keys)
         self.on_style_changed(self._style)
Пример #44
0
    def draw(self, data):
        """Displays decoded characters at the current cursor position and
        advances the cursor if :data:`~pyte.modes.DECAWM` is set.

        :param bytes data: bytes to display.

        .. versionchanged:: 0.5.0

           Character width is taken into account. Specifically, zero-width
           and unprintable characters do not affect screen state. Full-width
           characters are rendered into two consecutive character containers.

        .. versionchanged:: 0.6.0

           The input is now supposed to be in :func:`bytes`, which may encode
           multiple characters.
        """
        for char in self._decode(data):
            char_width = wcwidth(char)
            if char_width <= 0:
                # Unprintable character or doesn't advance the cursor.
                return

            # If this was the last column in a line and auto wrap mode is
            # enabled, move the cursor to the beginning of the next line,
            # otherwise replace characters already displayed with newly
            # entered.
            if self.cursor.x == self.columns:
                if mo.DECAWM in self.mode:
                    self.carriage_return()
                    self.linefeed()
                else:
                    self.cursor.x -= char_width

            # If Insert mode is set, new characters move old characters to
            # the right, otherwise terminal is in Replace mode and new
            # characters replace old characters at cursor position.
            if mo.IRM in self.mode:
                self.insert_characters(char_width)

            line = self.buffer[self.cursor.y]
            line[self.cursor.x] = self.cursor.attrs._replace(data=char)
            if char_width > 1:
                # Add a stub *after* a two-cell character. See issue #9
                # on GitHub.
                line[self.cursor.x + 1] = self.cursor.attrs._replace(data=" ")

            # .. note:: We can't use :meth:`cursor_forward()`, because that
            #           way, we'll never know when to linefeed.
            self.cursor.x += char_width
Пример #45
0
    def _disp_width(self, pwcs, n=None):
        """
        A wcswidth that never gives -1. Copying existing code is evil, but..

        github.com/jquast/wcwidth/blob/07cea7f/wcwidth/wcwidth.py#L182-L204
        """
        # pylint: disable=C0103
        #         Invalid argument name "n"
        # TODO: Shall we consider things like ANSI escape seqs here?
        #       We can implement some ignore-me segment like those wrapped by
        #       \1 and \2 in readline too.
        end = len(pwcs) if n is None else n
        idx = slice(0, end)
        width = 0
        for char in pwcs[idx]:
            width += max(0, wcwidth(char))
        return width
Пример #46
0
    def length(self):
        r"""
        Return the printable length of string containing sequences.

        Strings containing ``term.left`` or ``\b`` will cause "overstrike",
        but a length less than 0 is not ever returned. So ``_\b+`` is a
        length of 1 (displays as ``+``), but ``\b`` alone is simply a
        length of 0.

        Some characters may consume more than one cell, mainly those CJK
        Unified Ideographs (Chinese, Japanese, Korean) defined by Unicode
        as half or full-width characters.
        """
        # because control characters may return -1, "clip" their length to 0.
        clip = functools.partial(max, 0)
        return sum(clip(wcwidth.wcwidth(w_char))
                   for w_char in self.strip_seqs())
Пример #47
0
    def text_entry(self, ucs, name):
        """
        Display a single column segment row describing ``(ucs, name)``.

        :param ucs: target unicode point character string.
        :param name: name of unicode point.
        :rtype: unicode
        """
        style = self.screen.style
        if len(name) > style.name_len:
            idx = max(0, style.name_len - len(style.continuation))
            name = u''.join((name[:idx], style.continuation if idx else u''))
        if style.alignment == 'right':
            fmt = u' '.join(('0x{val:0>{ucs_printlen}x}',
                             '{name:<{name_len}s}',
                             '{delimiter}{ucs}{delimiter}'
                             ))
        else:
            fmt = u' '.join(('{delimiter}{ucs}{delimiter}',
                             '0x{val:0>{ucs_printlen}x}',
                             '{name:<{name_len}s}'))
        delimiter = style.attr_minor(style.delimiter)
        if len(ucs) != 1:
            # determine display of combining characters
            val = ord(next((_ucs for _ucs in ucs
                            if wcwidth(_ucs) == -1)))
            # a combining character displayed of any fg color
            # will reset the foreground character of the cell
            # combined with (iTerm2, OSX).
            disp_ucs = style.attr_major(ucs[0:2])
            if len(ucs) > 2:
                disp_ucs += ucs[2]
        else:
            # non-combining
            val = ord(ucs)
            disp_ucs = style.attr_major(ucs)

        return fmt.format(name_len=style.name_len,
                          ucs_printlen=UCS_PRINTLEN,
                          delimiter=delimiter,
                          name=name,
                          ucs=disp_ucs,
                          val=val)
Пример #48
0
def character_width(char):
    r"""
    Determine the width that a character is likely to be displayed as in
    a monospaced terminal. The width for a printable character will
    always be 0, 1, or 2.

    Nonprintable or control characters will return -1, a convention that comes
    from wcwidth.

    >>> character_width('車')
    2
    >>> character_width('A')
    1
    >>> character_width('\N{ZERO WIDTH JOINER}')
    0
    >>> character_width('\n')
    -1
    """
    return wcwidth(char)
Пример #49
0
def _is_equal_wcwidth(libc, ucs):
    w_libc = libc.wcwidth(ucs)
    w_local = wcwidth.wcwidth(ucs)
    assert w_libc == w_local, report_ucs_msg(ucs, w_libc, w_local)
Пример #50
0
import wcwidth

for x in range(0, 0x10FFFF):
    print("%04x %s" % (x, wcwidth.wcwidth(chr(x))))
Пример #51
0
    def draw(self, data):
        """Displays decoded characters at the current cursor position and
        advances the cursor if :data:`~pyte.modes.DECAWM` is set.

        :param bytes data: bytes to display.

        .. versionchanged:: 0.5.0

           Character width is taken into account. Specifically, zero-width
           and unprintable characters do not affect screen state. Full-width
           characters are rendered into two consecutive character containers.

        .. versionchanged:: 0.6.0

           The input is now supposed to be in :func:`bytes`, which may encode
           multiple characters.
        """
        for char in self._decode(data):
            char_width = wcwidth(char)

            # If this was the last column in a line and auto wrap mode is
            # enabled, move the cursor to the beginning of the next line,
            # otherwise replace characters already displayed with newly
            # entered.
            if self.cursor.x == self.columns:
                if mo.DECAWM in self.mode:
                    self.carriage_return()
                    self.linefeed()
                elif char_width > 0:
                    self.cursor.x -= char_width

            # If Insert mode is set, new characters move old characters to
            # the right, otherwise terminal is in Replace mode and new
            # characters replace old characters at cursor position.
            if mo.IRM in self.mode and char_width > 0:
                self.insert_characters(char_width)

            line = self.buffer[self.cursor.y]
            if char_width == 1:
                line[self.cursor.x] = self.cursor.attrs._replace(data=char)
            elif char_width == 2:
                # A two-cell character has a stub slot after it.
                line[self.cursor.x] = self.cursor.attrs._replace(data=char)
                if self.cursor.x + 1 < self.columns:
                    line[self.cursor.x + 1] = self.cursor.attrs._replace(data=" ")
            elif char_width == 0 and unicodedata.combining(char):
                # A zero-cell character is combined with the previous
                # character either on this or preceeding line.
                if self.cursor.x:
                    last = line[self.cursor.x - 1]
                    normalized = unicodedata.normalize("NFC", last.data + char)
                    line[self.cursor.x - 1] = last._replace(data=normalized)
                elif self.cursor.y:
                    last = self.buffer[self.cursor.y - 1][self.columns - 1]
                    normalized = unicodedata.normalize("NFC", last.data + char)
                    self.buffer[self.cursor.y - 1][self.columns - 1] = \
                        last._replace(data=normalized)
            else:
                pass  # Unprintable character or doesn't advance the cursor.

            # .. note:: We can't use :meth:`cursor_forward()`, because that
            #           way, we'll never know when to linefeed.
            if char_width > 0:
                self.cursor.x = min(self.cursor.x + char_width, self.columns)
Пример #52
0
    'Point',
    'Renderer',
    'Screen',
)

Point = namedtuple('Point', 'y x')
Size = namedtuple('Size', 'rows columns')

#: If True: write the output of the renderer also to the following file. This
#: is very useful for debugging. (e.g.: to see that we don't write more bytes
#: than required.)
_DEBUG_RENDER_OUTPUT = False
_DEBUG_RENDER_OUTPUT_FILENAME = '/tmp/prompt-toolkit-render-output'

#: Cache for wcwidth sizes.
_CHAR_SIZES_CACHE = [wcwidth(six.unichr(i)) for i in range(0, 64000)]


def _get_width(c):
    """
    Return width of character. Wrapper around ``wcwidth``.
    """
    try:
        return _CHAR_SIZES_CACHE[ord(c)]
    except IndexError:
        return wcwidth(c)


class TerminalCodes:
    """
    Escape codes for a VT100 terminal.