aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorinoas <mail@inoas.com>2022-05-17 18:48:03 +0000
committerGitHub <noreply@github.com>2022-05-17 19:48:03 +0100
commit5c26af70c60c51531972a760482a3580402b7d68 (patch)
tree50f1df6f5f1c3f09e550a977b45d510eb0a3a6c1 /src
parentf9d57db847ff2a8471c9136bd309c870b610d04d (diff)
downloadgleam_stdlib-5c26af70c60c51531972a760482a3580402b7d68.tar.gz
gleam_stdlib-5c26af70c60c51531972a760482a3580402b7d68.zip
add string.inspect() (#296)
Diffstat (limited to 'src')
-rw-r--r--src/gleam/string.gleam15
-rw-r--r--src/gleam_stdlib.erl68
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]), ")"].