How do I convert this code to a Mix project?

I have started this simple Elixir project and my goal is to turn it into a Mix project which when run, will list out the templates and prompt me to set values for them. I am to use run it in aiex which I expect to display the parameter values than start prompting for them. I later want to run it as an escript which will do the same thing.

How do I set up the details of the mix project to run it under iex?

PS. Does the forum offer a way to embed Github gists?

defmodule ParamStruct do                                                                                                                         
  defstruct key: "", value: "", default: "", description: "description of parameter", label: "label on web form", required: false, order: 99     
end                                                                                                                                              
                                                                                                                                                 
defmodule TemplateStruct do                                                                                                                      
  defstruct key: "must be unique", name: "descriptive name", code: "", executable: false, destination: "", delete_after: false,                  
  perms: "644"                                                                                                                                   
end                                                                                                                                              
                                                                                                                                                 
defmodule ProcessList do                                                                                                                         
  def parse_list([]), do: []                                                                                                                     
                                                                                                                                                 
  def parse_list([%{"key" => ky,"value" => val,"default" => dft, "description" => desc,"label" => lbl} | tail]) do
    [%ParamStruct{key: ky, value: val, description: desc, label: lbl, default: dft } | parse_list(tail) ]
  end                                                                                                                                            
                                                                                                                                                 
  def create_recommend_list(%{"itemScores" => score_list})  do                                                                                   
    parse_list(score_list)                                                                                                                       
  end                                                                                                                                            
end   
    
params = [                                                                                                                                     
%{"key" => "ca_cert_subj_state","value" => "Greater London","default" => "Greater London","description" => "Region","label" => "State/County"},                
  %{"key" => "key-file","value" => "cacert_001","default" => "cacert_001","description" => "","label" => "Key File (without password)"},                   
  %{"key" => "key-file-pass","value" => "cacert_pass_001","default" => "cacert_pass_001","description" => "","label" => "Key File (with password)"},            
  %{"key" => "ca_cert_email","value" => "admin@domain.net","default" => "admin@domain.net","description" => "","label" => "Email"},                              
  %{"key" => "ca_cert_subj_common_name","value" => "Elixir User","default" => "domain.net","description" => "","label" => "Common Name"},                   
  %{"key" => "ca_cert_subj_country","value" => "UK","default" => "UK","description" => "Country","label" => "Country"},                            
  %{"key" => "ca_cert_subj_location","value" => "Manchester","default" => "Westchester","description" => "","label" => "Location"},                        
  %{"key" => "ca_cert_subj_organization","value" => "Elixir Programs Forum","default" => "Big Company","description" => "","label" => "Organisation"},                
  %{"key" => "ca_cert_subj_org_unit","value" => "IT Department","default" => "Infosystems and Communications","description" => "","label" => "Organisational Unit"}                                                                                                                                            
  ]          

sslCmd = """
openssl req -x509 -new -nodes -sha256 \
 -key {{key-file-pass}}.key \
 -days 3650 \
 -out {{key-file-pass}}.pem \
 -subj ""\
/C={{ca_cert_subj_country}}\
/ST={{ca_cert_subj_state}}\
/L={{ca_cert_subj_location}}\
/O={{ca_cert_subj_organization}}\
/OU={{ca_cert_subj_org_unit}}\
/CN={{ca_cert_subj_common_name}}\
/emailAddress={{ca_cert_email}}\
"""

structList = ProcessList.parse_list(params)  
#IO.inspect ProcessList.parse_list(params)
# [first | _ ] = ProcessList.parse_list(params)
# IO.puts " #{first.key} is #{first.value} "

# IO.inspect first
IO.puts sslCmd
IO.puts "list of keys and values"
IO.puts "======================="
Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> IO.puts " #{x.key} is #{x.value} " end) 

IO.puts "list of keys and values - again"
IO.puts "======================="
Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> IO.puts " #{x.key} is #{x.value} " end) 


x = Enum.at(structList, 0)
IO.inspect x
IO.puts " #{x.key} is #{x.value} "
sslCmd2 = String.replace(sslCmd, "{{#{x.key}}}", x.value)
IO.puts "output enum now"
IO.puts "==============="

sslCmd = Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> 
    String.replace(sslCmd, "{{#{x.key}}}", x.value)
  end)
# Works now after avoiding sslCmd assignment within loop 

IO.puts "sslCmd2"
IO.puts "======================="
IO.puts sslCmd2

IO.puts "sslCmd"
IO.puts "======================="
IO.puts sslCmd

  %{"key" => "ca_cert_subj_organization","value" => "Elixir Programs Forum","default" => "Big Company","description" => "","label" => "Organisation"},                
  %{"key" => "ca_cert_subj_org_unit","value" => "IT Department","default" => "Infosystems and Communications","description" => "","label" => "Organisational Unit"}                                                                                                                                            
  ]          

sslCmd = '''
openssl req -x509 -new -nodes -sha256 \
 -key {{key-file-pass}}.key \
 -days 3650 \
 -out {{key-file-pass}}.pem \
 -subj "\
/C={{ca_cert_subj_country}}\
/ST={{ca_cert_subj_state}}\
/L={{ca_cert_subj_location}}\
/O={{ca_cert_subj_organization}}\
/OU={{ca_cert_subj_org_unit}}\
/CN={{ca_cert_subj_common_name}}\
/emailAddress={{ca_cert_email}}\

'''
  structList = ProcessList.parse_list(params)  
  #IO.inspect ProcessList.parse_list(params)
  # [first | _ ] = ProcessList.parse_list(params)
  # IO.puts " #{first.key} is #{first.value} "
    
  # IO.inspect first
  IO.puts sslCmd
    
   Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> IO.puts " #{x.key} is #{x.value} " end) 
 
   #This code causes a syntax error 
   Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> String.replace(sslCmd, "{{"<> x.key <> "}}", x.value) end)

Closest way is just linking to it, which will truncate it sadly:

iex is a shell/repl, if you want prompts then you need to call a function in the shell that would then prompt you (otherwise overlapping prompts really suck).

Have you already setup an escript project?

To run a mix project in iex you just start iex like iex -S mix, or are you needing something more specific?

I want to know what should go in the mix.exs application function, ie mod stanza. I am not sure where the entry point for prompting for user input should go, and if that should go in the mod stanza or what should be in the start function of the applicaion. Concepts in mix are quite different from what I am used to.

I know of main functions in languages like Java and Pascal where the program’s main loop begins.

When you create the project with Mix, it will use the name you provide for the application and create a module from it. It will then set up the mix.exs to use that module’s start function. It will create code for the module and even give you a basic start function there. You should be able to copy your module into the lib folder, and call it from the start function that Mix has written for you.

Try it with a test project,

2 Likes