I can't type anything in terminal when I run my app with "iex -S mix"

Hi guys!

I’m a beginner user in Elixir. I wrote a small program using Mix project. It’s work fine when I run my app with “mix run”, but when I use “iex -S mix” (for debug) I can’t type anything in terminal and I need to use ctrl+C for exit.

No idea what is going on there. Are you calling iex -S mix from within the root directory of your project? Are you able to just run iex normally?

1 Like

Yes, iex console it’s working.
I run in terminal inside vscode, mix run works fine, but iex -S mix not. I tested in terminal outside vscode and the same error happens too.

Hey @alrigotto welcome! This usually means that one of your supervisor’s children has hung and so the app is unable to boot. If you do iex -S mix run --no-start do you get a REPL? Can you show your application.ex file?

1 Like

Hi benwilson!

I did iex -S mix run --no-start and get normaly REPL.

I guess this problem started when I was made several debug testing for learning.

I wonder if this changed some file inside mix folder project, because new projects are working fine.

My app.ex:

It’s a simple guess number game tutorial.

defmodule GuessGame do
  use Application


  def start(_,_) do
    run()
    {:ok, self()}
    |> IO.inspect(label: "run after2")
  end

  def run() do

    IO.puts("Let's pĺay Guess the Number")
    IO.gets("Choose a dificult level (1, 2 or 3):")
    # the "|>" (pipe) operator in Elixir put the output from the previous line to the first function's argument in the next line
    |> parse_input()
    |> pickup_number()
    |> IO.inspect(label: "Before play()")
    |> play()
    |> IO.inspect(label: "After play()")
    # require IEx; IEx.pry
  end

  def pickup_number(level) do
    level
    |> IO.inspect()
    |> get_range()
    |> IO.inspect()
    |> Enum.random()
  end

  def play(picked_num) do
    IO.gets("I have my number. What is your guess?")
    |> parse_input()
    |> guess(picked_num, 1)
  end

  # In the function 'guess()' is being used 'Guards' technique in Elixir
  def guess(usr_guess, picked_num, count) when usr_guess > picked_num do
    IO.gets("Your number is too high. Guess again: ")
    |> parse_input()
    |> guess(picked_num, count + 1)
  end

  def guess(usr_guess, picked_num, count) when usr_guess < picked_num  do
    IO.gets("Your number is too low. Guess again: ")
    |> parse_input()
    |> guess(picked_num, count + 1)
  end

  # the last option for 'guess()' (guards)
  def guess(_usr_guess, _picked_num, count) do # '_' underscore makes the arguments to be ignored
  IO.puts("You got it #{count} guess. ")
  show_score(count)
  end

  def show_score(guesses) when guesses > 6 do
    IO.puts("Better luck next time!")
  end

  def show_score(guesses) do
    {_, msg} = %{1..1 => "You're a mind rider!",
      2..4 => "Most impressive!",
      3..6 => "You can do better than that!"}
    |> Enum.find(fn {range, _} -> Enum.member?(range, guesses) end)
    IO.puts(msg)
  end

  # The function "parse-input" is defined twice (it could be more) because Elixir has this feature where is possible...
  #...to choose what the functions will be used based on its argument.

  # if the player set a non number a ":error" will come up, so the game will ru again after a message error.
  def parse_input(:error) do
    IO.inspect(label: ":erro")
    IO.puts("Invalid level!!!")
    run()
  end

  # if the player set a number, this number will be returned.
  def parse_input({num, _}), do: num #one line def function

  def parse_input(data) do
    data
    |> Integer.parse()
    |> IO.inspect()
    |> parse_input()
    |> IO.inspect()
  end

  def get_range(level) do
    case level do
      1 -> 1..10 # define a range in Elixir
      2 -> 1..100
      3 -> 1..1000
      # in case the player set a number higher than 3 (max level)
      _ -> IO.puts("Invalid level--------!!!")
      run()
    end
  end

  def teste() do
    IO.getn("dsdsd: ")
    |> IO.puts()
  end
end

Thank you for your support!

Looks like you use this code at application start.

That’s good for normal app start or script, but when your are using iex then IO.gets/1 is blocking shell. Running the game in supervised task also does not solves the problem.

The only way to “play” a game in iex (using IO.gets/1) is to call the code directly from shell instead of adding it to application supervisor tree. However in that case when starting app normally the game would not run.

Therefore I would suggest to check some args/environment variables, so for some runs simply start the game automatically and when using iex shell start the game manually, for example:

defmodule GuessGame do
  use Application

  def start(_,_) do
    if some_check_here do
      run()
    end

    {:ok, self()}
  end

  # …
end

iex> GuessGame.run()
1 Like

I could be wrong but I’m pretty sure that returning {:ok, self()} from start is also a problem. The application root needs to be an actual supervisor, not whatever pid is booting the app.

1 Like

Thank you guys for your helps.

I’ll try to use your tips.
As a beginner this problem is a bit complex than I expected, I thought that was only a beginner’s mistake.

I have a lot of basic things to learn in Elixir, mainly in Mix projects.

Thank you again!! :smiley:

Also, might I suggest using the 1.14 version of elixir and the new dbg features?

The IEX+dbg and pipeline debugging will make your live much better, and remove the need for the many inspects.
The videos on that link give a view of how it can help you.

1 Like