diff options
author | inoas <mail@inoas.com> | 2022-05-17 18:48:03 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-17 19:48:03 +0100 |
commit | 5c26af70c60c51531972a760482a3580402b7d68 (patch) | |
tree | 50f1df6f5f1c3f09e550a977b45d510eb0a3a6c1 /src | |
parent | f9d57db847ff2a8471c9136bd309c870b610d04d (diff) | |
download | gleam_stdlib-5c26af70c60c51531972a760482a3580402b7d68.tar.gz gleam_stdlib-5c26af70c60c51531972a760482a3580402b7d68.zip |
add string.inspect() (#296)
Diffstat (limited to 'src')
-rw-r--r-- | src/gleam/string.gleam | 15 | ||||
-rw-r--r-- | src/gleam_stdlib.erl | 68 |
2 files changed, 77 insertions, 6 deletions
diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam index 45d4d31..d06e2dd 100644 --- a/src/gleam/string.gleam +++ b/src/gleam/string.gleam @@ -823,3 +823,18 @@ pub fn capitalise(s: String) -> String { _ -> "" } } + +pub fn inspect(value: a) -> String { + do_inspect(value) + |> string_builder.to_string +} + +if javascript { + external fn do_inspect(value: a) -> string_builder.StringBuilder = + "../gleam.mjs" "inspect" +} + +if erlang { + external fn do_inspect(value: a) -> string_builder.StringBuilder = + "gleam_stdlib" "inspect" +} diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index cc1475f..9dc769b 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -9,7 +9,8 @@ bit_string_slice/3, decode_bit_string/1, compile_regex/2, regex_scan/2, percent_encode/1, percent_decode/1, regex_check/2, regex_split/2, base_decode64/1, parse_query/1, bit_string_concat/1, size_of_tuple/1, - decode_tuple/1, tuple_get/2, classify_dynamic/1, print/1, println/1]). + decode_tuple/1, tuple_get/2, classify_dynamic/1, print/1, println/1, + inspect/1]). %% Taken from OTP's uri_string module -define(DEC2HEX(X), @@ -47,9 +48,9 @@ classify_dynamic(X) when is_float(X) -> <<"Float">>; classify_dynamic(X) when is_list(X) -> <<"List">>; classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; classify_dynamic(X) when is_map(X) -> <<"Map">>; -classify_dynamic(X) when is_tuple(X) -> +classify_dynamic(X) when is_tuple(X) -> iolist_to_binary(["Tuple of ", integer_to_list(tuple_size(X)), " elements"]); -classify_dynamic(X) when +classify_dynamic(X) when is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse @@ -81,7 +82,7 @@ decode_list(Data) -> decode_error_msg(<<"List">>, Data). decode_field(Data, Key) -> case Data of #{Key := Value} -> {ok, Value}; - _ -> + _ -> decode_error(<<"field"/utf8>>, <<"nothing"/utf8>>) end. @@ -227,7 +228,7 @@ wrap_list(X) -> [X]. parse_query(Query) -> case uri_string:dissect_query(Query) of {error, _, _} -> {error, nil}; - Pairs -> + Pairs -> Pairs1 = lists:map(fun ({K, true}) -> {K, <<"">>}; (Pair) -> Pair @@ -296,7 +297,7 @@ uri_parse(String) -> maps_get_optional(Uri, userinfo), maps_get_optional(Uri, host), maps_get_optional(Uri, port), - maps_get_or(Uri, path, <<>>), + maps_get_or(Uri, path, <<>>), maps_get_optional(Uri, query), maps_get_optional(Uri, fragment) }} @@ -319,3 +320,58 @@ print(String) -> println(String) -> io:put_chars([String, $\n]), nil. + +inspect(true) -> + "True"; +inspect(false) -> + "False"; +inspect(Any) when is_atom(Any) -> + lists:map( + fun(Part) -> + [Head | Tail] = string:next_grapheme(unicode:characters_to_binary(Part)), + [string:uppercase([Head]), Tail] + end, + re:split(erlang:atom_to_list(Any), "_+", [{return, iodata}]) + ); +inspect(Any) when is_integer(Any) -> + erlang:integer_to_list(Any); +inspect(Any) when is_float(Any) -> + io_lib_format:fwrite_g(Any); +inspect(Any) when is_binary(Any) -> + Pattern = [$"], + Replacement = [$\\, $\\, $"], + Escaped = re:replace(Any, Pattern, Replacement, [{return, binary}, global]), + ["\"", Escaped, "\""]; +inspect(Any) when is_list(Any) -> + ["[", + lists:join(<<", ">>, + lists:map(fun inspect/1, Any) + ), + "]"]; +inspect(Any) when is_tuple(Any) % Record constructors + andalso is_atom(element(1, Any)) + andalso element(1, Any) =/= false + andalso element(1, Any) =/= true + andalso element(1, Any) =/= nil +-> + [Atom | ArgsList] = erlang:tuple_to_list(Any), + Args = + lists:join(<<", ">>, + lists:map(fun inspect/1, ArgsList) + ), + [inspect(Atom), "(", Args, ")"]; +inspect(Any) when is_tuple(Any) -> + ["#(", + lists:join(<<", ">>, + lists:map(fun inspect/1, erlang:tuple_to_list(Any)) + ), + ")"]; +inspect(Any) when is_function(Any) -> + {arity, Arity} = erlang:fun_info(Any, arity), + ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), + Args = lists:join(<<", ">>, + lists:map(fun(Arg) -> <<Arg>> end, ArgsAsciiCodes) + ), + ["//fn(", Args, ") { ... }"]; +inspect(Any) -> + ["//erl(", io_lib:format("~p", [Any]), ")"]. |