-module(string_width). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/string_width.gleam"). -export([mode_2027/1, mode_2027_ext/1, mode_wcwidth/1, ambiguous_as_wide/1, count_ansi_codes/1, with_tab_width/2, at_tab_offset/2, get_terminal_size/0, is_tty/0, strip_ansi/1, is_ansi_component/2, inline_styles/1, fold_with/4, dimensions_with/2, line_with/2, fold_raw/4, soft_wrap_with/5, limit_with/4, stack_horizontal_with/5, align_with/5, position_with/6, padding_with/7, scroll_with/6, stack_vertical_with/5, fold_raw_pieces/4, tabs_to_spaces_with/2, new/0, line/1, dimensions/1, limit/3, soft_wrap/4, tabs_to_spaces/1, position/5, align/4, padding/6, scroll/5, stack_vertical/4, stack_horizontal/4, fold/3]). -export_type([options/0, mode/0, size/0, indent/0, limit_state/0, alignment/0, placement/0, view_state/1, piece/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " \n" " \n" "\n" "\n" " The `with` variants of all functions additionally work with custom options.\n" "\n" " **Tip:** Hover the links for short summaries!\n" "\n" " #### Measure\n" " [line](#line \"Width of a line\")[[_with](#line_with)]\n" " [dimensions](#dimensions \"Size of a string\")[[_with](#dimensions_with)],\n" " [get_terminal_size](#get_terminal_size \"Size of the terminal window\"),\n" " [is_tty](#is_tty \"Check if this is an interactive terminal\")\n" "\n" " #### Layout & Positioning\n" "\n" " [limit](#limit \"Word wrapping and truncation\")[[_with](#limit_with)],\n" " [soft_wrap](#soft_wrap \"Word wrapping with custom indentation logic\")[[_with](#soft_wrap_with)],\n" " [align](#align \"Text alignment\")[[_with](#align_with)],\n" " [tabs_to_spaces](#tabs_to_spaces \"Pin tab widths\")[[_with](#tabs_to_spaces_with)]\n" "\n" " [stack_horizontal](#stack_horizontal \"Column-based layouts\")[[_with](#stack_horizontal_with)],\n" " [stack_vertical](#stack_vertical \"Row-based layouts\")[[_with](#stack_vertical_with)],\n" " [padding](#padding \"Add extra space around a string\")[[_with](#padding_with)],\n" " [position](#position \"Put a string inside a fixed-size box\")[[_with](#position_with)],\n" " [scroll](#scroll \"Cutout a viewport area from a string\")[[_with](#scroll_with)]\n" "\n" " #### ANSI escape sequence helpers\n" " [inline_styles](#inline_styles \"Ensure styling doesn't overflow lines/columns\"),\n" " [strip_ansi](#strip_ansi \"Remove all styles\"),\n" " [is_ansi_component](#is_ansi_component \"Helper for fold\")\n" "\n" " #### Options Builder\n" " [new](#new \"Default options\"),\n" " [ambiguous_as_wide](#ambiguous_as_wide \"CJK support\"),\n" " [count_ansi_codes](#count_ansi_codes \"Non-terminal support\"),\n" " [mode_2027](#mode_2027 \"Compatibility with other libraries\"),\n" " [mode_2027_ext](#mode_2027_ext \"Compatibility with other libraries with extra salt\"),\n" " [mode_wcwidth](#mode_wcwidth \"Default mode, use this for terminals!\"),\n" " [at_tab_offset](#at_tab_offset \"Control tab width calculations\"),\n" " [with_tab_width](#with_tab_width \"Control tab width calculations\")\n" "\n" " #### Advanced\n" " [fold](#fold \"Loop grapheme clusters and their position/size\")[[_with](#fold_with)],\n" " [fold_raw](#fold_raw \"Loop low-level segments and their un-processed width\"),\n" " [fold_raw_pieces](#fold_raw_pieces \"Loop low-level segments and their position/size\")\n" "\n" ). -opaque options() :: {options, boolean(), boolean(), mode(), integer(), integer()}. -type mode() :: mode_wcwidth | mode2027 | mode2027_ext. -type size() :: {size, integer(), integer()}. -type indent() :: indent_unknown | {indent, binary(), integer()}. -type limit_state() :: {limit_state, binary(), binary(), integer(), integer(), binary(), integer(), binary(), integer(), binary(), integer(), indent(), boolean()}. -type alignment() :: left | center | right. -type placement() :: top | middle | bottom. -type view_state(EEN) :: {view_state, EEN, binary(), integer(), integer()}. -type piece() :: {piece, binary(), integer(), integer(), integer()}. -file("src/string_width.gleam", 204). ?DOC( " Measure grapheme clusters instead of individual code points.\n" "\n" " Most terminal emulators do not handle grapheme clusters well and will\n" " instead show their decomposition. To make sure a given string always fits\n" " even on those terminals, the functions in this package will copy this\n" " behaviour as well.\n" "\n" " If you enable this option, the returned numbers will more accurately represent\n" " the width of a string on a website or in an editor.\n" "\n" " **NOTE:** Grapheme support in terminals is highly experimental and subject\n" " to ongoing discussion! When working on CLIs or TUIs, you do not want to use\n" " this option most of the time.\n" "\n" " See also [Grapheme Clusters and Terminal Emulators](https://mitchellh.com/writing/grapheme-clusters-in-terminals)\n" " for a better explanation on how terminals behave.\n" ). -spec mode_2027(options()) -> options(). mode_2027(Options) -> {options, erlang:element(2, Options), erlang:element(3, Options), mode2027, erlang:element(5, Options), erlang:element(6, Options)}. -file("src/string_width.gleam", 219). ?DOC( " Measure grapheme clusters instead of individual code points, and always\n" " treat grapheme clusters with more than one non-modifier character as wide.\n" "\n" " This is a custom extension to Unicode Core. Many single grapheme clusters\n" " would currently still render as wide glyphs in many contexts, since font\n" " shaping would not be able to collapse them into a single narrow \"ligature\".\n" "\n" " This mode is an additional heuristic that tries to handle more such cases.\n" "\n" " See `mode_2027` for more explanation on the implications.\n" ). -spec mode_2027_ext(options()) -> options(). mode_2027_ext(Options) -> {options, erlang:element(2, Options), erlang:element(3, Options), mode2027_ext, erlang:element(5, Options), erlang:element(6, Options)}. -file("src/string_width.gleam", 231). ?DOC( " The default mode and the mode suitable for most terminals.\n" "\n" " Measures individual code points, similar to the libc `wcwidth` function\n" " that almost all of these terminals use.\n" "\n" " Note that except for `fold_raw`, this library will still always process\n" " grapheme clusters as a unit.\n" ). -spec mode_wcwidth(options()) -> options(). mode_wcwidth(Options) -> {options, erlang:element(2, Options), erlang:element(3, Options), mode_wcwidth, erlang:element(5, Options), erlang:element(6, Options)}. -file("src/string_width.gleam", 242). ?DOC( " Some characters are marked by Unicode as \"ambiguous\", meaning they may\n" " occupy 1 or 2 cells, depending on the context, current language, selected\n" " font, surrounding text, and more.\n" "\n" " Unicode recommends treating these characters as narrow by default,\n" " but you can change this behaviour using this option.\n" ). -spec ambiguous_as_wide(options()) -> options(). ambiguous_as_wide(Options) -> {options, erlang:element(2, Options), true, erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options)}. -file("src/string_width.gleam", 251). ?DOC( " Do not ignore ansi escape sequences, and count them as regular characters.\n" "\n" " You can enable this option as an optimisation if you are sure that your\n" " string doesn't contain any ansi escape codes.\n" ). -spec count_ansi_codes(options()) -> options(). count_ansi_codes(Options) -> {options, true, erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options)}. -file("src/string_width.gleam", 260). ?DOC( " Change the number of columns between tab stops. (Default: 8)\n" "\n" " Whenever a tab character `\\t` is encountered, the current column number will\n" " be rounded up to the next multiple of this number.\n" ). -spec with_tab_width(options(), integer()) -> options(). with_tab_width(Options, Tab_width) -> {options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), Tab_width, erlang:element(6, Options)}. -file("src/string_width.gleam", 270). ?DOC( " Define an _offset_ for tab stop calculations. (Default: 0)\n" "\n" " If the text you print doesn't start at the first column, but is instead\n" " indented somehow, you can set this option to this number to make sure tab\n" " stops are correctly calculated.\n" ). -spec at_tab_offset(options(), integer()) -> options(). at_tab_offset(Options, Tab_offset) -> {options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), Tab_offset}. -file("src/string_width.gleam", 287). ?DOC( " Get the size of the terminal, if available.\n" "\n" " Checks the built-in methods for the target, as well as the `LINES` and\n" " `COLUMNS` environment variables.\n" ). -spec get_terminal_size() -> {ok, size()} | {error, nil}. get_terminal_size() -> case string_width_ffi:get_terminal_size() of {ok, {Rows, Columns}} -> {ok, {size, Rows, Columns}}; _ -> {error, nil} end. -file("src/string_width.gleam", 301). ?DOC(" Checks whether the program is running in an interactive terminal (TTY).\n"). -spec is_tty() -> boolean(). is_tty() -> string_width_ffi:is_tty(). -file("src/string_width.gleam", 406). ?DOC(" Get the width of a tab at the given column.\n"). -spec tab(options(), integer()) -> integer(). tab(Options, Col) -> (((case erlang:element(5, Options) of 0 -> 0; Gleam@denominator -> Col div Gleam@denominator end) + 1) * erlang:element(5, Options)) - Col. -file("src/string_width.gleam", 413). -spec prepare_measure(options(), binary()) -> {binary(), list({integer(), integer()}), integer()}. prepare_measure(Options, Str) -> Ansi_ranges = case erlang:element(2, Options) of true -> []; false -> string_width@internal@ansi:match(Str) end, {Str, Ansi_ranges, 0}. -file("src/string_width.gleam", 752). -spec limit_state_col(limit_state()) -> integer(). limit_state_col(State) -> ((erlang:element(5, State) + erlang:element(7, State)) + erlang:element( 9, State )) + erlang:element(11, State). -file("src/string_width.gleam", 1781). ?DOC(" Integer division, rounding up\n"). -spec div_up(integer(), integer()) -> integer(). div_up(Numerator, Denom) -> case Denom of 0 -> 0; Gleam@denominator -> ((Numerator + Denom) - 1) div Gleam@denominator end. -file("src/string_width.gleam", 1786). ?DOC(" do something, multiple times.\n"). -spec repeat(integer(), EFH, fun((EFH) -> EFH)) -> EFH. repeat(Times, State, Fun) -> case Times > 0 of true -> repeat(Times - 1, Fun(State), Fun); false -> State end. -file("src/string_width.gleam", 1806). ?DOC(" early return on empty lists.\n"). -spec guard_list(list(EFJ), EFL, fun((EFJ, list(EFJ)) -> EFL)) -> EFL. guard_list(List, Empty, Non_empty) -> case List of [] -> Empty; [Head | Tail] -> Non_empty(Head, Tail) end. -file("src/string_width.gleam", 1897). ?DOC( " Strip _all_ ansi sequences from a string, using the same matching algorithm\n" " that this library uses internally.\n" "\n" " This makes it safe to enable `count_ansi_codes`, or print a string without\n" " having to worry that it might mess with the terminal and/or colors.\n" "\n" " Unexpected characters inside of escape sequences are ignored (swallowed).\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " strip_ansi(\"\\u{1b}[0;33;49;3;9;4mhi~\\u{1b}[0m\")\n" " // --> \"hi~\"\n" "\n" " strip_ansi(\"check out \\u{1b}]8;;https://gleam.run\\u{7}Gleam!\\u{1b}]8;;\\u{7}\")\n" " // --> \"check out Gleam!\"\n" " ```\n" ). -spec strip_ansi(binary()) -> binary(). strip_ansi(Str) -> string_width@internal@ansi:strip(Str). -file("src/string_width.gleam", 1904). ?DOC( " Returns true if a given component string recieved in `fold` is an ANSI\n" " escape sequence.\n" ). -spec is_ansi_component(binary(), options()) -> boolean(). is_ansi_component(Str, Options) -> case erlang:element(2, Options) of true -> false; false -> case Str of <<"\x{1b}"/utf8, _/binary>> -> true; <<"\x{9b}"/utf8, _/binary>> -> true; <<"\x{9d}"/utf8, _/binary>> -> true; _ -> false end end. -file("src/string_width.gleam", 2082). -spec piece_reducer(EFR, options(), fun((EFR, piece()) -> EFR)) -> {{EFR, integer(), integer()}, fun(({EFR, integer(), integer()}, binary(), integer()) -> {EFR, integer(), integer()})}. piece_reducer(State, Options, Fun) -> Initial = {State, 0, erlang:element(6, Options)}, Fun@1 = fun(State@1, Piece, Width) -> {State@2, Row, Column} = State@1, Width@1 = case Piece of <<"\t"/utf8>> -> tab(Options, Column); _ -> Width end, State@3 = Fun(State@2, {piece, Piece, Row, Column, Width@1}), case Piece of <<"\n"/utf8>> -> {State@3, Row + 1, erlang:element(6, Options)}; _ -> {State@3, Row, Column + Width@1} end end, {Initial, Fun@1}. -file("src/string_width.gleam", 2309). -spec table_lookup(bitstring(), integer()) -> boolean(). table_lookup(Table, Value) -> Hi = erlang:'bsr'(Value, 8), Md = erlang:'bsr'(erlang:'band'(Value, 16#ff), 3), Lo = erlang:'band'(Value, 7), Lvl1_skip = Hi * 8, Lvl1@1 = case Table of <<_:Lvl1_skip, Lvl1/integer, _/bitstring>> -> Lvl1; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"string_width"/utf8>>, function => <<"table_lookup"/utf8>>, line => 2315, value => _assert_fail, start => 72379, 'end' => 72437, pattern_start => 72390, pattern_end => 72429}) end, Lvl2_skip = ((Lvl1@1 * 32) + Md) * 8, Lvl3@1 = case Table of <<_:Lvl2_skip, Lvl3/integer, _/bitstring>> -> Lvl3; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"string_width"/utf8>>, function => <<"table_lookup"/utf8>>, line => 2318, value => _assert_fail@1, start => 72482, 'end' => 72540, pattern_start => 72493, pattern_end => 72532}) end, (erlang:'bsr'(Lvl3@1, Lo) rem 2) /= 0. -file("src/string_width.gleam", 2267). -spec is_ignorable(integer()) -> boolean(). is_ignorable(Cp) -> case Cp =< 16#1ffff of true -> table_lookup( <<16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 17, 33, 17, 17, 17, 34, 35, 36, 37, 38, 39, 40, 17, 17, 41, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 42, 43, 17, 17, 44, 45, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 46, 17, 47, 48, 49, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 51, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 52, 17, 17, 53, 54, 17, 55, 56, 57, 17, 17, 17, 17, 17, 17, 58, 17, 17, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 17, 73, 74, 75, 76, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 77, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 78, 17, 17, 17, 17, 17, 17, 17, 17, 79, 80, 17, 17, 17, 81, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 82, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 83, 17, 84, 85, 17, 17, 17, 17, 17, 17, 17, 86, 17, 17, 17, 17, 17, 87, 80, 88, 17, 89, 90, 17, 17, 91, 92, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 191, 182, 0, 0, 0, 0, 0, 0, 0, 63, 0, 255, 23, 0, 0, 0, 0, 0, 248, 255, 255, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 191, 159, 61, 0, 0, 0, 128, 2, 0, 0, 0, 255, 255, 255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 1, 0, 0, 0, 0, 0, 0, 248, 15, 32, 0, 0, 192, 251, 239, 62, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 131, 255, 0, 0, 0, 0, 0, 252, 255, 255, 255, 255, 255, 255, 7, 0, 0, 0, 0, 0, 0, 20, 254, 33, 254, 0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 16, 30, 32, 0, 0, 12, 0, 0, 64, 6, 0, 0, 0, 0, 0, 0, 16, 134, 57, 2, 0, 0, 0, 35, 0, 6, 0, 0, 0, 0, 0, 0, 16, 190, 33, 0, 0, 12, 0, 0, 252, 2, 0, 0, 0, 0, 0, 0, 144, 30, 32, 96, 0, 12, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 208, 193, 61, 96, 0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 144, 64, 48, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 24, 30, 32, 0, 0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 7, 128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 31, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 160, 2, 0, 0, 0, 0, 0, 0, 254, 127, 223, 224, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 253, 102, 0, 0, 0, 195, 1, 0, 30, 0, 100, 32, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 176, 63, 64, 254, 15, 32, 0, 0, 0, 0, 0, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 1, 4, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 9, 0, 0, 0, 0, 0, 0, 64, 127, 229, 31, 248, 159, 0, 0, 0, 0, 0, 0, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 208, 23, 4, 0, 0, 0, 0, 248, 15, 0, 3, 0, 0, 0, 60, 59, 0, 0, 0, 0, 0, 0, 64, 163, 3, 0, 0, 0, 0, 0, 0, 240, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 255, 253, 33, 16, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 248, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 247, 63, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 68, 8, 0, 0, 96, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 255, 255, 3, 128, 0, 0, 0, 0, 192, 63, 0, 0, 128, 255, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 200, 51, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 126, 102, 0, 8, 16, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 157, 193, 2, 0, 0, 0, 0, 48, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 15, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 240, 0, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 1, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 255, 127, 0, 0, 0, 0, 0, 25, 128, 3, 0, 0, 0, 0, 0, 120, 38, 4, 32, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 128, 239, 31, 0, 0, 0, 0, 0, 0, 0, 8, 0, 3, 0, 0, 0, 0, 0, 192, 127, 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 211, 64, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 248, 7, 0, 0, 3, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 0, 192, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 248, 1, 64, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 92, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 133, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 176, 1, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 167, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 188, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 255, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 12, 1, 0, 0, 0, 254, 7, 0, 0, 0, 0, 248, 121, 128, 0, 126, 14, 0, 0, 0, 0, 0, 252, 127, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 255, 255, 252, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 180, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 3, 0, 0, 0, 0, 0, 192, 7, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 129, 255, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 128, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 63, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 248, 255, 231, 15, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 127, 248, 255, 255, 255, 255, 255, 31, 32, 0, 16, 0, 0, 248, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 249, 219, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, Cp ); false -> (Cp >= 16#e0000) andalso (Cp =< 16#e0fff) end. -file("src/string_width.gleam", 2274). -spec is_ambiguous(integer()) -> boolean(). is_ambiguous(Cp) -> case Cp =< 16#ffff of true -> table_lookup( <<8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 13, 13, 22, 13, 13, 13, 13, 13, 13, 23, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, 13, 13, 13, 13, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 101, 223, 247, 64, 0, 129, 193, 67, 55, 141, 87, 2, 0, 10, 8, 192, 8, 14, 129, 23, 47, 12, 0, 192, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 85, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 46, 1, 175, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 254, 255, 251, 3, 254, 255, 251, 3, 0, 0, 0, 0, 0, 0, 2, 0, 255, 255, 255, 255, 255, 255, 255, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 51, 247, 0, 45, 72, 0, 0, 0, 0, 0, 0, 16, 128, 30, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 2, 72, 0, 70, 8, 0, 0, 0, 0, 24, 120, 255, 15, 255, 3, 0, 2, 255, 3, 0, 0, 0, 3, 0, 0, 20, 0, 128, 0, 0, 0, 141, 137, 34, 228, 169, 95, 240, 48, 0, 17, 4, 0, 243, 204, 0, 0, 204, 0, 32, 2, 32, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 255, 255, 255, 255, 15, 0, 255, 255, 60, 0, 251, 3, 204, 48, 195, 201, 3, 0, 60, 128, 0, 0, 96, 194, 0, 80, 0, 0, 0, 0, 5, 0, 0, 0, 187, 183, 0, 0, 0, 0, 0, 192, 0, 0, 0, 128, 192, 191, 239, 255, 11, 251, 211, 219, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 192, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32>>, Cp ); false -> (((((((((Cp >= 16#1f100) andalso (Cp =< 16#1f10a)) orelse ((Cp >= 16#1f110) andalso (Cp =< 16#1f12d))) orelse ((Cp >= 16#1f130) andalso (Cp =< 16#1f169))) orelse ((Cp >= 16#1f170) andalso (Cp =< 16#1f18d))) orelse ((Cp >= 16#1f18f) andalso (Cp =< 16#1f190))) orelse ((Cp >= 16#1f19b) andalso (Cp =< 16#1f1ac))) orelse ((Cp >= 16#e0100) andalso (Cp =< 16#e01ef))) orelse ((Cp >= 16#f0000) andalso (Cp =< 16#ffffd))) orelse ((Cp >= 16#100000) andalso (Cp =< 16#10FFFD)) end. -file("src/string_width.gleam", 2291). -spec is_wide(integer()) -> boolean(). is_wide(Cp) -> case Cp =< 16#1ffff of true -> table_lookup( <<16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 16, 19, 20, 21, 16, 16, 16, 22, 16, 16, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 16, 16, 16, 16, 30, 16, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 28, 28, 16, 16, 16, 32, 33, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 35, 28, 28, 28, 28, 36, 37, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 38, 28, 39, 40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 41, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 42, 43, 44, 45, 46, 47, 48, 49, 16, 50, 51, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 48, 0, 0, 0, 255, 0, 0, 255, 15, 0, 0, 0, 0, 128, 0, 252, 8, 0, 2, 12, 0, 96, 48, 64, 16, 0, 0, 4, 44, 36, 32, 12, 0, 0, 0, 1, 0, 0, 0, 80, 184, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 224, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 128, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 255, 255, 255, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 3, 0, 0, 255, 255, 255, 255, 247, 255, 127, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 3, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 0, 0, 0, 0, 128, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 111, 255, 255, 255, 255, 7, 0, 4, 0, 0, 0, 39, 0, 240, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 0, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 254, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 255, 255, 255, 255, 255, 15, 255, 1, 3, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 1, 224, 191, 255, 255, 255, 255, 255, 255, 255, 255, 223, 255, 255, 15, 0, 255, 255, 255, 255, 255, 135, 15, 0, 255, 255, 17, 255, 255, 255, 255, 255, 255, 255, 255, 127, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 159, 255, 255, 255, 255, 255, 255, 255, 63, 0, 120, 255, 255, 255, 0, 0, 4, 0, 0, 96, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 63, 16, 231, 240, 0, 24, 240, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 15, 1, 0, 0, 240, 255, 255, 255, 255, 255, 247, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 31, 255, 131, 255, 255, 255, 255, 255, 255, 127, 192, 255, 159, 255, 3, 255, 1>>, Cp ); false -> (Cp >= 16#20000) andalso (Cp =< 16#40000) end. -file("src/string_width.gleam", 2242). -spec wcwidth(options(), integer()) -> integer(). wcwidth(Options, Cp) -> case Cp of _ when Cp =< 16#1f -> 0; _ when Cp =< 16#7e -> 1; _ -> case is_ignorable(Cp) of true -> 0; false -> case is_wide(Cp) orelse (erlang:element(3, Options) andalso is_ambiguous( Cp )) of true -> 2; false -> 1 end end end. -file("src/string_width.gleam", 2298). -spec is_spacing_mark(integer()) -> boolean(). is_spacing_mark(Cp) -> case Cp =< 16#1ffff of true -> table_lookup( <<16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 20, 21, 16, 22, 23, 16, 16, 16, 16, 16, 16, 24, 16, 25, 26, 27, 28, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 29, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, 31, 32, 33, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 16, 45, 46, 47, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 49, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 50, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 51, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 200, 1, 222, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 192, 129, 25, 128, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 192, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 192, 1, 26, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 64, 129, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 198, 29, 128, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 64, 159, 13, 96, 0, 0, 0, 8, 0, 12, 0, 0, 0, 0, 0, 0, 192, 193, 29, 128, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 255, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 25, 0, 0, 192, 0, 156, 63, 0, 0, 152, 159, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 192, 191, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 14, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 160, 0, 26, 224, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 32, 232, 27, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 194, 4, 0, 0, 0, 0, 0, 0, 128, 92, 12, 0, 0, 0, 0, 0, 240, 15, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 128, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 240, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 48, 204, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 25, 0, 0, 32, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 22, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 56, 128, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 192, 158, 57, 128, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 164, 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 122, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 33, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 240, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 128, 1, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 8, 0, 0, 0, 0, 0, 48, 192, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 224, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, Cp ); false -> false end. -file("src/string_width.gleam", 2323). -spec fold_graphemes(binary(), EFY, fun((EFY, binary()) -> EFY)) -> EFY. fold_graphemes(Str, State, Fun) -> case gleam_stdlib:string_pop_grapheme(Str) of {ok, {Grapheme, Str@1}} -> fold_graphemes(Str@1, Fun(State, Grapheme), Fun); {error, nil} -> State end. -file("src/string_width.gleam", 2156). -spec fold_chars_wcwidth( options(), binary(), EFV, fun((EFV, binary(), integer()) -> EFV) ) -> EFV. fold_chars_wcwidth(Options, String, State, Fun) -> fold_graphemes( String, State, fun(State@1, Grapheme) -> Width = begin string_width_ffi:fold_codepoints( Grapheme, 0, fun(Acc, Cp) -> Acc + wcwidth(Options, Cp) end ) end, Fun(State@1, Grapheme, Width) end ). -file("src/string_width.gleam", 2192). -spec measure_mode_2027(options(), binary()) -> integer(). measure_mode_2027(Options, String) -> string_width_ffi:fold_codepoints(String, 0, fun(Max, Cp) -> case Cp of 16#fe0f when Max > 0 -> 2; _ -> gleam@int:max(Max, wcwidth(Options, Cp)) end end). -file("src/string_width.gleam", 2170). -spec fold_chars_2027( options(), binary(), EFW, fun((EFW, binary(), integer()) -> EFW) ) -> EFW. fold_chars_2027(Options, String, State, Fun) -> fold_graphemes( String, State, fun(State@1, Grapheme) -> Width = measure_mode_2027(Options, Grapheme), Fun(State@1, Grapheme, Width) end ). -file("src/string_width.gleam", 2201). -spec measure_mode_2027_ext(options(), binary()) -> integer(). measure_mode_2027_ext(Options, String) -> string_width_ffi:fold_codepoints( String, 0, fun(Max, Cp) -> case Max =:= 0 of true -> wcwidth(Options, Cp); false -> case Cp of 16#fe0f -> 2; _ -> case wcwidth(Options, Cp) of 0 -> Max; Width -> case is_spacing_mark(Cp) of true -> gleam@int:max(Max, Width); false -> 2 end end end end end ). -file("src/string_width.gleam", 2181). -spec fold_chars_2027_ext( options(), binary(), EFX, fun((EFX, binary(), integer()) -> EFX) ) -> EFX. fold_chars_2027_ext(Options, String, State, Fun) -> fold_graphemes( String, State, fun(State@1, Grapheme) -> Width = measure_mode_2027_ext(Options, Grapheme), Fun(State@1, Grapheme, Width) end ). -file("src/string_width.gleam", 2109). -spec fold_parts( binary(), integer(), list({integer(), integer()}), EFT, fun((EFT, binary()) -> EFT), fun((EFT, binary(), integer()) -> EFT) ) -> EFT. fold_parts(String, Offset, Ranges, State, On_chars, On_range) -> case Ranges of [{Start, Length} | Ranges@1] when Start =:= Offset -> {Range_slice, String@1} = erlang:split_binary(String, Length), State@1 = On_range(State, Range_slice, Length), Offset@1 = Start + Length, fold_parts( String@1, Offset@1, Ranges@1, State@1, On_chars, On_range ); [{Start@1, Length@1} | Ranges@2] -> {Before, At_range} = erlang:split_binary(String, Start@1 - Offset), {Range_slice@1, String@2} = erlang:split_binary(At_range, Length@1), State@2 = begin _pipe = State, _pipe@1 = On_chars(_pipe, Before), On_range(_pipe@1, Range_slice@1, Length@1) end, Offset@2 = Start@1 + Length@1, fold_parts( String@2, Offset@2, Ranges@2, State@2, On_chars, On_range ); [] -> case String of <<""/utf8>> -> State; _ -> On_chars(State, String) end end. -file("src/string_width.gleam", 1836). ?DOC( " Make sure [SGR ansi codes](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters)\n" " (these are the ones you'd use for colors and styling!) never wrap\n" " around a line. This makes it save to use other layout functions on the\n" " resulting string, without affecting the styling anymore.\n" "\n" " It does so by collecting all SGR sequences since the last reset, and\n" " re-applying them on each line break.\n" "\n" " **Warning:** This function assumes it is safe to emit reset commands,\n" " and that no ambient styling is in effect (that is, the terminal would be in\n" " its default state when printing the resulting string!)\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " // \"\\u{1b}[31m\": red text color\n" " // \"\\u{1b}[m\": reset/normal mode\n" " inline_styles(\"\\u{1b}[31mhello\\nworld\")\n" " // --> \"\\u{1b}[31mhello\" <> \"\\u{1b}[m\\n\" <> \"\\u{1b}[31mworld\" <> \"\\u{1b}[m\"\n" " ```\n" ). -spec inline_styles(binary()) -> binary(). inline_styles(Str) -> Ansi_ranges = string_width@internal@ansi:match(Str), On_range = fun(State, Ansi, _) -> {Buf, Sgr} = State, case Ansi of <<"\x{1b}[0m"/utf8>> -> {<>, <<""/utf8>>}; <<"\x{1b}[m"/utf8>> -> {<>, <<""/utf8>>}; _ -> case gleam_stdlib:string_ends_with(Ansi, <<"m"/utf8>>) of true -> {<>, <>}; false -> {<>, Sgr} end end end, On_chars = fun(State@1, Chars) -> case State@1 of {Buf@1, <<""/utf8>>} -> {<>, <<""/utf8>>}; {Buf@2, Sgr@1} -> {Rest, _, Buf@4} = begin string_width_ffi:fold_bytes( Chars, {Chars, 0, Buf@2}, fun(_use0, Byte) -> {Ptr, Pos, Buf@3} = _use0, case Byte of 16#A -> {Line@1, Ptr@2} = case erlang:split_binary( Ptr, Pos ) of {Line, <<"\n"/utf8, Ptr@1/binary>>} -> { Line, Ptr@1}; _assert_fail -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"string_width"/utf8>>, function => <<"inline_styles"/utf8>>, line => 1859, value => _assert_fail, start => 59210, 'end' => 59266, pattern_start => 59221, pattern_end => 59241} ) end, {Ptr@2, 0, <<<<<>/binary, "\x{1b}[m\n"/utf8>>/binary, Sgr@1/binary>>}; _ -> {Ptr, Pos + 1, Buf@3} end end ) end, {<>, Sgr@1} end end, State@2 = fold_parts( Str, 0, Ansi_ranges, {<<""/utf8>>, <<""/utf8>>}, On_chars, On_range ), case State@2 of {Buf@5, <<""/utf8>>} -> Buf@5; {Buf@6, _} -> <> end. -file("src/string_width.gleam", 1953). ?DOC( " A higher-level `fold` that keeps track of the position inside of the string.\n" " Like `fold`, but using custom options to measure the pieces.\n" "\n" " Handles tabs and newlines, and always passes full grapheme clusters,\n" " regardless of options. Concatenating the graphemes produces the original string.\n" "\n" " Intended to be used as a basis for custom layout algorithms.\n" ). -spec fold_with(binary(), options(), EFO, fun((EFO, piece()) -> EFO)) -> EFO. fold_with(Str, Options, State, Fun) -> {State@1, Fun@1} = piece_reducer(State, Options, Fun), On_chars = case erlang:element(4, Options) of mode_wcwidth -> fun(State@2, Str@1) -> fold_chars_wcwidth(Options, Str@1, State@2, Fun@1) end; mode2027 -> fun(State@3, Str@2) -> fold_chars_2027(Options, Str@2, State@3, Fun@1) end; mode2027_ext -> fun(State@4, Str@3) -> fold_chars_2027_ext(Options, Str@3, State@4, Fun@1) end end, Ansi_ranges = case erlang:element(2, Options) of true -> []; false -> string_width@internal@ansi:match(Str) end, On_range = fun(State@5, Ansi, _) -> Fun@1(State@5, Ansi, 0) end, {State@6, _, _} = fold_parts( Str, 0, Ansi_ranges, State@1, On_chars, On_range ), State@6. -file("src/string_width.gleam", 756). -spec limit_emergency_break_reflow(binary(), integer(), options()) -> {binary(), binary(), integer()}. limit_emergency_break_reflow(Str, Max_col, Options) -> Initial = {<<""/utf8>>, <<""/utf8>>, 0}, fold_with( Str, Options, Initial, fun(_use0, Piece) -> {Before, After, Width} = _use0, case (erlang:element(4, Piece) + erlang:element(5, Piece)) > Max_col of true -> {Before, <>, Width + erlang:element(5, Piece)}; false -> {<>, After, Width} end end ). -file("src/string_width.gleam", 769). -spec limit_emergency_truncate(binary(), integer(), options()) -> {binary(), integer()}. limit_emergency_truncate(Str, Max_col, Options) -> fold_with( Str, Options, {<<""/utf8>>, 0}, fun(_use0, Piece) -> {Truncated, Width} = _use0, case is_ansi_component(erlang:element(2, Piece), Options) orelse ((erlang:element( 4, Piece ) + erlang:element(5, Piece)) =< Max_col) of true -> {<>, Width + erlang:element(5, Piece)}; false -> {Truncated, Width} end end ). -file("src/string_width.gleam", 2146). -spec fold_chars_raw( options(), binary(), EFU, fun((EFU, binary(), integer()) -> EFU) ) -> EFU. fold_chars_raw(Options, String, State, Fun) -> string_width_ffi:fold_codepoints( String, State, fun(State@1, Cp) -> Fun( State@1, string_width_ffi:utf_codepoint_to_string(Cp), wcwidth(Options, Cp) ) end ). -file("src/string_width.gleam", 367). ?DOC(" Like `dimensions`, but use custom options.\n"). -spec dimensions_with(binary(), options()) -> size(). dimensions_with(Str, Options) -> {Str@1, Ranges, Range_width} = prepare_measure(Options, Str), Fun = fun(State, Chr, Width) -> {Rows, Cols_max, Cols_curr} = State, case Chr of <<"\n"/utf8>> -> {Rows + 1, gleam@int:max(Cols_max, Cols_curr), erlang:element(6, Options)}; <<"\t"/utf8>> -> {Rows, Cols_max, Cols_curr + tab(Options, Cols_curr)}; _ -> {Rows, Cols_max, Cols_curr + Width} end end, On_range = fun(State@1, Ansi, Length) -> Fun(State@1, Ansi, Range_width * Length) end, On_chars = case erlang:element(4, Options) of mode_wcwidth -> fun(State@2, Str@2) -> fold_chars_raw(Options, Str@2, State@2, Fun) end; mode2027 -> fun(State@3, Str@3) -> fold_chars_2027(Options, Str@3, State@3, Fun) end; mode2027_ext -> fun(State@4, Str@4) -> fold_chars_2027_ext(Options, Str@4, State@4, Fun) end end, Initial = {0, 0, erlang:element(6, Options)}, {Rows@1, Cols_max@1, Cols_curr@1} = fold_parts( Str@1, 0, Ranges, Initial, On_chars, On_range ), Cols_max@2 = gleam@int:max(Cols_max@1, Cols_curr@1) - erlang:element( 6, Options ), Rows@2 = case Cols_curr@1 > erlang:element(6, Options) of true -> Rows@1 + 1; false -> Rows@1 end, {size, Rows@2, Cols_max@2}. -file("src/string_width.gleam", 341). ?DOC( " Like `line`, but use custom options.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " let options =\n" " new()\n" " |> mode_2027\n" "\n" " line_with(\"πŸ‘©β€πŸ‘©β€πŸ‘¦β€πŸ‘¦\", options)\n" " // --> 2\n" " ```\n" ). -spec line_with(binary(), options()) -> integer(). line_with(Str, Options) -> {size, _, Columns} = dimensions_with(Str, Options), Columns. -file("src/string_width.gleam", 784). -spec limit_state_indent(fun((binary()) -> binary()), options(), limit_state()) -> {binary(), integer()}. limit_state_indent(Get_indent, Options, State) -> case erlang:element(12, State) of indent_unknown -> Indent = Get_indent(erlang:element(3, State)), Indent_width = line_with(Indent, Options), {Indent, Indent_width}; {indent, Indent@1, Indent_width@1} -> {Indent@1, Indent_width@1} end. -file("src/string_width.gleam", 800). ?DOC(" push a word-character into LimitState\n"). -spec limit_state_push( options(), size(), binary(), integer(), fun((binary()) -> binary()), limit_state(), binary(), integer() ) -> limit_state(). limit_state_push( Options, Max_size, Ellipsis, Ellipsis_width, Get_indent, State, Piece, Width ) -> Line_col = limit_state_col(State) + Width, Emergency_break_col = case erlang:element(12, State) of indent_unknown -> (erlang:element(9, State) + erlang:element(11, State)) + Width; {indent, _, Indent_width} -> ((Indent_width + erlang:element(9, State)) + erlang:element( 11, State )) + Width end, Lines_remaining = (erlang:element(2, Max_size) - erlang:element(4, State)) - 1, Overflow_col = case Lines_remaining of 0 -> erlang:element(3, Max_size) - Ellipsis_width; _ -> erlang:element(3, Max_size) end, case {Line_col =< Overflow_col, (Emergency_break_col =< Overflow_col) orelse (Lines_remaining =:= 0)} of {true, _} -> {limit_state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), <<(erlang:element(8, State))/binary, Piece/binary>>, erlang:element(9, State) + Width, erlang:element(10, State), erlang:element(11, State), erlang:element(12, State), erlang:element(13, State)}; {false, true} -> Indent = Get_indent( <<<<(erlang:element(3, State))/binary, (erlang:element(6, State))/binary>>/binary, (erlang:element(8, State))/binary>> ), Indent_width@1 = line_with(Indent, Options), case (erlang:element(9, State) =:= 0) andalso (Lines_remaining > 0) of true -> {limit_state, <<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, (erlang:element(8, State))/binary>>/binary, "\n"/utf8>>, Indent, erlang:element(4, State) + 1, Indent_width@1, <<""/utf8>>, 0, <<(erlang:element(10, State))/binary, Piece/binary>>, erlang:element(11, State) + Width, <<""/utf8>>, 0, {indent, Indent, Indent_width@1}, false}; false -> {limit_state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State), <<(erlang:element(10, State))/binary, Piece/binary>>, erlang:element(11, State) + Width, {indent, Indent, Indent_width@1}, erlang:element(13, State)} end; {false, false} -> {Indent@1, Indent_width@2} = limit_state_indent( Get_indent, Options, State ), case {Lines_remaining, erlang:element(13, State)} of {1, true} -> {Truncated, _} = limit_emergency_truncate( <<<<(erlang:element(8, State))/binary, (erlang:element(10, State))/binary>>/binary, Piece/binary>>, (erlang:element(3, Max_size) - Ellipsis_width) - Indent_width@2, Options ), {limit_state, <<<<<<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, "-\n"/utf8>>/binary, Indent@1/binary>>/binary, Truncated/binary>>/binary, Ellipsis/binary>>, <<""/utf8>>, erlang:element(2, Max_size), erlang:element(3, Max_size), <<""/utf8>>, 0, <<""/utf8>>, 0, <<""/utf8>>, 0, {indent, Indent@1, Indent_width@2}, false}; {_, true} -> {Before, After, After_width} = limit_emergency_break_reflow( <<<<(erlang:element(8, State))/binary, (erlang:element(10, State))/binary>>/binary, Piece/binary>>, erlang:element(3, Max_size) - Indent_width@2, Options ), {limit_state, <<<<<<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, "-\n"/utf8>>/binary, Indent@1/binary>>/binary, Before/binary>>/binary, "\n"/utf8>>, Indent@1, erlang:element(4, State) + 2, Indent_width@2, <<""/utf8>>, 0, After, After_width, <<""/utf8>>, 0, {indent, Indent@1, Indent_width@2}, false}; {_, false} -> {Truncated@1, Overflow, Overflow_width} = limit_emergency_break_reflow( <<<<(erlang:element(8, State))/binary, (erlang:element(10, State))/binary>>/binary, Piece/binary>>, erlang:element(9, State), Options ), {limit_state, <<<<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, (erlang:element(6, State))/binary>>/binary, Truncated@1/binary>>/binary, "\n"/utf8>>, Indent@1, erlang:element(4, State) + 1, Indent_width@2, <<""/utf8>>, 0, Overflow, Overflow_width, <<""/utf8>>, 0, {indent, Indent@1, Indent_width@2}, false} end end. -file("src/string_width.gleam", 1003). ?DOC(" Push a non-word character into LimitState, commiting the currently accumulated word.\n"). -spec limit_state_commit( options(), size(), binary(), integer(), fun((binary()) -> binary()), limit_state(), binary(), integer(), boolean() ) -> limit_state(). limit_state_commit( Options, Max_size, Ellipsis, Ellipsis_width, Get_indent, State, Piece, Width, Is_final ) -> New_col = limit_state_col(State), Max_row = erlang:element(2, Max_size), Is_last_line = (erlang:element(4, State) + 1) >= Max_row, Shy = Piece =:= <<"\x{ad}"/utf8>>, Piece@1 = case Shy of true -> <<""/utf8>>; false -> Piece end, case {erlang:element(9, State) =:= 0, erlang:element(11, State) =:= 0} of {true, true} -> case (erlang:element(4, State) =:= 0) andalso (erlang:element( 5, State ) =:= 0) of true -> State; false -> {limit_state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), <<(erlang:element(6, State))/binary, Piece@1/binary>>, erlang:element(7, State) + Width, erlang:element(8, State), erlang:element(9, State), erlang:element(10, State), erlang:element(11, State), erlang:element(12, State), erlang:element(13, State)} end; {false, true} -> Line = <<<<<<(erlang:element(3, State))/binary, (erlang:element(6, State))/binary>>/binary, (erlang:element(8, State))/binary>>/binary, (erlang:element(10, State))/binary>>, {limit_state, erlang:element(2, State), Line, erlang:element(4, State), New_col, Piece@1, Width, <<""/utf8>>, 0, <<""/utf8>>, 0, erlang:element(12, State), Shy andalso ((New_col + 1) < erlang:element(3, Max_size))}; {_, false} -> case {Is_last_line, Is_final, erlang:element(11, State) > Ellipsis_width} of {true, true, false} -> {limit_state, <<<<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, (erlang:element(6, State))/binary>>/binary, (erlang:element(8, State))/binary>>/binary, (erlang:element(10, State))/binary>>, <<""/utf8>>, erlang:element(4, State), ((erlang:element(5, State) + erlang:element(7, State)) + erlang:element( 9, State )) + erlang:element(11, State), Piece@1, Width, <<""/utf8>>, 0, <<""/utf8>>, 0, erlang:element(12, State), false}; {true, _, _} -> {Truncated, Truncated_width} = limit_emergency_truncate( <<<<(erlang:element(8, State))/binary, (erlang:element(10, State))/binary>>/binary, Piece@1/binary>>, erlang:element(9, State), Options ), Str = case Truncated_width of 0 -> <<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, Truncated/binary>>/binary, Ellipsis/binary>>; _ -> <<<<<<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, (erlang:element(6, State))/binary>>/binary, Truncated/binary>>/binary, Ellipsis/binary>> end, {limit_state, Str, <<""/utf8>>, erlang:element(4, State) + 1, erlang:element(3, Max_size), <<""/utf8>>, 0, <<""/utf8>>, 0, <<""/utf8>>, 0, indent_unknown, false}; {false, _, _} -> {Indent, Indent_width} = limit_state_indent( Get_indent, Options, State ), Str@1 = case erlang:element(13, State) of true -> <<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, "-\n"/utf8>>; false -> <<<<(erlang:element(2, State))/binary, (erlang:element(3, State))/binary>>/binary, "\n"/utf8>> end, {limit_state, Str@1, <<<>/binary, (erlang:element(10, State))/binary>>, erlang:element(4, State) + 1, (Indent_width + erlang:element(9, State)) + erlang:element( 11, State ), Piece@1, Width, <<""/utf8>>, 0, <<""/utf8>>, 0, {indent, Indent, Indent_width}, Shy} end end. -file("src/string_width.gleam", 1794). ?DOC(" line_with, but with a few fast paths for commmonly used strings.\n"). -spec spacer_width(options(), binary()) -> integer(). spacer_width(Options, Str) -> case Str of <<""/utf8>> -> 0; <<" "/utf8>> -> 1; <<"..."/utf8>> -> 3; <<"…"/utf8>> -> 1; <<"0"/utf8>> -> 1; _ -> line_with(Str, Options) end. -file("src/string_width.gleam", 2017). ?DOC( " A low-level fold that iterate over the measured components of a string.\n" " Components are either graphemes or codepoints depending on the `mode` option,\n" " or other undivisible sequences, like ANSI escape codes.\n" "\n" " This function does not by itself keep track of any additional state, and\n" " doesn't for example handle newlines or tabs like `fold` would.\n" " If you know that your algorithm is safe and won't break up graphemes (or\n" " maybe this is acceptable), you can use this fold variant instead as a\n" " performance optimisation.\n" "\n" " Concatenating all components is guaranteed to produce the original string.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " // A slower string_width.line implementation that doesn't handle tabs\n" " fold_raw(\"hello\", new(), from: 0, with: fn(so_far, _chr, width) { width + so_far })\n" " // --> 5\n" " ```\n" "\n" " ```gleam\n" " // truncate a string after 50 characters, but keep all ansi sequences.\n" " let options = new()\n" " use #(total, acc), chr, width <- fold_raw(input, options, from: #(0, \"\"))\n" " case total >= 50 {\n" " True -> case is_ansi_component(chr, options) {\n" " True -> #(total, acc <> chr)\n" " False -> #(total, acc)\n" " }\n" " False -> #(total + width, acc <> chr)\n" " }\n" " ```\n" ). -spec fold_raw(binary(), options(), EFP, fun((EFP, binary(), integer()) -> EFP)) -> EFP. fold_raw(String, Options, State, Fun) -> Ansi_ranges = case erlang:element(2, Options) of true -> []; false -> string_width@internal@ansi:match(String) end, On_chars = case erlang:element(4, Options) of mode_wcwidth -> fun(State@1, Str) -> fold_chars_raw(Options, Str, State@1, Fun) end; mode2027 -> fun(State@2, Str@1) -> fold_chars_2027(Options, Str@1, State@2, Fun) end; mode2027_ext -> fun(State@3, Str@2) -> fold_chars_2027_ext(Options, Str@2, State@3, Fun) end end, On_range = fun(State@4, Ansi, _) -> Fun(State@4, Ansi, 0) end, fold_parts(String, 0, Ansi_ranges, State, On_chars, On_range). -file("src/string_width.gleam", 552). ?DOC(" Like `soft_wrap`, but using custom options to measure the strings and indents.\n"). -spec soft_wrap_with( binary(), size(), options(), binary(), fun((binary()) -> binary()) ) -> binary(). soft_wrap_with(Str, Max_size, Options, Ellipsis, To_indent) -> Ellipsis_width = spacer_width(Options, Ellipsis), Max_row = erlang:element(2, Max_size), Push = fun(State, Piece, Width) -> limit_state_push( Options, Max_size, Ellipsis, Ellipsis_width, To_indent, State, Piece, Width ) end, Commit = fun(State@1, Piece@1, Width@1, Is_final) -> limit_state_commit( Options, Max_size, Ellipsis, Ellipsis_width, To_indent, State@1, Piece@1, Width@1, Is_final ) end, Initial = {limit_state, <<""/utf8>>, <<""/utf8>>, 0, 0, <<""/utf8>>, 0, <<""/utf8>>, 0, <<""/utf8>>, 0, indent_unknown, false}, State@4 = begin fold_raw( Str, Options, Initial, fun(State@2, Piece@2, Width@2) -> case erlang:element(4, State@2) >= Max_row of true -> case is_ansi_component(Piece@2, Options) of true -> {limit_state, erlang:element(2, State@2), <<(erlang:element(3, State@2))/binary, Piece@2/binary>>, erlang:element(4, State@2), erlang:element(5, State@2), erlang:element(6, State@2), erlang:element(7, State@2), erlang:element(8, State@2), erlang:element(9, State@2), erlang:element(10, State@2), erlang:element(11, State@2), erlang:element(12, State@2), erlang:element(13, State@2)}; false -> State@2 end; false -> case Piece@2 of <<"\n"/utf8>> -> State@3 = Commit(State@2, <<""/utf8>>, 0, false), {limit_state, <<<<(erlang:element(2, State@3))/binary, (erlang:element(3, State@3))/binary>>/binary, "\n"/utf8>>, <<""/utf8>>, erlang:element(4, State@3) + 1, 0, erlang:element(6, State@3), erlang:element(7, State@3), erlang:element(8, State@3), erlang:element(9, State@3), erlang:element(10, State@3), erlang:element(11, State@3), indent_unknown, false}; <<"\t"/utf8>> -> Curr_col = limit_state_col(State@2), Width@3 = case Curr_col =< erlang:element( 3, Max_size ) of true -> tab( Options, erlang:element(6, Options) + Curr_col ); false -> Wrapped_col = erlang:element(9, State@2) + erlang:element(11, State@2), tab( Options, erlang:element(6, Options) + Wrapped_col ) end, Commit(State@2, Piece@2, Width@3, false); <<" "/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{1680}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2000}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2001}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2002}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2003}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2004}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2005}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2006}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2008}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{2009}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{200a}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{205f}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{3000}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); <<"\x{ad}"/utf8>> -> Commit(State@2, Piece@2, Width@2, false); _ -> Push(State@2, Piece@2, Width@2) end end end ) end, State@5 = Commit(State@4, <<""/utf8>>, 0, true), <<(erlang:element(2, State@5))/binary, (erlang:element(3, State@5))/binary>>. -file("src/string_width.gleam", 459). ?DOC(" Like `limit`, but also customise the options used for measuring.\n"). -spec limit_with(binary(), size(), options(), binary()) -> binary(). limit_with(Str, Max_size, Options, Ellipsis) -> soft_wrap_with(Str, Max_size, Options, Ellipsis, fun(_) -> <<""/utf8>> end). -file("src/string_width.gleam", 1692). ?DOC( " collect a viewport/cutout of a string into a custom data structure.\n" " push is supposed to pad/align/etc however it sees fit.\n" " `stack_horizontal` uses this to collect all lines in parallel.\n" ). -spec view_fold( binary(), integer(), integer(), integer(), integer(), options(), EFF, fun((EFF, binary(), integer()) -> EFF) ) -> EFF. view_fold(Str, Top, Left, Bottom, Right, Options, Initial, Push) -> Total_height = gleam@int:max(0, Bottom - Top), Line_width_offset = gleam@int:max(0, Left), Push_line = fun(State) -> case (erlang:element(4, State) < Top) orelse (erlang:element(4, State) >= Bottom) of true -> {view_state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State) + 1, 0}; false -> Acc = Push( erlang:element(2, State), erlang:element(3, State), erlang:element(5, State) - Line_width_offset ), {view_state, Acc, <<""/utf8>>, erlang:element(4, State) + 1, 0} end end, Acc@1 = repeat( gleam@int:min(- Top, Total_height), Initial, fun(_capture) -> Push(_capture, <<""/utf8>>, 0) end ), State@2 = begin fold_raw( Str, Options, {view_state, Acc@1, <<""/utf8>>, 0, 0}, fun(State@1, Piece, Width) -> Width@1 = case Piece of <<"\t"/utf8>> -> tab( Options, erlang:element(5, State@1) + erlang:element( 6, Options ) ); _ -> Width end, case Piece of <<"\n"/utf8>> -> Push_line(State@1); _ -> case (((erlang:element(4, State@1) < Top) orelse (erlang:element( 4, State@1 ) >= Bottom)) orelse (erlang:element(5, State@1) < Left)) orelse (erlang:element(5, State@1) >= Right) of true -> case is_ansi_component(Piece, Options) of true -> {view_state, erlang:element(2, State@1), <<(erlang:element(3, State@1))/binary, Piece/binary>>, erlang:element(4, State@1), erlang:element(5, State@1)}; false -> {view_state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1) + Width@1} end; false -> {view_state, erlang:element(2, State@1), <<(erlang:element(3, State@1))/binary, Piece/binary>>, erlang:element(4, State@1), erlang:element(5, State@1) + Width@1} end end end ) end, Acc@2 = case (erlang:element(4, State@2) >= Top) andalso (erlang:element( 4, State@2 ) < Bottom) of true -> Push( erlang:element(2, State@2), erlang:element(3, State@2), erlang:element(5, State@2) - Line_width_offset ); false -> Push(erlang:element(2, State@2), erlang:element(3, State@2), -1) end, Missing_bottom = case erlang:element(5, State@2) >= Line_width_offset of true -> (Bottom - erlang:element(4, State@2)) - 1; false -> Bottom - erlang:element(4, State@2) end, repeat( gleam@int:min(Missing_bottom, Total_height), Acc@2, fun(_capture@1) -> Push(_capture@1, <<""/utf8>>, 0) end ). -file("src/string_width.gleam", 1560). ?DOC(" Like `stack_horizontal`, but using custom options for measure.\n"). -spec stack_horizontal_with( list(binary()), placement(), integer(), options(), binary() ) -> binary(). stack_horizontal_with(Blocks, Vertical, Gap, Options, Space) -> guard_list( Blocks, <<""/utf8>>, fun(First, Blocks@1) -> First_size = dimensions_with(First, Options), Measured = begin gleam@list:map( Blocks@1, fun(Block) -> {Block, dimensions_with(Block, Options)} end ) end, Height@1 = gleam@int:max( 1, begin gleam@list:fold( Measured, erlang:element(2, First_size), fun(Max, _use1) -> {_, {size, Height, _}} = _use1, gleam@int:max(Max, Height) end ) end ), Space_width = spacer_width(Options, Space), Gap_str = gleam@string:repeat(Space, div_up(Gap, Space_width)), Render = fun(Lines, Block@1, Size, Push_column) -> Push = fun(State, Line, Line_width) -> case State of {[Line_so_far | Rest_input], Output} -> Missing_right = div_up( erlang:element(3, Size) - Line_width, Space_width ), Padding_right = gleam@string:repeat( Space, Missing_right ), Line@1 = Push_column( Line_so_far, <> ), {Rest_input, [Line@1 | Output]}; _ -> State end end, Top = case Vertical of top -> 0; bottom -> erlang:element(2, Size) - Height@1; middle -> (erlang:element(2, Size) - Height@1) div 2 end, Bottom = Top + Height@1, Right = erlang:element(3, Size), {_, Formatted_lines} = view_fold( Block@1, Top, 0, Bottom, Right, Options, {Lines, []}, Push ), lists:reverse(Formatted_lines) end, Lines@1 = begin Render( gleam@list:repeat(<<""/utf8>>, Height@1), First, First_size, fun(_, Line@2) -> Line@2 end ) end, Lines@3 = begin gleam@list:fold( Measured, Lines@1, fun(Lines@2, _use1@1) -> {Block@2, Size@1} = _use1@1, Render( Lines@2, Block@2, Size@1, fun(Line_so_far@1, Line@3) -> <<<>/binary, Line@3/binary>> end ) end ) end, gleam@string:join(Lines@3, <<"\n"/utf8>>) end ). -file("src/string_width.gleam", 1665). ?DOC( " cutout a viewport of a string.\n" " the passed align function can pad the string to the right length, etc.\n" " `align` uses a different align function to box.\n" ). -spec view( binary(), integer(), integer(), integer(), integer(), options(), fun((binary(), integer()) -> binary()) ) -> binary(). view(Str, Top, Left, Bottom, Right, Options, Align) -> Push = fun(Buf, Line, Line_width) -> case Line_width >= 0 of true -> <<<>/binary, (Align(Line, Line_width))/binary>>; false -> <> end end, Result = view_fold( Str, Top, Left, Bottom, Right, Options, <<""/utf8>>, Push ), case Result of <<"\n"/utf8, Result@1/binary>> -> Result@1; _ -> Result end. -file("src/string_width.gleam", 1325). ?DOC(" Like `align`, bu use custom options for measure.\n"). -spec align_with(binary(), integer(), alignment(), options(), binary()) -> binary(). align_with(Str, Max_width, Alignment, Options, Space) -> Space_width = spacer_width(Options, Space), Str_size = dimensions_with(Str, Options), Bottom = gleam@int:max(1, erlang:element(2, Str_size)), Right = gleam@int:max(erlang:element(3, Str_size), Max_width), view( Str, 0, 0, Bottom, Right, Options, fun(Line, Line_width) -> Missing = div_up(Max_width - Line_width, Space_width), case Alignment of left -> <>; right -> <<(gleam@string:repeat(Space, Missing))/binary, Line/binary>>; center -> Left = Missing div 2, Right@1 = Missing - Left, <<<<(gleam@string:repeat(Space, Left))/binary, Line/binary>>/binary, (gleam@string:repeat(Space, Right@1))/binary>> end end ). -file("src/string_width.gleam", 1634). ?DOC( " cutout a viewport of a string in a rectangular manner, filling the remaining\n" " space with the spacer. Internal version of scroll or padding.\n" ). -spec box( binary(), integer(), integer(), integer(), integer(), options(), binary() ) -> binary(). box(Str, Top, Left, Height, Width, Options, Space) -> Space_width = spacer_width(Options, Space), Missing_left = div_up(gleam@int:max(0, - Left), Space_width), Padding_left = gleam@string:repeat(Space, Missing_left), Bottom = Top + Height, Right = Left + Width, view( Str, Top, Left, Bottom, Right, Options, fun(Line, Line_width) -> Missing_right = div_up( (Width - Missing_left) - Line_width, Space_width ), Padding_right = gleam@string:repeat(Space, Missing_right), <<<>/binary, Padding_right/binary>> end ). -file("src/string_width.gleam", 1260). ?DOC(" Like `position`, but use custom options to measure each line.\n"). -spec position_with( binary(), size(), alignment(), placement(), options(), binary() ) -> binary(). position_with(Str, Bounding_box, Alignment, Placement, Options, Space) -> Size = dimensions_with(Str, Options), Left = case Alignment of left -> 0; right -> gleam@int:min( erlang:element(3, Size) - erlang:element(3, Bounding_box), 0 ); center -> gleam@int:min( (erlang:element(3, Size) - erlang:element(3, Bounding_box)) div 2, 0 ) end, Top = case Placement of top -> 0; bottom -> gleam@int:min( erlang:element(2, Size) - erlang:element(2, Bounding_box), 0 ); middle -> gleam@int:min( (erlang:element(2, Size) - erlang:element(2, Bounding_box)) div 2, 0 ) end, Width = gleam@int:max( erlang:element(3, Size), erlang:element(3, Bounding_box) ), Height = gleam@int:max( erlang:element(2, Size), erlang:element(2, Bounding_box) ), box(Str, Top, Left, Height, Width, Options, Space). -file("src/string_width.gleam", 1397). ?DOC(" Like `padding`, but use custom options for measuring.\n"). -spec padding_with( binary(), integer(), integer(), integer(), integer(), options(), binary() ) -> binary(). padding_with(Str, Top, Right, Bottom, Left, Options, Space) -> Size = dimensions_with(Str, Options), Width = (erlang:element(3, Size) + Left) + Right, Height = (erlang:element(2, Size) + Top) + Bottom, box(Str, - Top, - Left, Height, Width, Options, Space). -file("src/string_width.gleam", 1449). ?DOC(" Like `scroll`, but provide custom options for measuring.\n"). -spec scroll_with(binary(), integer(), integer(), size(), options(), binary()) -> binary(). scroll_with(Str, Top, Left, Viewport_size, Options, Space) -> {size, Height, Width} = Viewport_size, box(Str, Top, Left, Height, Width, Options, Space). -file("src/string_width.gleam", 1490). ?DOC(" Like `stack_vertical`, but using custom options for measure.\n"). -spec stack_vertical_with( list(binary()), alignment(), integer(), options(), binary() ) -> binary(). stack_vertical_with(Blocks, Horizontal, Gap, Options, Space) -> guard_list( Blocks, <<""/utf8>>, fun(First, Blocks@1) -> First_size = dimensions_with(First, Options), Measured = begin gleam@list:map( Blocks@1, fun(Block) -> {Block, dimensions_with(Block, Options)} end ) end, Width@1 = begin gleam@list:fold( Measured, erlang:element(3, First_size), fun(Max, _use1) -> {_, {size, _, Width}} = _use1, gleam@int:max(Max, Width) end ) end, Space_width = spacer_width(Options, Space), Gap_line = gleam@string:repeat(Space, div_up(Width@1, Space_width)), Gap_str = gleam@string:repeat(<<"\n"/utf8, Gap_line/binary>>, Gap), Render = fun(Block@1, Size) -> Left = case Horizontal of left -> 0; right -> erlang:element(3, Size) - Width@1; center -> (erlang:element(3, Size) - Width@1) div 2 end, box( Block@1, 0, Left, erlang:element(2, Size), Width@1, Options, Space ) end, gleam@list:fold( Measured, Render(First, First_size), fun(Buf, _use1@1) -> {Block@2, Size@1} = _use1@1, <<<<<>/binary, "\n"/utf8>>/binary, (Render(Block@2, Size@1))/binary>> end ) end ). -file("src/string_width.gleam", 2053). ?DOC( " A version of `fold_raw` that does keep track of some state for you to\n" " handle tabs, and count the current row/column, passing `Piece` values to\n" " you instead.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " fold_raw_pieces(\"hi!\", using: new(), from: \"\", with: list.prepend)\n" " |> list.reverse\n" " // --> [Piece(\"h\", 0, 0, 1), Piece(\"i\", 0, 1, 1), Piece(\"!\", 0, 2, 1)]\n" " ```\n" ). -spec fold_raw_pieces(binary(), options(), EFQ, fun((EFQ, piece()) -> EFQ)) -> EFQ. fold_raw_pieces(String, Options, State, Fun) -> Ansi_ranges = case erlang:element(2, Options) of true -> []; false -> string_width@internal@ansi:match(String) end, {State@1, Fun@1} = piece_reducer(State, Options, Fun), On_chars = case erlang:element(4, Options) of mode_wcwidth -> fun(State@2, Str) -> fold_chars_raw(Options, Str, State@2, Fun@1) end; mode2027 -> fun(State@3, Str@1) -> fold_chars_2027(Options, Str@1, State@3, Fun@1) end; mode2027_ext -> fun(State@4, Str@2) -> fold_chars_2027_ext(Options, Str@2, State@4, Fun@1) end end, On_range = fun(State@5, Ansi, _) -> Fun@1(State@5, Ansi, 0) end, {State@6, _, _} = fold_parts( String, 0, Ansi_ranges, State@1, On_chars, On_range ), State@6. -file("src/string_width.gleam", 1206). ?DOC( " Like `tabs_to_spaces`, but customise the opttions as well.\n" "\n" " **NB:** You can use `at_tab_offset` and `with_tab_width` to change the measure of\n" " tab characters inside the string!\n" "\n" " ```gleam\n" " let options = new() |> with_tab_width(4)\n" " tabs_to_spaces_with(\"hi\\tcutie~\", options)\n" " // --> \"hi cutie~\"\n" " ```\n" ). -spec tabs_to_spaces_with(binary(), options()) -> binary(). tabs_to_spaces_with(Str, Options) -> fold_raw_pieces( Str, Options, <<""/utf8>>, fun(Acc, Piece) -> case erlang:element(2, Piece) of <<"\t"/utf8>> -> <>, erlang:element(5, Piece) ))/binary>>; _ -> <> end end ). -file("src/string_width.gleam", 183). ?DOC(" Start building up new options.\n"). -spec new() -> options(). new() -> {options, false, false, mode_wcwidth, 8, 0}. -file("src/string_width.gleam", 323). ?DOC( " Get the number of columns required to print a line in a terminal.\n" "\n" " If multiple lines are given, the length of the longest line is returned.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " line(\"Àâüè\")\n" " // --> 4\n" "\n" " line(\"μ•ˆλ…•ν•˜μ„Έμš”\")\n" " // --> 10\n" "\n" " line(\"πŸ‘©β€πŸ‘©β€πŸ‘¦β€πŸ‘¦\")\n" " // --> 8\n" "\n" " line(\"\\u{1B}[31mhello\\u{1B}[39m\")\n" " // --> 5\n" " ```\n" ). -spec line(binary()) -> integer(). line(Str) -> {size, _, Columns} = dimensions_with( Str, {options, false, false, mode_wcwidth, 8, 0} ), Columns. -file("src/string_width.gleam", 361). ?DOC( " The required number of rows and columns to display the given text.\n" "\n" " The number of rows is equal to the number of lines, while the number of\n" " columns represents the maximum line width.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " dimensions(\"μ•ˆλ…•ν•˜μ„Έμš”\")\n" " // --> Size(rows: 1, columns: 10)\n" "\n" " dimensions(\"hello,\\nμ•ˆλ…•ν•˜μ„Έμš”\")\n" " // --> Size(rows: 2, columns: 10)\n" " ```\n" ). -spec dimensions(binary()) -> size(). dimensions(Str) -> dimensions_with(Str, {options, false, false, mode_wcwidth, 8, 0}). -file("src/string_width.gleam", 449). ?DOC( " Limit the dimensions of a string, either by wrapping on white space\n" " characters or soft hyphens, or by truncating the last line and appending an\n" " ellipsis.\n" "\n" " The lines of the resulting string are left aligned and are at most `columns`\n" " wide. If a single word is longer than the maximum allowed line width, the\n" " word is broken into 2 pieces at the grapheme level. If the string gets\n" " truncated, this function will keep collecting ANSI sequences to make sure\n" " all formatting is preserved.\n" "\n" " A commonly used ellipsis character is `\"…\"`, also known as\n" " U+2026 HORIZONTAL ELLIPSIS.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " limit(\"Hello World\", Size(rows: 1, columns: 10), ellipsis: \"...\")\n" " // --> \"Hello W...\"\n" "\n" " limit(\"Hello World\", Size(rows: 2, columns: 10), ellipsis: \"...\")\n" " // --> \"Hello\\nWorld\"\n" " ```\n" ). -spec limit(binary(), size(), binary()) -> binary(). limit(Str, Max_size, Ellipsis) -> limit_with( Str, Max_size, {options, false, false, mode_wcwidth, 8, 0}, Ellipsis ). -file("src/string_width.gleam", 539). ?DOC( " Limit the dimensions of a string, either by wrapping on white space\n" " characters or soft hyphens while using a custom indentation function, or by\n" " truncating the last line and appending an ellipsis.\n" "\n" " This function gives a little bit more control over what happens on soft\n" " line breaks than `limit` and allows you to inspect the line printed so far\n" " to figure out the indentation for all soft-wrapped lines. The `to_indent`\n" " callback is called with the line so far, and should return an indentation\n" " string (usually just the proper amount of spaces) that is prepended to all\n" " the following soft-wrapped lines.\n" "\n" " Behaves like `limit` otherwise.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " fn to_indent(str) {\n" " case str {\n" " // if it is a list, indent with 2 spaces\n" " \"- \" <> _ -> \" \"\n" " // if it is a blockquote, prepend another blockquote marker\n" " \"> \" <> _ -> \"> \"\n" " // else, don't indent (like limit)\n" " _ -> \"\"\n" " }\n" " }\n" "\n" " // Girly Girl Productions - 10 drunk cigarettes\n" " let lyrics = \"\n" " > Getting girls rich, yeah, that's a part of my plan.\n" " > And I could name 10 things us girls need, before we ever need a man:\n" "\n" " - One new vape, two lines of coke\n" " - Three drinks from the bar, four more lines of coke\n" " - Five Guys fries, six hits from my blunt\n" " - Seven more lines of coke, eight pairs of shoes\n" " - Nine BB belts, and 10 drunk cigarettes.\n" " \"\n" "\n" " lyrics\n" " |> soft_wrap(to: Size(rows: 24, columns: 34), ellipsis: \"...\", to_indent:)\n" " |> io.println\n" " ```\n" "\n" " **Output:**\n" "\n" " ```txt\n" " > Getting girls rich, yeah, that's\n" " > a part of my plan.\n" " > And I could name 10 things us\n" " > girls need, before we ever need\n" " > a man:\n" "\n" " - One new vape, two lines of coke\n" " - Three drinks from the bar, four\n" " more lines of coke\n" " - Five Guys fries, six hits from\n" " my blunt\n" " - Seven more lines of coke, eight\n" " pairs of shoes\n" " - Nine BB belts, and 10 drunk\n" " cigarettes.\n" " ```\n" "\n" " **Note:** This is not meant to allow for arbitrary text formatting, but as a\n" " quick way to indicate soft-wrapping in the printed text. As shown in the\n" " example, it _can_ be used to do some very light formatting, but you should\n" " almost always parse the string first, and print it in a way that makes sense\n" " for your text format, for example using the awesome\n" " [glam](https://hexdocs.pm/glam/) package!\n" ). -spec soft_wrap(binary(), size(), binary(), fun((binary()) -> binary())) -> binary(). soft_wrap(Str, Max_size, Ellipsis, To_indent) -> soft_wrap_with( Str, Max_size, {options, false, false, mode_wcwidth, 8, 0}, Ellipsis, To_indent ). -file("src/string_width.gleam", 1191). ?DOC( " Replace all tab characters found in the string with the amount of spaces\n" " that this tab would have had otherwise.\n" "\n" " This makes it safe to prepend to a line, without changing the spacing produced\n" " by tabs anymore.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " tabs_to_spaces(\"Hello\\tWorld\")\n" " // --> \"Hello World\" // 3 spaces\n" " ```\n" ). -spec tabs_to_spaces(binary()) -> binary(). tabs_to_spaces(Str) -> tabs_to_spaces_with(Str, {options, false, false, mode_wcwidth, 8, 0}). -file("src/string_width.gleam", 1248). ?DOC( " Position the string area inside a bigger box without changing text alignment.\n" " The box will be filled with the space character.\n" "\n" " **Tip:** If you only want to align a string on one axis, you can provide\n" " `0` for the orthogonal one! Extra characters and lines will be kept.\n" "\n" " If the space strings' width does not evenly divide the missing amount of\n" " columns, the extra spacer will overflow the max width.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " position(\"X\", in: Size(3, 3), align: Center, place: Middle, with: \"o\")\n" " // --> \"ooo\\noXo\\nooo\"\n" "\n" " // text still left-aligned, but moved to the right by 1 space\n" " position(\"Trans\\nrights\\nare\\nhuman\\nrights\", Size(0, 7), Right, Top, \" \")\n" " // --> \" Trans \\n rights\\n are \\n human \\n rights\"\n" " ```\n" ). -spec position(binary(), size(), alignment(), placement(), binary()) -> binary(). position(Str, Bounding_box, Alignment, Placement, Space) -> position_with( Str, Bounding_box, Alignment, Placement, {options, false, false, mode_wcwidth, 8, 0}, Space ). -file("src/string_width.gleam", 1314). ?DOC( " Align each line horizontally, using a spacer character or string as a filler.\n" " Each line of the return value will be at least `max_width` wide.\n" "\n" " If a line is already longer than the max width, it will not be changed.\n" " If the space strings width does not evenly divide the missing amount of\n" " columns, the extra spacer will overflow the max width.\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " align(\"\", to: 5, align: Left, with: \"x\")\n" " // --> \"xxxxx\"\n" "\n" " align(\"hello\", to: 10, align: Left, with: \" \")\n" " // --> \"hello \"\n" "\n" " align(\"12345\", to: 8, align: Right, with: \"0\")\n" " // --> \"00012345\"\n" "\n" " align(\" Welcome \", to: 20, align: Center, with: \"==\")\n" " // --> \"====== Welcome ======\" // (len = 21)\n" "\n" " align(\"Trans\\nrights\\nare\\nhuman\\nrights\", to: 7, align: Right, with: \" \")\n" " // --> \" Trans\\n rights\\n are\\n human\\n rights\"\n" " ```\n" ). -spec align(binary(), integer(), alignment(), binary()) -> binary(). align(Str, Max_width, Alignment, Space) -> align_with( Str, Max_width, Alignment, {options, false, false, mode_wcwidth, 8, 0}, Space ). -file("src/string_width.gleam", 1378). ?DOC( " Add some padding around the box of a string, filling empty space and the\n" " padded area with the provided character.\n" "\n" " Padding is given as a number of rows/columns. Values are given clockwise,\n" " following the CSS shorthand property.\n" "\n" " Ansi sequences will always be kept. If the space strings' width does not\n" " evenly divide the missing area in the computed outer size of the string,\n" " the extra spacer will the resulting lines may not all be equally long.\n" "\n" " **Tip:** Provide negative values to drop columns or rows!\n" "\n" " ### Examples\n" "\n" " ```gleam\n" " padding(\"o\", 1, 1, 1, 1, with: \"x\")\n" " // --> \"xxx\\nxox\\nxxx\"\n" "\n" " padding(\"hello\", 0, 0, 0, right: -1, with: \"\")\n" " // --> \"hell\"\n" "\n" " padding(\"Trans\\nrights!\", top: 2, right: 5, bottom: 1, left: 1, with: \"-\")\n" " // --> \"-------------\\n-------------\\n-Trans-------\\n-rights!-----\\n-------------\"\n" " ```\n" ). -spec padding(binary(), integer(), integer(), integer(), integer(), binary()) -> binary(). padding(Str, Top, Right, Bottom, Left, Space) -> Options = {options, false, false, mode_wcwidth, 8, 0}, Size = dimensions_with(Str, Options), Width = (erlang:element(3, Size) + Left) + Right, Height = (erlang:element(2, Size) + Top) + Bottom, box(Str, - Top, - Left, Height, Width, Options, Space). -file("src/string_width.gleam", 1435). ?DOC( " Cut out a `viewort` at the given origin `#(top, left)` from a string. This\n" " is similar to _\"scrolling\"_ a web page.\n" "\n" " You can scroll past the filled area of the string in any direction.\n" " Empty space is filled using the `space` string. If the space string does not\n" " evenly fill the empty area, some lines may be longer than the given viewport.\n" "\n" " All ANSI sequences in the entire string will be kept, even if they are\n" " outside of the visible viewport.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " scroll(\"wibble\", top: 0, left: 2, view: Size(1, 2), with: \" \")\n" " // --> \"bb\"\n" "\n" " \"Hello\\nHow are you today?\\nDid you know:\\nLucy says trans rights!\"\n" " |> scroll(top: 2, left: 10, view: Size(3, 5), with: \"-\")\n" " // --> \"ow:--\\ntrans\\n-----\"\n" " ```\n" ). -spec scroll(binary(), integer(), integer(), size(), binary()) -> binary(). scroll(Str, Top, Left, Viewport_size, Space) -> Options = {options, false, false, mode_wcwidth, 8, 0}, {size, Height, Width} = Viewport_size, box(Str, Top, Left, Height, Width, Options, Space). -file("src/string_width.gleam", 1479). ?DOC( " Stack multiple blocks of strings on top of each other into multiple rows.\n" "\n" " The resulting string will as wide as the widest string in the list. All other\n" " blocks can be `position`-ed horizontally relative to this size.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " [\n" " \"Hello!\",\n" " \"I hope you are feeling fantastic today!\"\n" " ]\n" " |> stack_vertical(Center, gap: 1, with: \" \")\n" " // --> \" Hello! \\n\"\n" " // <> \" \\n\"\n" " // <> \"I hope you are feeling fantastic today!\"\n" " ```\n" ). -spec stack_vertical(list(binary()), alignment(), integer(), binary()) -> binary(). stack_vertical(Blocks, Horizontal, Gap, Space) -> stack_vertical_with( Blocks, Horizontal, Gap, {options, false, false, mode_wcwidth, 8, 0}, Space ). -file("src/string_width.gleam", 1549). ?DOC( " Stack multiple blocks of strings horizontally next to each other into\n" " multiple columns.\n" "\n" " The resulting string will as high as the highest string in the list. All\n" " other blocks can be `position`-ed vertically relative to this size.\n" "\n" " **Tip;** Use [limit](#limit) and [inline_styles](#inline_styles) to lay out\n" " the text in your columns!\n" "\n" " ### Example\n" "\n" " ```gleam\n" " [\n" " \"--color\",\n" " \"Enable color support.\\nThis option is enabled by default in a terminal.\"\n" " ]\n" " |> stack_horizontal(place: Top, gap: 4, with: \" \")\n" " // --> \"--color Enable color support. \\n\"\n" " // <> \" This option is enabled by default in a terminal.\"\n" " ```\n" ). -spec stack_horizontal(list(binary()), placement(), integer(), binary()) -> binary(). stack_horizontal(Blocks, Vertical, Gap, Space) -> stack_horizontal_with( Blocks, Vertical, Gap, {options, false, false, mode_wcwidth, 8, 0}, Space ). -file("src/string_width.gleam", 1937). ?DOC( " A higher-level `fold` that keeps track of the position inside of the string.\n" "\n" " Handles tabs and newlines, and always passes full grapheme clusters,\n" " regardless of options. Concatenating the graphemes produces the original string.\n" "\n" " Intended to be used as a basis for custom layout algorithms.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " fold(\"hi 😊\", from: [], with: list.prepend)\n" " |> list.reverse\n" " // --> [Piece(\"h\", 0, 0, 1), Piece(\"i\", 0, 1, 1), Piece(\" \", 0, 2, 1), Piece(\"😊\", 0, 3, 2)]\n" " ```\n" ). -spec fold(binary(), EFN, fun((EFN, piece()) -> EFN)) -> EFN. fold(Str, State, Fun) -> fold_with(Str, {options, false, false, mode_wcwidth, 8, 0}, State, Fun).