Skip to content

Commit

Permalink
Fix IEx doc printing for headings with newline characters (#13018)
Browse files Browse the repository at this point in the history
Update `IEx.introspection.print_doc/5` to trasverse the list of headings
and split each heading into multiple headings, in case the heading has
any newline characters (`\n`). This fixes an issue where using the `h`
macro with some functions ended up with a broken output for the function
signature, as the padding done by `IO.ANSI.Docs.print_headings/2` does
not take into consideration the fact the the headings can contain
newline characters, and thus end up in multiple lines.
  • Loading branch information
dinocosta authored Oct 20, 2023
1 parent 2f9061e commit d332f26
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/elixir/lib/io/ansi/docs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ defmodule IO.ANSI.Docs do
"""
@spec print_headings([String.t()], keyword) :: :ok
def print_headings(headings, options \\ []) do
# It's possible for some of the headings to contain newline characters (`\n`), so in order to prevent it from
# breaking the output from `print_headings/2`, as `print_headings/2` tries to pad the whole heading, we first split
# any heading containgin newline characters into multiple headings, that way each one is padded on its own.
headings = Enum.flat_map(headings, fn heading -> String.split(heading, "\n") end)
options = Keyword.merge(default_options(), options)
newline_after_block(options)
width = options[:width]
Expand Down
8 changes: 8 additions & 0 deletions lib/elixir/test/elixir/io/ansi/docs_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ defmodule IO.ANSI.DocsTest do
assert String.contains?(result, " foo ")
assert String.contains?(result, " bar ")
end

test "is correctly formatted when newline character is present" do
result = format_headings(["foo\nbar"])
assert :binary.matches(result, "\e[0m\n\e[7m\e[33m") |> length == 2
assert ["\e[0m", foo_line, bar_line, "\e[0m"] = String.split(result, "\n")
assert Regex.match?(~r/\e\[7m\e\[33m +foo +\e\[0m/, foo_line)
assert Regex.match?(~r/\e\[7m\e\[33m +bar +\e\[0m/, bar_line)
end
end

describe "metadata" do
Expand Down

0 comments on commit d332f26

Please sign in to comment.