Can't run IO.inspect(args) in the first main(args) line

defmodule Createproj do
  @moduledoc """
  Documentation for `Createproj`.
  """
  def print_help do
    IO.puts(
      "Usage: newP" <>
        " -f filepath: creates a new project\n" <>
        "-b: adds boilerplate\n"
    )
  end

  def write_boilerplate(project_name) do
    file_name = project_name <> ".ex"
    file_path = Path.join([project_name, file_name])
    boilerplate = "defmodule #{project_name} do\nend"
    File.write(file_path, boilerplate, [:append])
  end

  def get_filename(args) do
    Enum.with_index(args)
    |> Enum.find(fn {arg, index} -> arg == "-f" and index < length(args) - 1 end)
    |> case do
      {_, index} ->
        Enum.at(args, index + 1)

      {nil} ->
        nil
    end
  end

  def create_folder(project_name, file_name \\ "") do
    folder_path = Path.join([project_name, file_name])

    File.mkdir(folder_path)
    |> case do
      :ok -> IO.puts("created#{folder_path}")
      {_, _} -> IO.puts("failed to make #{file_name}")
    end
  end

  def main(args) do
    IO.inspect(args)
    new_file = Enum.member?(args, "-f")
    boilerplate = Enum.member?(args, "-b")

    cond do
      new_file and not boilerplate ->
        project_name = get_filename(args)
        create_folder(project_name)
        create_folder(project_name, "/lib")
        create_folder(project_name, "/test")

      new_file and boilerplate ->
        project_name = get_filename(args)
        create_folder(project_name)
        create_folder(project_name, "/lib")
        create_folder(project_name, "/test")
        write_boilerplate(project_name)

      true ->
        print_help()
    end
  end
end

compilation works great but when I run:

~/projects ./createproj -f dio -b
** (MatchError) no match of right hand side value: "dio"
    (createproj 0.1.0) lib/createproj.ex:33: Createproj.main/1
    (elixir 1.18.1) lib/kernel/cli.ex:137: anonymous fn/3 in Kernel.CLI.exec_fun/2

If I run it from the iex like this:

Createproj.main(["-f", "cane", "-b"])
["-f", "cane", "-b"]
createdcane
createdcane/lib
createdcane/test
:ok

as you can see everything works… any idea what’s going on?

I have tried this in newly generated project. I have only added escript: [main_module: Createproj] to Keyword returned in project function inside mix.exs and it works as expected. We would need something more to see where is the problem as for now I cannot reproduce it.

1 Like

Line 33 of what you posted isn’t in main and couldn’t raise a MatchError anyways:

folder_path = Path.join([project_name, file_name])

My guess is that a compiled version of Createproj is running, confusing the situation.

2 Likes

what else can i provide to help you understand? i already had that line in mix.exs so i am even more confused now

i rebooted and run it but still happens so it is impossible

IMO you’re better off publishing a GitHub project demonstrating the issue at this point.

The BEAM caches compiled bytecode to disk when it reads .ex files, so rebooting will not make a difference. Usually the advice is to remove the _build folder, but I’m not sure where that lives for escripts.

1 Like

Heh, ya, rm -rf _build deps is the general “turn it off an on again” for Mix projects. The nuclear option is rm -rf _build deps ~/.hex though in six years of Elixiring that has only been necessary once (and I can’t even remember why).

If this is an escript, you need to rebuild the escript after each change you make.

2 Likes

It’s as nuclear as rm -rf ~/.config - I would definitely not recommend that … In this directory there are:

  1. docs - cached docs, so (in very short) just HTML stuff
  2. packages - cached package archives (when fetching dependencies for every project)
  3. hex.config - auth file used when for example you publish a package or send it’s new version
  4. cache.ets - I don’t remember now what’s for, so at in best case this should be the only cache file to remove

So removing this directory developer would have to sign in again in CLI and download again all deps and their docs for every project.

When compiling project in many cases a cache is saved in some directory in ~/.cache folder (make sure to not remove the entire directory). Also in ~/.cache/mix there is installs directory and it’s used when calling Mix.install/1 in scripts and iex. Same deps for different Elixir and Erlang versions are fetched and compiled in separate directories like elixir-1.18.1-erts-15.2. There all “installs” used in Mix.install/1 are stored separately by generated hash of packages passed to this function. Therefore if you work always on latest versions only you may (but not need to) remove all directories in ~/.cache/mix/installs/ except the one for your latest version.

Other directories that you may be interested is ~/.cache/erlang-history which stores not only data for Erlang, but also Elixir.

Yeah, that reminds me I had similar fails - they happened way too often … :sweat_smile:

that’s it anyway there’s nothing more than what i shared

my file is a .ex not exs. And that folder is not present in my project root folder

thanks a lot i’m still gaining familiarity with mix and somehow my brain thought running elixirc was the right way of doing this.

for future readers:

mix escript.build

is what it is supposed to be run

elixirc createproj

is what i was running and this is why my folder tree didn’t look look like what it should (no _build folder) and why i was getting the error. what i can’t understand is why did this happen?
aren,t exs made for escript build and ex for elixirc?