You might be able to do that with Port.open
and then receive
messages coming from it and send them to the liveview process.
port.exs
defmodule Command do
def exec(cmd, args) do
path = System.find_executable(cmd)
port = Port.open({:spawn_executable, path}, [:binary, :exit_status, args: args, line: 1000])
loop(port)
end
defp loop(port) do
receive do
{^port, {:data, data}} ->
IO.inspect(data: data)
loop(port)
{^port, {:exit_status, exit_status}} ->
IO.inspect(exit_status: exit_status)
end
end
end
Command.exec("cat", ["port.exs"])
> elixir port.exs
[data: {:eol, "defmodule Command do"}]
[data: {:eol, " def exec(cmd, args) do"}]
[data: {:eol, " path = System.find_executable(cmd)"}]
[
data: {:eol,
" port = Port.open({:spawn_executable, path}, [:binary, :exit_status, args: args, line: 1000])"}
]
[data: {:eol, " loop(port)"}]
[data: {:eol, " end"}]
[data: {:eol, ""}]
[data: {:eol, " defp loop(port) do"}]
[data: {:eol, " receive do"}]
[data: {:eol, " {^port, {:data, data}} ->"}]
[data: {:eol, " IO.inspect(data: data)"}]
[data: {:eol, " loop(port)"}]
[data: {:eol, ""}]
[data: {:eol, " {^port, {:exit_status, exit_status}} ->"}]
[data: {:eol, " IO.inspect(exit_status: exit_status)"}]
[data: {:eol, " end"}]
[data: {:eol, " end"}]
[data: {:eol, "end"}]
[data: {:eol, ""}]
[data: {:eol, "Command.exec(\"cat\", [\"port.exs\"])"}]
[exit_status: 0]