Last active
September 4, 2016 14:01
-
-
Save benhamill/88ea21885c584df10bd5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env elixir | |
defmodule Listen do | |
use GenServer | |
## Client | |
def start_link(command, opts \\ []) do | |
GenServer.start_link(__MODULE__, command, opts) | |
end | |
def handle_input(server, input) do | |
GenServer.call(server, input) | |
end | |
## Server | |
def init(command) do | |
{:ok, %{port: start_port(command), waiting: nil, exit_status: nil}} | |
end | |
def handle_call(input, from, state) do | |
if state.exit_status do | |
{:reply, {:exit_status, state.exit_status}, %{state | exit_status: nil}} | |
else | |
Port.command(state.port, input) | |
{:noreply, %{state | waiting: from}} | |
end | |
end | |
def handle_info({_port, {:data, response}}, state) do | |
case state.waiting do | |
nil -> {:stop, "Got unexpected data: #{response}", state} | |
caller -> | |
GenServer.reply(caller, {:ok, response}) | |
{:noreply, %{state | waiting: nil}} | |
end | |
end | |
def handle_info({_port, {:exit_status, status}}, state) do | |
case state.waiting do | |
nil -> {:noreply, %{state | exit_status: status}} | |
caller -> | |
GenServer.reply(caller, {:exit_status, status}) | |
{:noreply, %{state | waiting: nil, exit_status: nil}} | |
end | |
end | |
def handle_info(info, state) do | |
{:stop, "Weird message: #{inspect info}", state} | |
end | |
defp start_port(command) do | |
Port.open({:spawn, command}, [:binary, :exit_status]) | |
end | |
end | |
{options, _, _} = OptionParser.parse( | |
System.argv, | |
strict: [ | |
ruby: :boolean, | |
elixir: :boolean, | |
bash: :boolean, | |
] | |
) | |
command = cond do | |
options[:elixir] -> ~S""" | |
elixir -e " | |
IO.read(:line) | |
|> String.strip | |
|> IO.puts | |
" | |
""" | |
options[:ruby] -> ~S""" | |
ruby -e " | |
STDOUT.sync = true | |
puts gets.strip | |
" | |
""" | |
true -> "head -n1" | |
end | |
{:ok, server} = Listen.start_link(command, debug: [:trace]) | |
Enum.each [ | |
~s(Yeah\n), | |
~s(Yep\n), | |
~s(Uh-huh\n), | |
], fn out-> | |
case Listen.handle_input(server, out) do | |
{:exit_status, status} -> | |
IO.puts "Process exited, #{status}." | |
exit :normal | |
{:ok, response} -> IO.inspect response | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment