diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e27f4..f393554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Support parsing multiline doctests with `iex>` on all lines, but reformat them using `...>` on every line but the first one. - Fix implementation for multiline results. Multiline results are allowed, and they can be terminated with an empty new line or another doctest. - Support exception expressions (`** (ModuleName) message`) in results. +- Desired line length for doctest result now accounts for its indentation. ## 0.1.0 (2024-02-25) diff --git a/lib/doctest_formatter/formatter.ex b/lib/doctest_formatter/formatter.ex index cef15b5..7485ef9 100644 --- a/lib/doctest_formatter/formatter.ex +++ b/lib/doctest_formatter/formatter.ex @@ -70,6 +70,10 @@ defmodule DoctestFormatter.Formatter do end def do_format_expression(%DoctestExpression{} = chunk, opts) do + format_lines(chunk, opts) ++ format_result(chunk, opts) + end + + defp format_lines(chunk, opts) do first_line_symbol = "iex> " next_line_symbol = "...> " @@ -78,17 +82,25 @@ defmodule DoctestFormatter.Formatter do line_length = desired_line_length - elem(chunk.indentation, 1) - String.length(first_line_symbol) - formatted_lines = - chunk.lines - |> Enum.join("\n") - |> Code.format_string!(Keyword.put(opts, :line_length, line_length)) - |> IO.iodata_to_binary() - |> String.split("\n") - |> Enum.with_index() - |> Enum.map(fn {line, index} -> - symbol = if(index == 0, do: first_line_symbol, else: next_line_symbol) - Indentation.indent(symbol <> line, chunk.indentation) - end) + opts = Keyword.put(opts, :line_length, line_length) + + chunk.lines + |> Enum.join("\n") + |> Code.format_string!(opts) + |> IO.iodata_to_binary() + |> String.split("\n") + |> Enum.with_index() + |> Enum.map(fn {line, index} -> + symbol = if(index == 0, do: first_line_symbol, else: next_line_symbol) + Indentation.indent(symbol <> line, chunk.indentation) + end) + end + + defp format_result(chunk, opts) do + desired_line_length = Keyword.get(opts, :line_length, default_elixir_line_length()) + + line_length = desired_line_length - elem(chunk.indentation, 1) + opts = Keyword.put(opts, :line_length, line_length) string_result = chunk.result @@ -104,14 +116,11 @@ defmodule DoctestFormatter.Formatter do |> IO.iodata_to_binary() end - formatted_result = - string_result - |> String.split("\n") - |> Enum.map(fn line -> - Indentation.indent(line, chunk.indentation) - end) - - formatted_lines ++ formatted_result + string_result + |> String.split("\n") + |> Enum.map(fn line -> + Indentation.indent(line, chunk.indentation) + end) end defp exception_result?(string) do diff --git a/test/doctest_formatter/formatter_test.exs b/test/doctest_formatter/formatter_test.exs index 61a127a..ad36851 100644 --- a/test/doctest_formatter/formatter_test.exs +++ b/test/doctest_formatter/formatter_test.exs @@ -649,7 +649,7 @@ defmodule DoctestFormatter.FormatterTest do assert output == desired_output end - test "adjust desired line length to fit the indentation and 'iex> '" do + test "adjust desired test code line length to fit the indentation and 'iex> '" do opts = [line_length: 30] input = @@ -677,6 +677,34 @@ defmodule DoctestFormatter.FormatterTest do assert output == desired_output end + test "adjust desired result line length to fit the indentation" do + opts = [line_length: 30] + + input = + """ + defmodule Foo do + @doc \""" + iex> "aaa" + "a" <> "a" <> "a" + \""" + end + """ + + desired_output = + """ + defmodule Foo do + @doc \""" + iex> "aaa" + "a" <> + "a" <> "a" + \""" + end + """ + + output = format(input, opts) + assert output == desired_output + end + test "can handle exceptions in results" do input = """