-module(glee). -export([parse/1, format_key_value/2, format_dict/1]). % Parse Sorbet formatted string into a map -spec parse(string()) -> map(). parse(Contents) -> Lines = string:split(Contents, "\n", all), parse_lines(Lines, #{}, none, ""). parse_lines([], Map, none, _) -> Map; parse_lines([], Map, {key, Key}, Value) -> maps:put(Key, string:trim(Value), Map); parse_lines([Line|Rest], Map, CurrentKey, CurrentValue) -> case string:find(Line, "=>") of nomatch -> % Check for continuation line TrimmedLine = string:trim(Line), case string:prefix(TrimmedLine, ">") of nomatch -> parse_lines(Rest, Map, CurrentKey, CurrentValue); _ when CurrentKey =:= none -> utilities:print_error("Continuation line without a key"), parse_lines(Rest, Map, CurrentKey, CurrentValue); _ -> Continuation = string:trim(string:slice(TrimmedLine, 1)), NewValue = case CurrentValue of "" -> Continuation; _ -> CurrentValue ++ "\n" ++ Continuation end, parse_lines(Rest, Map, CurrentKey, NewValue) end; _ -> % Process new key-value pair case CurrentKey of {key, Key} -> UpdatedMap = maps:put(Key, string:trim(CurrentValue), Map), process_key_value(Line, Rest, UpdatedMap); none -> process_key_value(Line, Rest, Map) end end. process_key_value(Line, Rest, Map) -> case string:split(Line, "=>") of [Key, Value] -> parse_lines(Rest, Map, {key, string:trim(Key)}, string:trim(Value)); _ -> utilities:print_error("Expected [key] => [value]"), parse_lines(Rest, Map, none, "") end. % Format a key-value pair into Sorbet format -spec format_key_value(string(), string()) -> string(). format_key_value(Key, Value) -> case string:find(Value, "\n") of nomatch -> Key ++ " => " ++ Value; _ -> [First|Rest] = string:split(Value, "\n", all), FirstLine = Key ++ " => " ++ First, ContinuationLines = ["> " ++ Line || Line <- Rest], string:join([FirstLine|ContinuationLines], "\n") end. % Format a map into Sorbet format -spec format_dict(map()) -> string(). format_dict(Map) -> Entries = maps:to_list(Map), FormattedEntries = [format_key_value(Key, Value) || {Key, Value} <- Entries], string:join(FormattedEntries, "\n").