defmodule Mix.Tasks.Cascade.Help do @shortdoc "Lists available templates or prints the documentation for a given template" @moduledoc """ Lists available templates or prints the documentation for a given template. ## Usage $ mix cascade.help - prints all available templates and their short description $ mix cascade.help TEMPLATE - prints full docs for the given template """ use Mix.Task @impl Mix.Task def run([]) do loadpaths!() Mix.shell().info("The following templates are available:") Mix.shell().info("") list_templates() Mix.shell().info("") Mix.shell().info([ "Run ", :yellow, "mix cascade NAME", :reset, " to generate code from the given template" ]) Mix.shell().info([ "Run ", :yellow, "mix cascade.help NAME", :reset, " to see help for a specific template" ]) end def run(["-" <> _arg]) do Mix.raise( ~s'Unexpected arguments, expected "mix cascade.help" or "mix cascade.help TEMPLATE"' ) end def run([template]) do loadpaths!() templates = Cascade.templates() case templates[String.to_atom(template)] do nil -> Mix.raise( "No template `#{template}` found. Run \"mix cascade.help\" to get a list of available templates" ) module -> docs = Cascade.Template.moduledoc(module) || "" opts = [width: 80, enabled: IO.ANSI.enabled?()] IO.ANSI.Docs.print_headings(["mix cascade #{template}"], opts) IO.ANSI.Docs.print(docs, "text/markdown", opts) end end def run(_other) do Mix.raise( ~s'Unexpected arguments, expected "mix cascade.help" or "mix cascade.help TEMPLATE"' ) end # Loadpaths without checks because templates may be defined in deps. defp loadpaths! do args = ["--no-elixir-version-check", "--no-deps-check", "--no-archives-check"] Mix.Task.run("loadpaths", args) Mix.Task.reenable("loadpaths") Mix.Task.reenable("deps.loadpaths") end defp list_templates do templates = Cascade.templates() |> Enum.sort_by(fn {name, _module} -> name end) |> Enum.map(fn {name, module} -> {Atom.to_string(name), shortdoc(module)} end) max = templates |> Enum.map(fn {name, _doc} -> byte_size(name) end) |> Enum.max() templates |> Enum.map(fn {name, doc} -> [" ", :bright, :cyan, String.pad_trailing(name, max), :reset, " # ", doc] end) |> Enum.each(fn line -> Mix.shell().info(line) end) end defp shortdoc(module) do case Cascade.Template.shortdoc(module) do nil -> "" shortdoc -> shortdoc end end end