io_lib_pretty.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 547 行 · 第 1/2 页
ERL
547 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id $%%-module(io_lib_pretty).%%% Pretty printing Erlang terms%%%%%% In this module "print" means the formatted printing while "write"%%% means just writing out onto one line.-export([print/1,print/2,print/3,print/4,print/5]).%%%%%% Exported functions%%%%% print(Term) -> [Chars]%% print(Term, Column, LineLength, Depth) -> [Chars]%% Depth = -1 gives unlimited print depth. Use io_lib:write for atomic terms.print(Term) -> print(Term, 1, 80, -1).%% print(Term, RecDefFun) -> [Chars]%% print(Term, Depth, RecDefFun) -> [Chars]%% RecDefFun = fun(Tag, NoFields) -> [FieldTag] | no%% Used by the shell for printing records.print(Term, RecDefFun) -> print(Term, -1, RecDefFun).print(Term, Depth, RecDefFun) -> print(Term, 1, 80, Depth, RecDefFun).print(Term, Col, Ll, D) -> print(Term, Col, Ll, D, no_fun).print(_, _, _, 0, _RF) -> "...";print(Term, Col, Ll, D, RecDefFun) when Col =< 0 -> print(Term, 1, Ll, D, RecDefFun);print(Term, Col, Ll, D, RecDefFun) when is_tuple(Term); is_list(Term) -> If = {_S, Len} = print_length(Term, D, RecDefFun), if Len < Ll - Col -> write(If); true -> TInd = while_fail([-1, 4], fun(I) -> cind(If, Col, Ll, I) end, 1), pp(If, Col, Ll, TInd, indent(Col), 0) end;print(<<_/bitstr>>=Term, Col, Ll, D, RecDefFun) -> If = {_S, Len} = print_length(Term, D, RecDefFun), if Len < Ll - Col -> write(If); true -> TInd = while_fail([-1, 4], fun(I) -> cind(If, Col, Ll, I) end, 1), pp(If, Col, Ll, TInd, indent(Col), 0) end;print(Term, _Col, _Ll, _D, _RF) -> io_lib:write(Term).%%%%%% Local functions%%%pp({_S, Len} = If, Col, Ll, _TInd, _Ind, LD) when Len < Ll - Col - LD -> write(If);pp({{list,L}, _Len}, Col, Ll, TInd, Ind, LD) -> [$[, pp_list(L, Col + 1, Ll, TInd, indent(1, Ind), LD, $|), $]];pp({{tuple,true,L}, _Len}, Col, Ll, TInd, Ind, LD) -> [${, pp_tag_tuple(L, Col, Ll, TInd, Ind, LD), $}];pp({{tuple,false,L}, _Len}, Col, Ll, TInd, Ind, LD) -> [${, pp_list(L, Col + 1, Ll, TInd, indent(1, Ind), LD, $,), $}];pp({{record,[{Name,NLen} | L]}, _Len}, Col, Ll, TInd, Ind, LD) -> [Name, ${, pp_record(L, NLen, Col, Ll, TInd, Ind, LD), $}];pp({{bin,S}, _Len}, Col, Ll, _TInd, Ind, LD) -> pp_binary(S, Col + 2, Ll, indent(2, Ind), LD);pp({S, _Len}, _Col, _Ll, _TInd, _Ind, _LD) -> S.%% Print a tagged tuple by indenting the rest of the elements%% differently to the tag. Tuple has size >= 2.pp_tag_tuple([{Tag,Tlen} | L], Col, Ll, TInd, Ind, LD) -> TagInd = Tlen + 2, Tcol = Col + TagInd, S = $,, if TInd > 0, TagInd > TInd -> [Tag | pp_tail(L, Col+TInd, Ll, TInd, indent(TInd, Ind), LD, S)]; true -> [Tag, S | pp_list(L, Tcol, Ll, TInd, indent(TagInd, Ind), LD, S)] end.pp_record([], _Nlen, _Col, _Ll, _TInd, _Ind, _LD) -> "";pp_record({dots, _}, _Nlen, _Col, _Ll, _TInd, _Ind, _LD) -> "...";pp_record([F | Fs], Nlen, Col0, Ll, TInd, Ind0, LD) -> Nind = Nlen + 1, {Col, Ind, S} = rec_indent(Nind, TInd, Col0, Ind0), [S, pp_field(F, Col, Ll, TInd, Ind, last_depth(Fs, LD)) | pp_fields_tail(Fs, Col, Ll, TInd, Ind, LD)]. pp_fields_tail([], _Col, _Ll, _TInd, _Ind, _LD) -> "";pp_fields_tail({dots, _}, _Col, _Ll, _TInd, _Ind, _LD) -> ",...";pp_fields_tail([F | Fs], Col, Ll, TInd, Ind, LD) -> [$,, $\n, Ind, pp_field(F, Col, Ll, TInd, Ind, last_depth(Fs, LD)) | pp_fields_tail(Fs, Col, Ll, TInd, Ind, LD)].pp_field({_,Len}=Fl, Col, Ll, _TInd, _Ind, LD) when Len < Ll - Col - LD -> write_field(Fl);pp_field({{field, Name, NameL, F}, _Len}, Col0, Ll, TInd, Ind0, LD) -> {Col, Ind, S} = rec_indent(NameL, TInd, Col0, Ind0), [Name, " = ", S | pp(F, Col, Ll, TInd, Ind, LD)].rec_indent(RInd, TInd, Col0, Ind0) -> Nl = (TInd > 0) and (RInd > TInd), DCol = case Nl of true -> TInd; false -> RInd end, Col = Col0 + DCol, Ind = indent(DCol, Ind0), S = case Nl of true -> [$\n | Ind]; false -> "" end, {Col, Ind, S}.pp_list({dots, _}, _Col, _Ll, _TInd, _Ind, _LD, _S) -> "...";pp_list([E | Es], Col, Ll, TInd, Ind, LD, S) -> [pp(E, Col, Ll, TInd, Ind, last_depth(Es, LD)) | pp_tail(Es, Col, Ll, TInd, Ind, LD, S)].pp_tail([], _Col, _Ll, _TInd, _Ind, _LD, _S) -> "";pp_tail([E | Es], Col, Ll, TInd, Ind, LD, S) -> [$,, $\n, Ind, pp(E, Col, Ll, TInd, Ind, last_depth(Es, LD)) | pp_tail(Es, Col, Ll, TInd, Ind, LD, S)];pp_tail({dots, _}, _Col, _Ll, _TInd, _Ind, _LD, S) -> [S | "..."];pp_tail(E, Col, Ll, TInd, Ind, LD, S) -> [S, $\n, Ind | pp(E, Col, Ll, TInd, Ind, LD + 1)].last_depth([_ | _], _LD) -> 0;last_depth(_, LD) -> LD + 1.%% Reuse the list created by io_lib:write_binary()...pp_binary([LT,LT,S,GT,GT], Col, Ll, Ind, LD) -> N = max(8, Ll - Col - LD), [LT,LT,pp_binary(S, N, N, Ind),GT,GT].pp_binary([BS, $, | S], N, N0, Ind) -> Len = length(BS) + 1, case N - Len of N1 when N1 < 0 -> [$\n, Ind, BS, $, | pp_binary(S, N0 - Len, N0, Ind)]; N1 -> [BS, $, | pp_binary(S, N1, N0, Ind)] end;pp_binary([BS1, $:, BS2]=S, N, _N0, Ind) when length(BS1) + length(BS2) + 1 > N -> [$\n, Ind, S];pp_binary(S, N, _N0, Ind) when length(S) > N -> [$\n, Ind, S];pp_binary(S, _N, _N0, _Ind) -> S.write({{tuple, _IsTagged, L}, _}) -> [${, write_list(L, $,), $}];write({{list, L}, _}) -> [$[, write_list(L, $|), $]];write({{record, [{Name,_} | L]}, _}) -> [Name, ${, write_fields(L), $}];write({{bin, S}, _}) -> S;write({S, _}) -> S.write_fields([]) -> "";write_fields({dots, _}) -> "...";write_fields([F | Fs]) -> [write_field(F) | write_fields_tail(Fs)].write_fields_tail([]) -> "";write_fields_tail({dots, _}) -> ",...";write_fields_tail([F | Fs]) -> [$,, write_field(F) | write_fields_tail(Fs)].write_field({{field, Name, _NameL, F}, _}) -> [Name, " = " | write(F)].write_list({dots, _}, _S) -> "...";write_list([E | Es], S) -> [write(E) | write_tail(Es, S)].write_tail([], _S) -> [];write_tail([E | Es], S) -> [$,, write(E) | write_tail(Es, S)];write_tail({dots, _}, S) -> [S | "..."];write_tail(E, S) -> [S | write(E)].%% The depth (D) is used for extracting and counting the characters to%% print. The structure is kept so that the returned intermediate%% format can be formatted. The separators (list, tuple, record) are%% counted but need to be added later.%% D =/= 0print_length([], _D, _RF) -> {"[]", 2};print_length({}, _D, _RF) -> {"{}", 2};print_length(List, D, RF) when is_list(List) -> case printable_list(List, D) of true -> S = io_lib:write_string(List, $"), %" {S, length(S)}; %% Truncated lists could break some existing code. % {true, Prefix} -> % S = io_lib:write_string(Prefix, $"), %" % {[S | "..."], 3 + length(S)}; false -> print_length_list(List, D, RF) end;print_length(Fun, _D, _RF) when is_function(Fun) -> S = io_lib:write(Fun), {S, iolist_size(S)};print_length(R, D, RF) when is_atom(element(1, R)), is_function(RF) -> case RF(element(1, R), size(R) - 1) of no -> print_length_tuple(R, D, RF); RDefs -> print_length_record(R, D, RF, RDefs) end;print_length(Tuple, D, RF) when is_tuple(Tuple) -> print_length_tuple(Tuple, D, RF);print_length(<<>>, _D, _RF) -> {"<<>>", 4};print_length(<<_/bitstr>>, 1, _RF) -> {"<<...>>", 7};print_length(<<_/bitstr>>=Bin, D, _RF) -> case erlang:bitsize(Bin) rem 8 of 0 -> D1 = D - 1, case printable_bin(Bin, D1) of List when is_list(List) ->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?