-module(gurka_formatter_plain). -include("gurka.hrl"). -export([format/2]). format({Status, Result}, Opts) -> format_header(Status, Opts) ++ format_steps(Result, undefined). format_header(Status, Opts) -> H1 = case proplists:get_value(file, Opts) of undefined -> []; File when Status == ok -> io_lib:format("File: ~s~s~n", [string:left(File, 70, $\s), "PASS"]); File -> io_lib:format("File: ~s~s~n", [string:left(File, 70, $\s), "FAIL"]) end, H2 = case proplists:get_value(tags, Opts) of undefined -> []; [] -> []; Tags -> io_lib:format("Tags: ~s~n", [string:join([binary_to_list(Tag) || Tag <- Tags],",")]) end, H1 ++ H2. format_steps([], _LastAction) -> []; format_steps([Step | Steps], LastAction) when is_list(Step) -> format_steps(Step, LastAction) ++ format_steps(Steps, LastAction); format_steps([Step | Steps], LastAction) -> {FormattedStep, NewLastAction} = format_step(Step, LastAction), FormattedStep ++ format_steps(Steps, NewLastAction). format_step({ok, #step{phase = Phase, action = Action, tokens = Pattern, row = RowNum}}, LastAction) -> {format_pattern(Pattern, RowNum, format_phase(Phase, Action, LastAction)), Action}; format_step({Result, #step{phase = Phase, action = Action, tokens = Pattern, row = RowNum}}, LastAction) -> FormattedPattern = format_pattern(Pattern, RowNum, format_phase(Phase, Action, LastAction)), FormattedFailure = io_lib:format("~s FAILED: ~60p~n", [FormattedPattern, Result]), {FormattedFailure, Action}. format_phase(feature, skip, _LastAction) -> "\nSkipped Feature: "; format_phase(feature, start, _LastAction) -> "\nFeature: "; format_phase(feature, desc, _LastAction) -> " "; format_phase(background, start, _LastAction) -> "\n Background: "; format_phase(scenario, skip, _LastAction) -> "\n Skipped Scenario: "; format_phase(scenario, start, _LastAction) -> "\n Scenario: "; format_phase(_Phase, Action, Action) -> " And "; format_phase(_Phase, given, _LastAction) -> " Given "; format_phase(_Phase, 'when', _LastAction) -> " When "; format_phase(_Phase, 'then', _LastAction) -> " Then "; format_phase(Phase, Action, _LastAction) -> io_lib:format(" ~p:~p ", [Phase, Action]). format_pattern([], RowNum, [$\n | Acc]) -> io_lib:format("~n~s~4B~n", [unicode:characters_to_binary(string:left(Acc, 76, $\s)), RowNum]); format_pattern([], RowNum, Acc) -> io_lib:format("~s~4B~n", [unicode:characters_to_binary(string:left(Acc, 76, $\s)), RowNum]); format_pattern([{table, Table} | Pattern], RowNum, Acc) -> Sizes = [[length(unicode:characters_to_list(Col, utf8)) || Col <- Row] || Row <- Table], Max = lists:foldl(fun(Row, MaxAcc) -> lists:zipwith(fun(X, Y) -> max(X, Y) end, Row, MaxAcc) end, hd(Sizes), tl(Sizes)), FTable = [ " " ++ lists:zipwith(fun(V, M) -> "| " ++ string:left(binary_to_list(V), M + 1, $\s) end, Row, Max) ++ "|\n" || Row <- Table ], format_pattern(Pattern, RowNum, Acc) ++ io_lib:format("~s", [FTable]); format_pattern([{docstring, Docstring} | Pattern], RowNum, Acc) -> IndentedDocString = binary:replace(Docstring, <<"\n">>, <<"\n ">>, [global]), format_pattern(Pattern, RowNum, Acc) ++ io_lib:format(" \"\"\"~n ~s~n \"\"\"~n", [IndentedDocString]); format_pattern([Term | Pattern], RowNum, Acc) -> format_pattern(Pattern, RowNum, Acc ++ unicode:characters_to_list(Term, utf8) ++ " ").