Skip to content

Commit

Permalink
improvement: support csv option type and properly handle keep options…
Browse files Browse the repository at this point in the history
… lists
  • Loading branch information
zachdaniel committed Oct 14, 2024
1 parent addc035 commit ebe43a1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
3 changes: 2 additions & 1 deletion installer/lib/mix/tasks/igniter.new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ defmodule Mix.Tasks.Igniter.New do
end

install =
options[:install]
options
|> Keyword.get_values(:install)
|> List.wrap()
|> Enum.join(",")
|> String.split(",", trim: true)
Expand Down
47 changes: 47 additions & 0 deletions lib/mix/task.ex
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,54 @@ defmodule Igniter.Mix.Task do

argv = Igniter.Util.Info.args_for_group(argv, Igniter.Util.Info.group(info, task_name))

schema =
Enum.map(info.schema, fn
{k, :csv} ->
{k, :keep}

{k, v} ->
{k, v}
end)

{parsed, _} = OptionParser.parse!(argv, switches: info.schema, aliases: info.aliases)

parsed =
info.schema
|> Enum.filter(fn {_, type} ->
type == :keep
end)
|> Enum.reduce(parsed, fn {k, _}, parsed ->
parsed_without = Keyword.delete(parsed, k)

values =
parsed
|> Keyword.get_values(k)
|> List.wrap()

Keyword.put(parsed_without, k, values)
end)

parsed =
info.schema
|> Enum.reduce(parsed, fn
{k, :csv}, parsed ->
case Keyword.fetch(parsed, k) do
{:ok, value} ->
value
|> List.wrap()
|> Enum.flat_map(&String.split(&1, ",", trim: true))
|> then(fn v ->
Keyword.put(parsed, k, v)
end)

:error ->
parsed
end

_, parsed ->
parsed
end)

with_defaults = Keyword.merge(info.defaults, parsed)

Enum.each(info.required, fn option ->
Expand Down
27 changes: 24 additions & 3 deletions lib/mix/task/info.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Igniter.Mix.Task.Info do
## Configurable Keys
* `schema` - The option schema for this task, in the format given to `OptionParser`, i.e `[name: :string]`
* `schema` - The option schema for this task, in the format given to `OptionParser`, i.e `[name: :string]`. See the schema section for more.
* `defaults` - Default values for options in the schema.
* `required` - A list of flags that are required for this task to run.
* `positional` - A list of positional arguments that this task accepts. A list of atoms, or a keyword list with the option and config.
Expand All @@ -18,14 +18,35 @@ defmodule Igniter.Mix.Task.Info do
Your task should *always* use `switches` and not `strict` to validate provided options!
## Positonal Arguments
## Options and Arguments
To get the options (values for flags specified by the schema), use the `positional_args!/1` and `options!/` macros,
like so:
```elixir
def igniter(igniter, argv) do
{arguments, argv} = positional_args!(argv)
options = options!(argv)
...
end
```
## Options
The schema is an option parser schema, and `OptionParser` is used to parse the options, with
a few noteable differences.
- The defaults from the `defaults` option in your task info are applied.
- The `:keep` type is automatically aggregated into a list.
- The `:csv` option automatically splits the value on commas, and allows it to be specified multiple times.
## Positional Arguments
Each positional argument can provide the following options:
* `:optional` - Whether or not the argument is optional. Defaults to `false`.
* `:rest` - Whether or not the argument consumes the rest of the positional arguments. Defaults to `false`.
The value will be converted to a list automatically.
"""

@global_options [
Expand Down

0 comments on commit ebe43a1

Please sign in to comment.