igniter/lib/mix/tasks/igniter.gen.task.ex

199 lines
5.6 KiB
Elixir

defmodule Mix.Tasks.Igniter.Gen.Task do
use Igniter.Mix.Task
@example "mix igniter.gen.task my_app.install"
@shortdoc "Generates a new igniter task"
@moduledoc """
#{@shortdoc}
## Example
```bash
#{@example}
```
## Options
* `--optional` or `-o` - Whether or not to define the task to be compatible with igniter as an optional dependency.
"""
def info(_argv, _source) do
%Igniter.Mix.Task.Info{
example: @example,
positional: [:task_name],
schema: [optional: :boolean],
aliases: [o: :optional]
}
end
def igniter(igniter, argv) do
{%{task_name: task_name}, argv} = positional_args!(argv)
options = options!(argv)
module_name = Module.concat(Mix.Tasks, Mix.Utils.command_to_module_name(to_string(task_name)))
contents =
if options[:optional] do
optional_template(module_name, task_name)
else
template(module_name, task_name)
end
file = "lib/mix/tasks/#{task_name}.ex"
if Igniter.exists?(igniter, file) do
Igniter.add_issue(
igniter,
"Could not generate task #{task_name}, as `#{file}` already exists."
)
else
Igniter.create_new_file(igniter, file, contents)
end
end
defp template(module_name, task_name) do
"""
defmodule #{inspect(module_name)} do
use Igniter.Mix.Task
@example "mix #{task_name} --example arg"
@shortdoc "A short description of your task"
@moduledoc \"\"\"
\#{@shortdoc}
Longer explanation of your task
## Example
```bash
\#{@example}
```
## Options
* `--example-option` or `-e` - Docs for your option
\"\"\"
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
# dependencies to add
adds_deps: [],
# dependencies to add and call their associated installers, if they exist
installs: [],
# An example invocation
example: @example,
# Accept additional arguments that are not in your schema
# Does not guarantee that, when composed, the only options you get are the ones you define
extra_args?: false,
# A list of environments that this should be installed in, only relevant if this is an installer.
only: nil,
# a list of positional arguments, i.e `[:file]`
positional: [],
# Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv
# This ensures your option schema includes options from nested tasks
composes: [],
# `OptionParser` schema
schema: [],
# CLI aliases
aliases: []
}
end
def igniter(igniter, argv) do
# extract positional arguments according to `positional` above
{arguments, argv} = positional_args!(argv)
# extract options according to `schema` and `aliases` above
options = options!(argv)
# Do your work here and return an updated igniter
igniter
|> Igniter.add_warning("mix #{task_name} is not yet implemented")
end
end
"""
end
defp optional_template(module_name, task_name) do
"""
defmodule #{inspect(module_name)} do
@example "mix #{task_name} --example arg"
@shortdoc "A short description of your task"
if !Code.ensure_loaded?(Igniter) do
@shortdoc "\#{@shortdoc} | Install `igniter` to use"
end
@moduledoc \"\"\"
\#{@shortdoc}
Longer explanation of your task
## Example
```bash
\#{@example}
```
## Options
* `--example-option` or `-e` - Docs for your option
\"\"\"
if Code.ensure_loaded?(Igniter) do
use Igniter.Mix.Task
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
# dependencies to add
adds_deps: [],
# dependencies to add and call their associated installers, if they exist
installs: [],
# An example invocation
example: @example,
# Accept additional arguments that are not in your schema
# Does not guarantee that, when composed, the only options you get are the ones you define
extra_args?: false,
# A list of environments that this should be installed in, only relevant if this is an installer.
only: nil,
# a list of positional arguments, i.e `[:file]`
positional: [],
# Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv
# This ensures your option schema includes options from nested tasks
composes: [],
# `OptionParser` schema
schema: [],
# CLI aliases
aliases: []
}
end
def igniter(igniter, argv) do
# extract positional arguments according to `positional` above
{arguments, argv} = positional_args!(argv)
# extract options according to `schema` and `aliases` above
options = options!(argv)
# Do your work here and return an updated igniter
igniter
|> Igniter.add_warning("mix #{task_name} is not yet implemented")
end
else
use Mix.Task
def run(_argv) do
Mix.shell().error(\"\"\"
The task '#{task_name}' requires igniter to be run.
Please install igniter and try again.
For more information, see: https://hexdocs.pm/igniter
\"\"\")
exit({:shutdown, 1})
end
end
end
"""
end
end