Current section

Files

Jump to
membrane_core lib mix tasks membrane.gen.component.ex
Raw

lib/mix/tasks/membrane.gen.component.ex

[Filter, Endpoint, Sink, Source, Bin, Pipeline]
|> Enum.map(fn component_type ->
component_name = inspect(component_type)
defmodule Module.concat(Mix.Tasks.Membrane.Gen, component_type) do
@shortdoc "Generates a template for a Membrane #{component_name}"
@moduledoc """
Generates a template for a Membrane #{component_name} with the provided module name.
$ mix membrane.gen.#{String.downcase(component_name)} module_name [-l target_location]
## Options
* `-l, --location` - If a target location is provided, the #{component_name} will be created there, relative to the `lib` directory.
The filename must also be present and have an `.ex` extension. If location is not provided, then it will be
inferred from the provided module name - it will be converted to lowercase and `.` separators will be interpreted
as directory separators. For example, a #{component_name} with module name `Foo.Bar` will be created at `lib/foo/bar.ex`.
"""
use Mix.Task
@switches [location: :string]
@aliases [l: :location]
@impl true
def run(argv) do
do_run("lib", argv)
end
@spec do_run(binary(), [binary()]) :: any()
def do_run(base_dir, argv) do
{option, argv} = OptionParser.parse!(argv, aliases: @aliases, strict: @switches)
module_name =
case argv do
[] ->
Mix.raise("""
Module name not provided.
This task expects a module name for the newly created #{unquote(component_type)}:
$ mix membrane.gen.#{String.downcase(unquote(component_name))} My#{unquote(component_name)}
""")
[module_name | _rest] ->
module_name
end
if not valid_module_name?(module_name) do
Mix.raise("""
Invalid module name, please provide a valid one.
(no other special characters than dots are allowed and the module name as well as dot-separated segments in it must start with uppercase letters).
""")
end
component_path =
case option do
[] -> Macro.underscore(module_name) <> ".ex"
[{:location, path} | _rest] -> path
end
|> then(&Path.join(base_dir, &1))
component_path |> Path.dirname() |> File.mkdir_p!()
File.write!(component_path, get_component(module_name))
end
defp get_component(module_name) do
template =
"../../../templates"
|> Path.expand(__DIR__)
|> Path.join(Macro.underscore(unquote(component_type)) <> ".ex")
|> File.read!()
template
|> String.split("\n")
|> List.replace_at(0, "defmodule #{module_name} do")
|> Enum.join("\n")
end
@spec valid_module_name?(String.t()) :: boolean()
defp valid_module_name?(name) do
case Code.string_to_quoted(name) do
{:ok, {:__aliases__, _metadata, _name}} -> true
_other -> false
end
end
end
end)