Igniter - A code generation and project patching framework

mix igniter.new new_project --install your_generators --components foo,bar,baz would be a one liner that does it. You’d make an installer task (you can generate one with mix igniter.gen.task your_generators.install), and your installer would have a components option, and the installer would look something like this:

def igniter(igniter, argv) do
  # there is another place where your schema is defined that populates this
  options = options!(argv) 

  Enum.reduce(options[:components], igniter, fn component, igniter ->
    Igniter.compose_task("your_generators.add_component", [component])
  end)
end

EDIT if you want a new project using phoenix

mix igniter.new new_project --with phx.new --install your_generators --components foo,bar,baz
2 Likes

Excellent! This feels like a real Captain Planet situation.

1 Like

Ok I’m cooking now, making good progress. One issue I’ve stumbled on is copying HEEx templates, which have EEx tags like <%= render_slot(@inner_block) %>. When I call Igniter.copy_template/5, the code is executed though it needs to be rendered as-is. I tried wrapping the tag in <%% ... %> but Mix/Igniter still attempts to execute the render_slot/1 function.

Since there’s no Igniter.copy_file function, would I need to read the template’s contents and use Igniter.create_new_file/4?

PS: Should I break out a separate topic? I realized this one may be intended for updates.

EDIT: This works: <%%= render_slot(@inner_block) %> :sweat_smile:

1 Like

Yeah, perhaps from here on we can use a different channel. We also have an igniter channel in the Ash discord if you’d like to use that :slight_smile: Given that igniter is a tool meant for the wider ecosystem we could also have a channel in the slack/discord for informal chats, etc.

1 Like

It’ll be nice to find these posts in 6 months when I’m searching for answers, so I choose this silo. If I run into more hiccups, I’ll open a new topic.

I’ve gotta say, writing Igniter tasks is fun. Looking forward to going deeper with the other modules. :tada: Good work!

2 Likes

That is the right choice :sweat_smile: I should probably not really suggest the really silo’d platforms if people aren’t explicitly asking for them. I want people to use ElixirForum but I also would rather them participate in a silo than not at all… Its a tricky balance :laughing:

1 Like

Igniter’s first project-wide refactoring tool!

Rename functions everywhere across your project with one command :sunglasses:
This can also be used by library maintainers in their upgrade scripts
to automatically move users off of deprecated functions.

mix igniter.refactor.rename_function \
  Igniter.Code.List.list \
  Igniter.Code.List.is_a_list \
  --deprecate hard

Speaking of upgrade scripts…

We just released :fire: mix igniter.upgrade :fire:

This command is a drop in replacement for mix deps.update,
except it hooks into any upgrade scripts provided by libraries
that use Igniter! We’re still testing it out, but this also ships
with a --git-ci flag and instructions on how to set up dependabot
to run mix igniter.upgrade automatically :robot:. Think Laravel shift
but free, leveraging our already excellent build tool mix!

mix igniter.upgrade ash 

It is still early days, and there will be plenty of rough edges
to sand down, but I truly believe that igniter can play a massive
part in improving the DX around building Elixir applications.

Igniter now provides a fit-for-purpose framework for:

  • Installers
  • Generators
  • Refactoring tools
  • Custom code patching
  • Upgrade scripts

All that is left is for us to spread it into the ecosystem
Even without adoption, it is useful for end-users as it is today

Happy hacking :sunglasses:

16 Likes

We’ve made an update to igniter in 0.4.x that changes slightly how you write tasks.

It is a very small update, but adds a convenience around dealing with options and arguments.

It’s “soft deprecated” for now, it won’t warn, but eventually it will. Essentially, instead of:

def igniter(igniter, argv) do
  {arguments, argv} = positional!(argv)
  options = options!(argv)
end

you can now do

def igniter(igniter) do
  # positional args are in 
  igniter.args.positional
  # options are in 
  igniter.args.options
  # argv without positional args (for composition) are in 
  igniter.args.argv_flags`
  # raw argue are in 
  igniter.args.argv

  ...
end

Additionally, mix igniter.upgrade in 0.3.x had some issues that may make it not work, so manual upgrade to 0.4.x will likely be required. More on that in the readme.

3 Likes