You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

775 lines
29 KiB

-module(eFmt).
-compile(inline).
-compile({inline_size, 128}).
-include("eFmt.hrl").
-export([
%% eFmt
format/2
, format/3
, scan/2
, build/1
, build/2
, print/1
, print/4
, write/1
, write/2
, write/3
, write/4
%% eFmtformat
, fWrite/2
, fWrite/3
, fScan/2
, fBuild/1
, fBuild/2
%% eFmtPretty
%% utils
, toLowerStr/1
, toUpperStr/1
, toBinary/1
, charsLen/1
]).
%% ********************************************** eFmt start ***********************************************************
-type chars() :: [char() | chars() | binary()].
-type depth() :: -1 | non_neg_integer().
-type encoding() :: epp:source_encoding() | 'unicode'.
-type charsLimit() :: integer().
-type fmtSpec() :: #fmtSpec{}.
-spec format(Format :: io:format(), Data :: [term()]) -> chars().
format(Format, Args) ->
try fWrite(Format, Args)
catch
_C:_R ->
erlang:error(badarg, [Format, Args])
end.
-spec format(Format :: io:format(), Data :: [term()], Options :: [{charsLimit, CharsLimit :: charsLimit()}]) -> chars().
format(Format, Args, Options) ->
try fWrite(Format, Args, Options)
catch
_C:_R ->
erlang:error(badarg, [Format, Args])
end.
-spec scan(Format :: io:format(), Data :: [term()]) -> FormatList :: [char() | fmtSpec()].
scan(Format, Args) ->
try fScan(Format, Args)
catch
_C:_R ->
erlang:error(badarg, [Format, Args])
end.
-spec build(FormatList :: [char() | fmtSpec()]) -> chars().
build(FormatList) ->
try fBuild(FormatList)
catch
_C:_R ->
erlang:error(badarg, [FormatList])
end.
-spec build(FormatList :: [char() | fmtSpec()], Options :: [{charsLimit, CharsLimit :: charsLimit()}]) -> chars().
build(FormatList, Options) ->
try fBuild(FormatList, Options)
catch
_C:_R ->
erlang:error(badarg, [FormatList, Options])
end.
-spec print(Term :: term()) -> chars().
print(Term) ->
eFmtPretty:pPrint(Term).
-spec print(Term :: term(), Column :: non_neg_integer(), LineLength :: non_neg_integer(), Depth :: depth()) -> chars().
print(Term, Column, LineLength, Depth) ->
eFmtPretty:pPrint(Term, Column, LineLength, Depth).
-spec write(Term :: term()) -> chars().
write(Term) ->
writeTerm(Term, -1, latin1).
-spec write(Term :: term(), Depth :: depth()) -> chars().
write(Term, Depth) ->
writeTerm(Term, Depth, latin1).
-spec write(Term :: term(), Depth :: depth(), IsPretty :: boolean()) -> chars().
write(Term, Depth, IsPretty) ->
case IsPretty of
true ->
eFmtPretty:pPrint(Term, 1, 80, Depth);
_ ->
writeTerm(Term, Depth, latin1)
end.
-spec write(Term :: term(), Depth :: depth(), Encoding :: encoding(), CharsLimit :: charsLimit()) -> chars().
write(Term, Depth, Encoding, CharsLimit) ->
if
Depth =:= 0 orelse CharsLimit =:= 0 ->
<<"...">>;
CharsLimit < 0 ->
writeTerm(Term, Depth, Encoding);
true ->
RecDefFun = fun(_, _) -> no end,
If = eFmtPretty:pIntermediate(Term, Depth, CharsLimit, RecDefFun, Encoding, _Str = false),
eFmtPretty:pWrite(If)
end.
-define(writeInt(Int), integer_to_binary(Term)).
-define(writeFloat(Float), floatG(Term)).
-define(writeAtom(Atom, Encoding), <<"'", (atom_to_binary(Atom, Encoding))/binary, "'">>).
-define(writePort(Port), list_to_binary(erlang:port_to_list(Port))).
-define(writeRef(Ref), list_to_binary(erlang:ref_to_list(Ref))).
-define(writePid(Ref), list_to_binary(erlang:pid_to_list(Ref))).
-define(writeFun(Fun), list_to_binary(erlang:fun_to_list(Fun))).
writeList([], _D, _E, BinAcc) ->
<<BinAcc/binary, "]">>;
writeList([One], D, E, BinAcc) ->
<<BinAcc/binary, (writeTerm(One, D, E))/binary, "]">>;
writeList([One | List], D, E, BinAcc) ->
if
D =:= 1 -> <<BinAcc, "|...]">>;
true ->
writeList(List, D - 1, E, <<BinAcc/binary, (writeTerm(One, D, E))/binary, ",">>)
end;
writeList(Other, D, E, BinAcc) ->
<<BinAcc/binary, "|", (writeTerm(Other, D, E))/binary, "]">>.
writeTuple(Tuple, D, E, Index, TupleSize, BinAcc) ->
if
D =:= 1 -> <<BinAcc/binary, "...}">>;
true ->
if
Index < TupleSize ->
writeTuple(Tuple, D - 1, E, Index + 1, TupleSize, <<BinAcc/binary, (writeTerm(element(Index, Tuple), D - 1, E))/binary, ",">>);
Index == TupleSize ->
<<BinAcc/binary, (writeTerm(element(Index, Tuple), D - 1, E))/binary, "}">>;
true ->
<<BinAcc/binary, "}">>
end
end.
writeMap(Map, D, E, BinAcc) when is_integer(D) ->
if
D =:= 1 ->
<<BinAcc/binary, "...}">>;
true ->
writeMapBody(maps:iterator(Map), D, E, BinAcc)
end.
writeMapBody(I, D, E, BinAcc) ->
if
D =:= 1 ->
<<BinAcc/binary, " ...}">>;
true ->
case maps:next(I) of
{K, V, none} ->
<<BinAcc/binary, (writeTerm(K, -1, E))/binary, " => ", (writeTerm(V, D, E))/binary, "}">>;
{K, V, NextI} ->
writeMapBody(NextI, D - 1, E, <<BinAcc/binary, (writeTerm(K, -1, E))/binary, " => ", (writeTerm(V, D, E))/binary, ",">>);
none ->
<<BinAcc/binary, "}">>
end
end.
writeBinary(Bin, D, BinAcc) ->
if
D == 1 ->
<<BinAcc/binary, "...>>">>;
true ->
case Bin of
<<>> ->
<<BinAcc/binary, ">>">>;
<<Int:8>> ->
<<BinAcc/binary, (integer_to_binary(Int))/binary, ">>">>;
<<Int:8, LeftBin/bitstring>> ->
writeBinary(LeftBin, D - 1, <<BinAcc/binary, (integer_to_binary(Int))/binary, ",">>);
_ ->
L = bit_size(Bin),
<<X:L>> = Bin,
<<BinAcc/binary, (integer_to_binary(X))/binary, ":", (integer_to_binary(L))/binary, ">>">>
end
end.
writeTerm(_Term, 0, _E) -> <<"...">>;
writeTerm(Term, _D, _E) when is_integer(Term) -> ?writeInt(Term);
writeTerm(Atom, _D, E) when is_atom(Atom) -> ?writeAtom(Atom, E);
writeTerm(Term, D, E) when is_list(Term) -> writeList(Term, D, E, <<"[">>);
writeTerm(Term, D, E) when is_map(Term) -> writeMap(Term, D, E, <<"#{">>);
writeTerm(Term, D, E) when is_tuple(Term) -> writeTuple(Term, D, E, 1, tuple_size(Term), <<"{">>);
writeTerm(Term, D, _E) when is_bitstring(Term) -> writeBinary(Term, D, <<"<<">>);
writeTerm(Term, _D, _E) when is_pid(Term) -> ?writePid(Term);
writeTerm(Term, _D, _E) when is_float(Term) -> ?writeFloat(Term);
writeTerm(Term, _D, _E) when is_port(Term) -> ?writePort(Term);
writeTerm(Term, _D, _E) when is_reference(Term) -> ?writeRef(Term);
writeTerm(Term, _D, _E) when is_function(Term) -> ?writeFun(Term).
%% ********************************************** eFmt end *************************************************************
%% ********************************************** eFmtFormat start *****************************************************
-spec fWrite(Format :: io:format(), Data :: [term()]) -> chars().
fWrite(Format, Args) ->
fBuild(fScan(Format, Args), []).
-spec fWrite(Format :: io:format(), Data :: [term()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> chars().
fWrite(Format, Args, Options) ->
fBuild(fScan(Format, Args), Options).
%% Parse all control sequences in the format string.
-spec fScan(Format :: io:format(), Data :: [term()]) -> FormatList :: [char() | fmtSpec()].
%% 格式 ~F.P.PadModC
fScan(Format, Args) ->
if
is_atom(Format) ->
doCollect(atom_to_binary(Format, utf8), Args, []);
is_list(Format) ->
doCollect(list_to_binary(Format), Args, []);
true ->
doCollect(Format, Args, [])
end.
doCollect(FmtBinStr, Args, Acc) ->
case binary:split(FmtBinStr, <<"~">>) of
[NotMatch] ->
[NotMatch | Acc];
[FPart, LPart] ->
doCollWidth(LPart, Args, 0, right, [FPart | Acc])
end.
doCollWidth(<<>>, _Args, _Width, _Adjust, Acc) ->
Acc;
doCollWidth(LPart, Args, Width, Adjust, Acc) ->
case LPart of
<<"-*", LeftLPart/binary>> ->
[WidthArgs | LeftArgs] = Args,
doCollPrecision(LeftLPart, LeftArgs, WidthArgs, left, Acc);
<<"-", LeftLPart/binary>> ->
doCollWidth(LeftLPart, Args, Width, left, Acc);
<<"*", LeftLPart/binary>> ->
[WidthArgs | LeftArgs] = Args,
doCollPrecision(LeftLPart, LeftArgs, WidthArgs, right, Acc);
<<WidthInt:8/integer, LeftLPart/binary>> ->
case WidthInt >= $0 andalso WidthInt =< $9 of
true ->
doCollWidth(LeftLPart, Args, 10 * Width + (WidthInt - $0), Adjust, Acc);
_ ->
case Width == 0 of
true ->
doCollPrecision(LPart, Args, none, left, Acc);
_ ->
doCollPrecision(LPart, Args, Width, Adjust, Acc)
end
end
end.
doCollPrecision(LPart, Args, Width, Adjust, Acc) ->
case LPart of
<<".", LeftLPart/binary>> ->
doCollPrecision(LeftLPart, Args, Width, Adjust, 0, Acc);
_ ->
doCollPadChar(LPart, Args, Width, Adjust, none, Acc)
end.
doCollPrecision(LPart, Args, Width, Adjust, Precision, Acc) ->
case LPart of
<<"*", LeftLPart/binary>> ->
[PrecisionArgs | LeftArgs] = Args,
doCollPadChar(LeftLPart, LeftArgs, Width, Adjust, PrecisionArgs, Acc);
<<PrecisionInt:8/integer, LeftLPart/binary>> ->
case PrecisionInt >= $0 andalso PrecisionInt =< $9 of
true ->
doCollPrecision(LeftLPart, Args, Width, Adjust, 10 * Precision + (PrecisionInt - $0), Acc);
_ ->
case Precision == 0 of
true ->
doCollPadChar(LPart, Args, Width, Adjust, none, Acc);
_ ->
doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc)
end
end
end.
doCollPadChar(LPart, Args, Width, Adjust, Precision, Acc) ->
case LPart of
<<".*", LeftLPart/binary>> ->
[PadChar | LeftArgs] = Args,
doCollEncoding(LeftLPart, LeftArgs, Width, Adjust, Precision, PadChar, Acc);
<<".", PadChar:8/integer, LeftLPart/binary>> ->
doCollEncoding(LeftLPart, Args, Width, Adjust, Precision, PadChar, Acc);
_ ->
doCollEncoding(LPart, Args, Width, Adjust, Precision, 32, Acc)
end.
doCollEncoding(LPart, Args, Width, Adjust, Precision, PadChar, Acc) ->
case LPart of
<<"t", LeftLPart/binary>> ->
%true = Char =/= $l,
doCollStrings(LeftLPart, Args, Width, Adjust, Precision, PadChar, unicode, Acc);
_ ->
doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, latin1, Acc)
end.
doCollStrings(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Acc) ->
case LPart of
<<"l", LeftLPart/binary>> ->
%true = Char =/= $t,
doCollCA(LeftLPart, Args, Width, Adjust, Precision, PadChar, Encoding, false, Acc);
_ ->
doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, true, Acc)
end.
doCollCA(LPart, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, Acc) ->
<<CtlChar:8/integer, LeftLPart/binary>> = LPart,
case CtlChar of
$w -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$p -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$W -> [OneArgs | LeftArgs] = Args, [Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs;
$P -> [OneArgs | LeftArgs] = Args, [Depth | LastArgs] = LeftArgs, As = [OneArgs, Depth], NextArgs = LastArgs;
$s -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$e -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$f -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$g -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$b -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$B -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$x -> [OneArgs | LeftArgs] = Args, [Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs;
$X -> [OneArgs | LeftArgs] = Args, [Prefix | LastArgs] = LeftArgs, As = [OneArgs, Prefix], NextArgs = LastArgs;
$+ -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$# -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$c -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs;
$~ -> As = undefined, NextArgs = Args;
$n -> As = undefined, NextArgs = Args;
$i -> [OneArgs | LeftArgs] = Args, As = OneArgs, NextArgs = LeftArgs
end,
FmtSpec = #fmtSpec{ctlChar = CtlChar, args = As, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding, strings = Strings},
doCollect(LeftLPart, NextArgs, [FmtSpec | Acc]).
%% Build the output text for a pre-parsed format list.
-spec fBuild(FormatList :: [char() | fmtSpec()]) -> chars().
fBuild(Cs) ->
fBuild(Cs, []).
-spec fBuild(FormatList :: [char() | fmtSpec()], Options :: [{'chars_limit', CharsLimit :: integer()}]) -> chars().
fBuild(Cs, Options) ->
CharsLimit = getOpt(chars_limit, Options, -1),
ResList = buildSmall(Cs, []),
{P, S, W, Other} = cntSmall(ResList, 0, 0, 0, 0),
NumOfLimited = P + S + W,
case NumOfLimited of
0 ->
ResList;
_ ->
RemainChars = remainChars(CharsLimit, Other),
buildLimited(ResList, P, NumOfLimited, RemainChars, 0, [])
end.
buildSmall([], Acc) -> Acc;
buildSmall([OneCA | Cs], Acc) ->
case OneCA of
#fmtSpec{ctlChar = CtlChar, args = Args, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding} ->
case ctlSmall(CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding) of
not_small -> buildSmall(Cs, [OneCA | Acc]);
ignore -> buildSmall(Cs, Acc);
Str -> buildSmall(Cs, [Str | Acc])
end;
_ ->
buildSmall(Cs, [OneCA | Acc])
end.
ctlSmall($s, Args, Width, Adjust, Precision, PadChar, Encoding) when is_atom(Args) ->
case Encoding of
latin1 ->
AtomBinStr = ?writeAtom(Args, latin1);
_ ->
AtomBinStr = ?writeAtom(Args, uft8)
end,
string(AtomBinStr, Width, Adjust, Precision, PadChar, Encoding);
ctlSmall($e, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
floatE(Args, Width, Adjust, Precision, PadChar);
ctlSmall($f, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
floatF(Args, Width, Adjust, Precision, PadChar);
ctlSmall($g, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_float(Args) ->
floatG(Args, Width, Adjust, Precision, PadChar);
ctlSmall($b, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
unPrefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, true);
ctlSmall($B, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
unPrefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, false);
ctlSmall($x, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args), is_atom(Prefix) ->
prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_binary(Prefix, utf8), true);
ctlSmall($x, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, Prefix, true);
ctlSmall($X, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args), is_atom(Prefix) ->
prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, atom_to_binary(Prefix, utf8), false);
ctlSmall($X, [Args, Prefix], Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
prefixedInt(Args, Width, Adjust, ?base(Precision), PadChar, Prefix, false);
ctlSmall($+, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
Base = ?base(Precision),
prefixedInt(Args, Width, Adjust, Base, PadChar, integer_to_binary(Base), $#, true);
ctlSmall($#, Args, Width, Adjust, Precision, PadChar, _Encoding) when is_integer(Args) ->
Base = ?base(Precision),
prefixedInt(Args, Width, Adjust, Base, PadChar, integer_to_binary(Base), $#, false);
ctlSmall($c, Args, Width, Adjust, Precision, PadChar, Encoding) when is_integer(Args) ->
case Encoding of
unicode ->
char(Args, Width, Adjust, Precision, PadChar);
_ ->
char(Args band 255, Width, Adjust, Precision, PadChar)
end;
ctlSmall($~, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> char($~, Width, Adjust, Precision, PadChar);
ctlSmall($n, _Args, Width, Adjust, Precision, PadChar, _Encoding) -> newline(Width, Adjust, Precision, PadChar);
ctlSmall($i, _Args, _Width, _Adjust, _Precision, _PadChar, _Encoding) -> ignore;
ctlSmall(_C, _Args, _Width, _Adjust, _Precision, _PadChar, _Encoding) -> not_small.
cntSmall([], P, S, W, Other) ->
{P, S, W, Other};
cntSmall([OneRes | Cs], P, S, W, Other) ->
case OneRes of
#fmtSpec{ctlChar = CtlChar} ->
case CtlChar of
$p ->
cntSmall(Cs, P + 1, S, W, Other);
$P ->
cntSmall(Cs, P + 1, S, W, Other);
$w ->
cntSmall(Cs, P, S, W + 1, Other);
$W ->
cntSmall(Cs, P, S, W + 1, Other);
$s ->
cntSmall(Cs, P, S, W + 1, Other);
_ ->
cntSmall(Cs, P, S, W, Other)
end;
_ ->
if
is_binary(OneRes) orelse is_list(OneRes) ->
cntSmall(Cs, P, S, W, Other + charsLen(OneRes));
is_integer(OneRes) ->
cntSmall(Cs, P, S, W, Other + 1);
true ->
cntSmall(Cs, P, S, W, Other)
end
end.
buildLimited([], _, _, _, _, Acc) -> Acc;
buildLimited([OneCA | Cs], NumOfPs, Count, MaxLen, I, Acc) ->
case OneCA of
#fmtSpec{ctlChar = CtlChar, args = Args, width = Width, adjust = Adjust, precision = Precision, padChar = PadChar, encoding = Encoding, strings = Strings} ->
MaxChars = if MaxLen < 0 -> MaxLen; true -> MaxLen div Count end,
IoListStr = ctlLimited(CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, MaxChars, I),
NewNumOfPs = decrPc(CtlChar, NumOfPs),
NewCount = Count - 1,
MaxLen = ?IIF(MaxLen < 0, MaxLen, remainChars(MaxLen, charsLen(IoListStr))),
if
NewNumOfPs > 0 ->
buildLimited(Cs, NewNumOfPs, NewCount, MaxLen, I, [IoListStr | Acc]);
true ->
buildLimited(Cs, NewNumOfPs, NewCount, MaxLen, I, [IoListStr | Acc])
end;
_ ->
buildLimited(Cs, NumOfPs, Count, MaxLen, I + 1, [OneCA | Acc])
end.
decrPc($p, Pc) -> Pc - 1;
decrPc($P, Pc) -> Pc - 1;
decrPc(_, Pc) -> Pc.
%% (CtlChar, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, MaxChars, I)
ctlLimited($s, Args, Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
case Encoding of
latin1 ->
BinStr = erlang:iolist_to_binary(Args);
_ ->
BinStr = case catch unicode:characters_to_binary(Args, unicode) of
Str when is_binary(Str) -> Str;
_ -> toBinary(Args)
end
end,
TemBinStr = strToChars(BinStr, Width, CharsLimit),
string(TemBinStr, ?IIF(CharsLimit < 0 orelse Width =:= none, Width, max(3, min(Width, CharsLimit))), Adjust, Precision, PadChar, Encoding);
ctlLimited($w, Args, Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
Chars = write(Args, -1, Encoding, CharsLimit),
term(Chars, Width, Adjust, Precision, PadChar);
ctlLimited($p, Args, Width, Adjust, Precision, PadChar, Encoding, Strings, CharsLimit, I) ->
print(Args, -1, Width, Adjust, Precision, PadChar, Encoding, Strings, CharsLimit, I);
ctlLimited($W, [Args, Depth], Width, Adjust, Precision, PadChar, Encoding, _Strings, CharsLimit, _I) ->
Chars = write(Args, Depth, Encoding, CharsLimit),
term(Chars, Width, Adjust, Precision, PadChar);
ctlLimited($P, [Args, Depth], Width, Adjust, Precision, PadChar, Encoding, Strings, CharsLimit, I) ->
print(Args, Depth, Width, Adjust, Precision, PadChar, Encoding, Strings, CharsLimit, I).
term(BinStrOrIoList, Width, Adjust, Precision, PadChar) ->
if
Width == none andalso Precision == none ->
BinStrOrIoList;
Width == none ->
StrLen = charsLen(BinStrOrIoList),
NewPrecision = erlang:min(StrLen, Precision),
if
StrLen > NewPrecision ->
adjust(Adjust, makePadChars($*, NewPrecision, <<>>), <<>>);
true ->
adjust(Adjust, BinStrOrIoList, makePadChars(PadChar, Precision - StrLen, <<>>))
end;
true ->
StrLen = charsLen(BinStrOrIoList),
NewPrecision = erlang:min(StrLen, case Precision of none -> Width; _ -> min(Precision, Width) end),
if
StrLen > NewPrecision ->
adjust(Adjust, makePadChars($*, NewPrecision, <<>>), makePadChars(PadChar, Width - NewPrecision, <<>>));
true ->
adjust(Adjust, BinStrOrIoList, makePadChars(PadChar, Width - StrLen, <<>>))
end
end.
print(Term, Depth, Width, _Adjust, Precision, _PadChar, Encoding, Strings, CharsLimit, I) ->
if
Width == none -> NewWidth = 80;
true -> NewWidth = Width
end,
if
Precision == none -> NewPrecision = I + 1;
true -> NewPrecision = Precision
end,
eFmtPretty:print(Term, NewPrecision, NewWidth, Depth, -1, CharsLimit, no_fun, Encoding, Strings).
floatE(Float, Width, Adjust, Precision, PadChar) ->
case Precision of
none ->
NewPrecision = 6;
_ ->
NewPrecision = Precision
end,
case Width of
none ->
float_to_binary(Float, [{scientific, NewPrecision}]);
_ ->
term(float_to_binary(Float, [{scientific, NewPrecision}]), Width, Adjust, Width, PadChar)
end.
floatF(Float, Width, Adjust, Precision, PadChar) ->
case Precision of
none ->
NewPrecision = 6;
_ ->
NewPrecision = Precision
end,
case Width of
none ->
float_to_binary(Float, [{decimals, NewPrecision}]);
_ ->
term(float_to_binary(Float, [{decimals, NewPrecision}]), Width, Adjust, Width, PadChar)
end.
floatG(Float, Width, Adjust, Precision, PadChar) ->
case Float > -10000.0 andalso Float < 10000.0 of
true ->
floatF(Float, Width, Adjust, Precision, PadChar);
_ ->
floatE(Float, Width, Adjust, Precision, PadChar)
end.
floatG(Float) ->
float_to_binary(Float, [{decimals, 6}]).
strToChars(BinStr, Width, CharsLimit) ->
ByteSize = byte_size(BinStr),
if
Width == none ->
case CharsLimit < 0 orelse CharsLimit >= ByteSize of
true ->
BinStr;
_ ->
<<(binary:part(BinStr, 0, CharsLimit))/binary, "...">>
end;
CharsLimit < 0 orelse CharsLimit >= Width ->
BinStr;
true ->
<<(binary:part(BinStr, 0, CharsLimit))/binary, "...">>
end.
string(Str, Width, Adjust, Precision, PadChar, Encoding) ->
if
Width == none andalso Precision == none ->
Str;
Precision == none ->
strField(Str, Width, Adjust, charsLen(Str), PadChar, Encoding);
Width == none ->
strField(Str, Precision, left, charsLen(Str), PadChar, Encoding);
true ->
StrLen = charsLen(Str),
if
Width > Precision ->
if StrLen > Precision ->
adjust(Adjust, flatTrunc(Str, Precision, Encoding), makePadChars(PadChar, Width - Precision, <<>>));
StrLen < Precision ->
adjust(Adjust, [Str | makePadChars(PadChar, Precision - StrLen, <<>>)], makePadChars(PadChar, Width - Precision, <<>>));
true -> % N == P
adjust(Adjust, Str, makePadChars(PadChar, Width - Precision, <<>>))
end;
true -> % F == P
strField(Str, Width, Adjust, StrLen, PadChar, Encoding)
end
end.
strField(Str, Width, Adjust, StrLen, PadChar, Encoding) when StrLen > Width ->
if
StrLen > Width ->
flatTrunc(Str, Width, Encoding);
StrLen < Width ->
adjust(Adjust, Str, makePadChars(PadChar, Width - StrLen, <<>>));
true ->
Str
end.
flatTrunc(List, Width, _Encoding) ->
binary:part(iolist_to_binary(List), 0, Width).
makePadChars(PadChar, Cnt, BinStr) ->
case Cnt > 0 of
true ->
makePadChars(PadChar, Cnt - 1, <<BinStr/binary, PadChar:8>>);
_ ->
BinStr
end.
adjust(left, Data, Pad) -> [Data, Pad];
adjust(right, Data, Pad) -> [Pad, Data].
unPrefixedInt(Int, Width, Adjust, Base, PadChar, Lowercase) ->
case Lowercase of
true ->
term(toLowerStr(integer_to_binary(Int, Base)), Width, Adjust, none, PadChar);
_ ->
term(integer_to_binary(Int, Base), Width, Adjust, none, PadChar)
end.
prefixedInt(Int, Width, Adjust, Base, PadChar, Prefix, Lowercase) ->
case Int < 0 of
true ->
case Lowercase of
true ->
term(<<"-", (toBinary(Prefix))/binary, (toLowerStr(integer_to_binary(-Int, Base)))/binary>>, Width, Adjust, none, PadChar);
_ ->
term(<<"-", (toBinary(Prefix))/binary, (integer_to_binary(-Int, Base))/binary>>, Width, Adjust, none, PadChar)
end;
_ ->
case Lowercase of
true ->
term(<<(toBinary(Prefix))/binary, (toLowerStr(integer_to_binary(Int, Base)))/binary>>, Width, Adjust, none, PadChar);
_ ->
term(<<(toBinary(Prefix))/binary, (integer_to_binary(Int, Base))/binary>>, Width, Adjust, none, PadChar)
end
end.
prefixedInt(Int, Width, Adjust, Base, PadChar, Prefix, Prefix2, Lowercase) ->
case Int < 0 of
true ->
case Lowercase of
true ->
term(<<"-", (toBinary(Prefix))/binary, Prefix2:8, (toLowerStr(integer_to_binary(-Int, Base)))/binary>>, Width, Adjust, none, PadChar);
_ ->
term(<<"-", (toBinary(Prefix))/binary, Prefix2:8, (integer_to_binary(-Int, Base))/binary>>, Width, Adjust, none, PadChar)
end;
_ ->
case Lowercase of
true ->
term(<<(toBinary(Prefix))/binary, Prefix2:8, (toLowerStr(integer_to_binary(Int, Base)))/binary>>, Width, Adjust, none, PadChar);
_ ->
term(<<(toBinary(Prefix))/binary, Prefix2:8, (integer_to_binary(Int, Base))/binary>>, Width, Adjust, none, PadChar)
end
end.
char(Char, Width, Adjust, Precision, PadChar) ->
if
Width == none andalso Precision == none ->
Char;
Precision == none ->
makePadChars(Char, Width, <<>>);
Width == none ->
makePadChars(Char, Precision, <<>>);
true ->
adjust(Adjust, makePadChars(Char, Precision, <<>>), makePadChars(PadChar, Width - Precision, <<>>))
end.
newline(none, _Adjust, _Precision, _PadChar) -> <<"\n">>;
newline(Width, Adjust, _Precision, _PadChar) ->
case Adjust of
right ->
makePadChars($\n, Width, <<>>);
_ ->
<<"\n">>
end.
remainChars(T, E) ->
if
T < 0 ->
T;
T >= E ->
T - E;
true ->
0
end.
%% ********************************************** eFmtFormat end *****************************************************
%% ********************************************** eFmtPretty start *****************************************************
%% ********************************************** eFmtPretty end *****************************************************
%% ********************************************** utils start **********************************************************
toLowerStr(BinStr) ->
<<begin
case C >= $A andalso C =< $Z of
true ->
<<(C + 32)>>;
_ ->
<<C>>
end
end || <<C:8>> <= BinStr
>>.
toUpperStr(BinStr) ->
<<begin
case C >= $a andalso C =< $z of
true ->
<<(C - 32)>>;
_ ->
<<C>>
end
end || <<C:8>> <= BinStr
>>.
-spec charsLen(chars()) -> non_neg_integer().
charsLen(S) ->
try
iolist_size(S)
catch
_:_ ->
string:length(S)
end.
getOpt(Key, TupleList, Default) ->
case lists:keyfind(Key, 1, TupleList) of
false ->
Default;
ValueTuple ->
element(2, ValueTuple)
end.
toBinary(Value) when is_integer(Value) -> integer_to_binary(Value);
toBinary(Value) when is_list(Value) -> list_to_binary(Value);
toBinary(Value) when is_float(Value) -> float_to_binary(Value, [{decimals, 6}, compact]);
toBinary(Value) when is_atom(Value) -> atom_to_binary(Value, utf8);
toBinary(Value) when is_binary(Value) -> Value;
toBinary([Tuple | PropList] = Value) when is_list(PropList) and is_tuple(Tuple) ->
lists:map(fun({K, V}) -> {toBinary(K), toBinary(V)} end, Value);
toBinary(Value) -> term_to_binary(Value).
%% ********************************************** utils end **********************************************************