I’m quite stuck at something I thought would be quite straight forward, but it seems maybe this topic hasn’t come up much in my career in Elixir.
I am trying to run a test to check STOUT and test STDIN for a function:
test "can read and output" do
input =
"""
3
Hello
Hello World
Hello A B World
"""
assert ExUnit.CaptureIO.capture_io(fn ->
IO.write(input)
task = Task.async(Example, :start, [])
Task.await(task)
end) == """
3
Hello
Hello World
Hello B A World
"""
end
Within my code I’ve been trying to read from stdin, but I keep getting :eof
when I used IO.read(:line) or
""if I try
IO.read(:all)`.
I’m pretty sure I must be close, but I am missing something somewhere. The reason I’m launching a task is because I’m pretty sure the code will block so I’m unable to write to :stdio
.
here’s my code for the function:
def start(pid \\ :stdio) do
number_of_lines =
IO.read(pid, :read)
|> String.trim()
|> String.to_integer()
Enum.each(0..number_of_lines, fn _i ->
sentence =
IO.read(pid, :line)
|> IO.inspect()
|> String.trim()
|> String.split()
sentence_to_write =
if length(sentence) > 2 do
[hd | tail] = sentence
{last, rest} = List.pop_at(tail, length(tail))
new_tail = Enum.reverse(rest) ++ [last]
[hd | new_tail]
else
sentence
end
sentence_to_write
|> Enum.reduce(fn word, acc ->
acc <> " " <> word
end)
|> IO.write(pid)
end)
end
The there’s a pid there is I was also thinking I can create a pid that responds to the message protocol for writing to a device, but I kind of gave up around there, thinking there must be a way to do this without creating another process.
Does anyone have any idea about how I can achieve this?