-module(string_width_ffi). -export([fold_bytes/3, fold_codepoints/3, utf_codepoint_to_string/1, get_terminal_size/0, is_tty/0]). fold_bytes(<>, State, Fun) -> fold_bytes(Rest, Fun(State, Byte), Fun); fold_bytes(_Binary, State, _Fun) -> State. fold_codepoints(<>, State, Fun) -> fold_codepoints(Rest, Fun(State, Cp), Fun); fold_codepoints(_Binary, State, _Fun) -> State. utf_codepoint_to_string(Cp) -> <>. get_terminal_size() -> case {io:rows(), io:columns()} of {{ok, Rows}, {ok, Cols}} -> {ok, {Rows, Cols}}; _ -> case {os:getenv("LINES"), os:getenv("COLUMNS")} of {false, _} -> {error, nil}; {_, false} -> {error, nil}; {LinesStr, ColumnsStr} -> case catch {list_to_integer(LinesStr), list_to_integer(ColumnsStr)} of {EnvRows, EnvCols} when is_integer(EnvRows) andalso is_integer(EnvCols) -> {ok, {EnvRows, EnvCols}}; _ -> {error, nil} end end end. is_tty() -> case io:columns() of {ok, _} -> % Check io:getopts for stdin, stdout, and terminal flags Opts = io:getopts(), HasStdin = proplists:get_value(stdin, Opts, false), HasStdout = proplists:get_value(stdout, Opts, false), IsDumb = os:getenv("TERM") == "DUMB", HasStdin and HasStdout and not IsDumb; {error, _} -> false end.