diff --git a/lib/elixir/lib/string_io.ex b/lib/elixir/lib/string_io.ex index 550633a7af8..f9fcfc163a4 100644 --- a/lib/elixir/lib/string_io.ex +++ b/lib/elixir/lib/string_io.ex @@ -183,7 +183,7 @@ defmodule StringIO do _ = Process.monitor(pid) capture_prompt = options[:capture_prompt] || false encoding = options[:encoding] || :unicode - {:ok, %{encoding: encoding, input: string, output: "", capture_prompt: capture_prompt}} + {:ok, %{encoding: encoding, input: string, output: [], capture_prompt: capture_prompt}} end @impl true @@ -208,15 +208,18 @@ defmodule StringIO do @impl true def handle_call(:contents, _from, %{input: input, output: output} = state) do - {:reply, {input, output}, state} + string_output = reverse_join(output) + # update the state too to avoid having to do the same joining in future calls + {:reply, {input, string_output}, %{state | output: [string_output]}} end def handle_call(:flush, _from, %{output: output} = state) do - {:reply, output, %{state | output: ""}} + {:reply, reverse_join(output), %{state | output: []}} end def handle_call(:close, _from, %{input: input, output: output} = state) do - {:stop, :normal, {:ok, {input, output}}, state} + string_output = reverse_join(output) + {:stop, :normal, {:ok, {input, string_output}}, %{state | output: [string_output]}} end defp io_request(from, reply_as, req, state) do @@ -302,7 +305,7 @@ defmodule StringIO do defp put_chars(encoding, chars, req, state) do case :unicode.characters_to_binary(chars, encoding, state.encoding) do string when is_binary(string) -> - {:ok, %{state | output: state.output <> string}} + {:ok, %{state | output: [string | state.output]}} {_, _, _} -> {{:error, {:no_translation, encoding, state.encoding}}, state} @@ -450,12 +453,14 @@ defmodule StringIO do ## helpers + defp reverse_join(output), do: output |> :lists.reverse() |> IO.iodata_to_binary() + defp state_after_read(%{capture_prompt: false} = state, remainder, _prompt, _count) do %{state | input: remainder} end defp state_after_read(%{capture_prompt: true, output: output} = state, remainder, prompt, count) do - output = <> + output = [:binary.copy(IO.chardata_to_string(prompt), count) | output] %{state | input: remainder, output: output} end