defmodule Mix.Tasks.Complete do
use Mix.Task
@shortdoc "Cache tab completions for mix"
def run(_) do
loadpaths!()
modules = load_tasks()
aliases = load_aliases()
docs = build_doc_list(modules, aliases)
text =
docs
|> Enum.sort()
|> Enum.map(fn {task, shortdoc} -> "#{task}\t#{shortdoc}" end)
|> Enum.join("\n")
# text = elem(System.shell("mix help --names"), 0)
cache_dir =
case System.get_env("XDG_CACHE_HOME") do
nil -> Path.join([System.get_env("HOME"), ".cache"])
"" -> Path.join([System.get_env("HOME"), ".cache"])
xdg_cache_home -> xdg_cache_home
end
if File.exists?("mix.exs") do
File.write(".mix_complete.cache", text)
IO.puts(:stderr, "cache updated in project directory")
else
File.write(Path.join([cache_dir, ".mix_complete.cache"]), text)
IO.puts(:stderr, "cache updated in #{cache_dir}")
end
end
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 load_tasks() do
Enum.filter(Mix.Task.load_all(), &(Mix.Task.moduledoc(&1) != false))
end
defp load_aliases() do
aliases = Mix.Project.config()[:aliases]
Map.new(aliases, fn {alias_name, alias_tasks} -> {Atom.to_string(alias_name), alias_tasks} end)
end
defp build_doc_list(modules, aliases) do
task_docs = build_task_doc_list(modules)
alias_docs = build_alias_doc_list(aliases)
task_docs ++ alias_docs
end
defp build_task_doc_list(modules) do
Enum.reduce(modules, [], fn module, docs ->
if doc = Mix.Task.shortdoc(module) do
task = Mix.Task.task_name(module)
[{task, doc} | docs]
else
docs
end
end)
end
defp build_alias_doc_list(aliases) do
Enum.reduce(aliases, [], fn {alias_name, _task_name}, docs ->
doc = "Alias defined in mix.exs"
task = alias_name
[{task, doc} | docs]
end)
end
end