defmodule Mix.Tasks.Bloom.Install do @moduledoc "Mix task to install components from the Bloom library" use Mix.Task @doc """ Run the mix task with the component name as an argument to install the component. ## Examples iex> Mix.Tasks.Bloom.Install.run(["component_name"]) "component_name component installed successfully." iex> Mix.Tasks.Bloom.Install.run(["nonexistent_component"]) "Component not found: nonexistent_component" """ @impl true def run(args) do case args do ["help"] -> print_usage_and_components() [component_name] -> if component_exists?(component_name) do install_component(component_name) else IO.inspect("what?") Mix.shell().error("Component not found: #{component_name}") print_usage_and_components() end _ -> print_usage_and_components() end end def install_component(file_name) do project_name = Mix.Project.config()[:app] |> Atom.to_string() |> String.downcase() case retrieve_source_code(file_name) do {:ok, source_code} -> component_dir = component_dir(project_name) File.mkdir_p(component_dir) target_path = "#{component_dir}/#{file_name}.ex" module_name = project_name |> Macro.camelize() updated_source_code = Regex.replace(~r/Bloom\.Components/, source_code, "#{module_name}Web.Components") File.write!(target_path, updated_source_code) Mix.shell().info("#{file_name} component installed successfully.") {:error, reason} -> Mix.shell().info("Error: #{reason}") end end def retrieve_source_code(file_name) do bloom_path = Path.join(File.cwd!(), "deps/bloom") if File.dir?(bloom_path) do source_file = Path.join([bloom_path, "lib/bloom/components/#{file_name}.ex"]) if File.exists?(source_file) do {:ok, File.read!(source_file)} else {:error, "Source file not found: #{source_file}"} end else {:error, "Bloom dependency not found"} end end defp component_dir(app_name), do: "lib/#{app_name}_web/components" |> String.downcase() defp print_usage_and_components do Mix.shell().info("Usage: mix bloom.install [component_name]") Mix.shell().info("Available components: glow_button") end defp component_exists?(file_name) do # Check if Bloom is running as a dependency if Code.ensure_loaded?(Bloom) and function_exported?(Bloom, :__info__, 1) do env = Mix.env() |> Atom.to_string() # Path when Bloom is used as a dependency source_file = "_build/#{env}/lib/bloom/components/#{file_name}.ex" IO.inspect(source_file, label: "source_file") File.exists?(source_file) else # Path when running within the Bloom project itself source_file = "lib/bloom/components/#{file_name}.ex" IO.inspect(source_file, label: "from bloom") File.exists?(source_file) end end end