codekingpro/portable-devtools
115k
1"""Python grapheme, emoji, and sequence-aware ljust, rjust, center()."""2from typing import Literal3 4# local5from ._width import width6 7 8def ljust(9 text: str,10 dest_width: int,11 fillchar: str = ' ',12 *,13 control_codes: Literal['parse', 'strict', 'ignore'] = 'parse',14 ambiguous_width: int = 1,15) -> str:16 r"""17 Return text left-justified in a string of given display width.18 19 :param text: String to justify, may contain terminal sequences.20 :param dest_width: Total display width of result in terminal cells.21 :param fillchar: Single character for padding (default space). Must have22 display width of 1 (not wide, not zero-width, not combining). Unicode23 characters like ``'ยท'`` are acceptable. The width is not validated.24 :param control_codes: How to handle control sequences when measuring.25 Passed to :func:`width` for measurement.26 :param ambiguous_width: Width to use for East Asian Ambiguous (A)27 characters. Default is ``1`` (narrow). Set to ``2`` for CJK contexts.28 :returns: Text padded on the right to reach ``dest_width``.29 30 .. versionadded:: 0.3.031 32 Example::33 34 >>> wcwidth.ljust('hi', 5)35 'hi '36 >>> wcwidth.ljust('\x1b[31mhi\x1b[0m', 5)37 '\x1b[31mhi\x1b[0m '38 >>> wcwidth.ljust('\U0001F468\u200D\U0001F469\u200D\U0001F467', 6)39 '๐จโ๐ฉโ๐ง '40 """41 if text.isascii() and text.isprintable():42 text_width = len(text)43 else:44 text_width = width(text, control_codes=control_codes, ambiguous_width=ambiguous_width)45 padding_cells = max(0, dest_width - text_width)46 return text + fillchar * padding_cells47 48 49def rjust(50 text: str,51 dest_width: int,52 fillchar: str = ' ',53 *,54 control_codes: Literal['parse', 'strict', 'ignore'] = 'parse',55 ambiguous_width: int = 1,56) -> str:57 r"""58 Return text right-justified in a string of given display width.59 60 :param text: String to justify, may contain terminal sequences.61 :param dest_width: Total display width of result in terminal cells.62 :param fillchar: Single character for padding (default space). Must have63 display width of 1 (not wide, not zero-width, not combining). Unicode64 characters like ``'ยท'`` are acceptable. The width is not validated.65 :param control_codes: How to handle control sequences when measuring.66 Passed to :func:`width` for measurement.67 :param ambiguous_width: Width to use for East Asian Ambiguous (A)68 characters. Default is ``1`` (narrow). Set to ``2`` for CJK contexts.69 :returns: Text padded on the left to reach ``dest_width``.70 71 .. versionadded:: 0.3.072 73 Example::74 75 >>> wcwidth.rjust('hi', 5)76 ' hi'77 >>> wcwidth.rjust('\x1b[31mhi\x1b[0m', 5)78 ' \x1b[31mhi\x1b[0m'79 >>> wcwidth.rjust('\U0001F468\u200D\U0001F469\u200D\U0001F467', 6)80 ' ๐จโ๐ฉโ๐ง'81 """82 if text.isascii() and text.isprintable():83 text_width = len(text)84 else:85 text_width = width(text, control_codes=control_codes, ambiguous_width=ambiguous_width)86 padding_cells = max(0, dest_width - text_width)87 return fillchar * padding_cells + text88 89 90def center(91 text: str,92 dest_width: int,93 fillchar: str = ' ',94 *,95 control_codes: Literal['parse', 'strict', 'ignore'] = 'parse',96 ambiguous_width: int = 1,97) -> str:98 r"""99 Return text centered in a string of given display width.100 101 :param text: String to center, may contain terminal sequences.102 :param dest_width: Total display width of result in terminal cells.103 :param fillchar: Single character for padding (default space). Must have104 display width of 1 (not wide, not zero-width, not combining). Unicode105 characters like ``'ยท'`` are acceptable. The width is not validated.106 :param control_codes: How to handle control sequences when measuring.107 Passed to :func:`width` for measurement.108 :param ambiguous_width: Width to use for East Asian Ambiguous (A)109 characters. Default is ``1`` (narrow). Set to ``2`` for CJK contexts.110 :returns: Text padded on both sides to reach ``dest_width``.111 112 For odd-width padding, the extra cell fills in the same cell position as113 Python's :meth:`str.center` behavior (the left side when ``dest_width`` is114 odd, the right side when ``dest_width`` is even).115 See `the eccentric str.center <https://jazcap53.github.io/pythons-eccentric-strcenter.html>`_.116 117 .. versionadded:: 0.3.0118 119 Example::120 121 >>> wcwidth.center('hi', 6)122 ' hi '123 >>> wcwidth.center('\x1b[31mhi\x1b[0m', 6)124 ' \x1b[31mhi\x1b[0m '125 >>> wcwidth.center('\U0001F468\u200D\U0001F469\u200D\U0001F467', 6)126 ' ๐จโ๐ฉโ๐ง '127 """128 if text.isascii() and text.isprintable():129 text_width = len(text)130 else:131 text_width = width(text, control_codes=control_codes, ambiguous_width=ambiguous_width)132 total_padding = max(0, dest_width - text_width)133 # matching https://jazcap53.github.io/pythons-eccentric-strcenter.html134 left_pad = total_padding // 2 + (total_padding & dest_width & 1)135 right_pad = total_padding - left_pad136 return fillchar * left_pad + text + fillchar * right_pad137 