Last active
January 30, 2020 08:58
-
-
Save Kaylebor/7be37160e5cafceebf4ed5115c560717 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% @doc | |
%% USAGE: | |
%% In the $HOME folder, create a file called .erlang | |
%% On that file, write the following line: | |
%% | |
%% code:load_abs("/path/to/user_default"). | |
%% | |
%% Note that user_default must have been compiled | |
%% (there must be a user_default.beam file in the folder) | |
%% | |
%% Also, the call to code:load_abs/1 must be the first line | |
%% in .erlang | |
%% | |
%% print_function/3 and print_record/2 have been copied from | |
%% https://gist.github.com/seriyps/ada87b9896e745f57ddce87672e3728c | |
%% @end | |
-module(user_default). | |
%% ------------------------------------------------------------------ | |
%% API Function Exports | |
%% ------------------------------------------------------------------ | |
-export([ | |
format/1, format/2, | |
test_sequence/4, | |
test_sequence_parallel/5, | |
print_function/3, | |
print_record/2 | |
]). | |
%% Record definitions MUST be a module | |
-define(DEFAULT_RECORD_DEFINITIONS_MODULE, module_atom). | |
format(Value) -> format(Value, ?DEFAULT_RECORD_DEFINITIONS_MODULE). | |
format(Value, RecordDefinitionsModule) when is_list(Value) -> lists:flatten([$[, string:join(lists:map(fun(Record) -> format(Record, RecordDefinitionsModule) end, Value), ",\n"), $]]); | |
%% The second argument on print_record/2 tells it where to find the record definitions for printing; | |
%% it can be an atom or a list | |
format(Value, RecordDefinitionsModule) when is_tuple(Value) -> print_record(Value, RecordDefinitionsModule); | |
format(Value, _RecordDefinitionsModule) -> lists:flatten(io_lib:format("~p", [Value])). | |
append_to_file(FileName, Data) -> | |
case file:read_file_info(FileName) of | |
{ok, _FileInfo} -> file:write_file(FileName, "\n" ++ format(Data), [append]); | |
{error, enoent} -> file:write_file(FileName, format(Data)) | |
end. | |
test_sequence(FileName, Start, End, FBackend) -> | |
lists:map(fun(Counter) -> | |
Result = FBackend(Counter), | |
append_to_file(FileName, Result) | |
end, lists:seq(Start, End)). | |
test_sequence_parallel(FileName, Start, End, Interval, FBackend) -> | |
lists:map(fun(Counter) -> | |
spawn(fun() -> | |
CounterEnd = case Counter + Interval of | |
Val when Val > End -> End; | |
Val -> Val | |
end, | |
test_sequence(FileName, Counter, CounterEnd, FBackend) | |
end) | |
end, lists:seq(Start, End, Interval)). | |
print_function(Mod, Fun, Arity) when is_atom(Fun), is_integer(Arity) -> | |
try do_print_function(Mod, Fun, Arity) | |
catch E:R -> | |
error_logger:warning_msg("Error ~p:~p~n~p", [E, R, erlang:get_stacktrace()]), | |
io_lib:format("fun ~p:~p/~p", [Mod, Fun, Arity]) | |
end. | |
do_print_function(Mod, Fun, Arity) when is_atom(Mod) -> | |
case code:which(Mod) of | |
preloaded -> error(preloaded); | |
Filename -> do_print_function(Filename, Fun, Arity) | |
end; | |
do_print_function(Filename, Fun, Arity) when is_list(Filename) -> | |
{ok, {_Mod, [{abstract_code, {_Version, Forms}}]}} = beam_lib:chunks(Filename, [abstract_code]), | |
[FunDef] = [D || {function, _, Fun0, Arity0, _} = D <- Forms, Fun0 == Fun, Arity0 == Arity], | |
erl_prettypr:format(erl_syntax:form_list([FunDef])). | |
print_record(Record, Module) -> | |
try do_print_record(Record, Module) | |
catch E:R -> | |
error_logger:warning_msg("Error: ~p:~p~n~p", [E, R, erlang:get_stacktrace()]), | |
io_lib:format("~p", [Record]) | |
end. | |
do_print_record(Record, Module) when is_tuple(Record), is_atom(Module) -> | |
case code:which(Module) of | |
preloaded -> Record; | |
Filename -> do_print_record(Record, Filename) | |
end; | |
do_print_record(Record, Filename) when is_tuple(Record), is_list(Filename) -> | |
{ok, {_Mod, [{abstract_code, {_Version, Forms}}]}} = beam_lib:chunks(Filename, [abstract_code]), | |
RecordName = element(1, Record), | |
[RecordDef] = [D || {attribute, _, record, {RecordName1, _} = D} <- Forms, RecordName1 == RecordName], | |
try do_print_record_pretty(Record, RecordDef) | |
catch E:R -> | |
error_logger:warning_msg("prettyprint error ~p:~p", [E, R]), | |
do_print_record_raw(Record, RecordDef) | |
end. | |
%% Handcrafted simple record printer | |
do_print_record_raw(Record, {Name, FieldDefs}) -> | |
%% NFields = tuple_size(Record) - 1, | |
Name = element(1, Record), | |
FieldVals = tl(tuple_to_list(Record)), | |
FieldKV = print_pairs(FieldVals, FieldDefs), | |
["#", atom_to_list(Name), "{", FieldKV, "}"]. | |
print_pairs([Val], [Def]) -> | |
%% trailing comma | |
[pair(Val, Def)]; | |
print_pairs([Val | VRest], [Def | DRest]) -> | |
[pair(Val, Def), ", " | print_pairs(VRest, DRest)]; | |
print_pairs([], []) -> []. | |
pair(Val, Def) -> io_lib:format("~p = ~500p", [field_to_name(Def), Val]). | |
%% Pretty printer with erl_syntax and erl_prettypr | |
do_print_record_pretty(Record, {Name, FieldDefs}) when element(1, Record) == Name -> | |
Values = tl(tuple_to_list(Record)), | |
Names = lists:map(fun field_to_name/1, FieldDefs), | |
Fields = lists:zip(Names, Values), | |
FieldsExpr = [erl_syntax:record_field(erl_syntax:atom(FieldName), erl_syntax:abstract(FieldValue)) || {FieldName, FieldValue} <- Fields], | |
RecordExpr = erl_syntax:record_expr(erl_syntax:atom(Name), FieldsExpr), | |
erl_prettypr:format(erl_syntax:revert(RecordExpr), [{paper, 120}, {ribbon, 110}]). | |
field_to_name({record_field, _, {atom, _, Name}, _Default}) -> Name; | |
field_to_name({record_field, _, {atom, _, Name}}) -> Name. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment