Packages

A mix task that counts directories, files, lines of code, modules, functions etc and displays the results.

Current section

Files

Jump to
mix_info lib mix tasks info.ex
Raw

lib/mix/tasks/info.ex

defmodule Mix.Tasks.Info do
use Mix.Task
@shortdoc "Display project code info"
@moduledoc """
A mix task to display code information like number of modules, functions,
lines of codes etc
"""
def run([]) do
#info is used as an accumulator
scanned_dirs = ["lib", "test"]
info =
scanned_dirs
|> Enum.map(&process_dir/1)
|> merge_results
display(info)
end
defp process_dir(path) do
case File.ls(path) do
{:ok, content} ->
#files
files = content
|> Enum.map(&(Path.join(path, &1)))
|> Enum.filter(&(not File.dir?(&1)))
#process files
files_info = files
|> Enum.map(&process_file/1)
|> merge_results
#dirs
dirs_info = content
|> Enum.map(&(Path.join(path, &1)))
|> Enum.filter(&File.dir?/1)
|> Enum.map(&process_dir/1)
|> merge_results
merge_results([[dirs: 1], dirs_info, files_info])
{:error, :enoent} -> Mix.Shell.IO.error("#{path} No such file or directory")
end
end
defp process_file(path) do
File.stream!(path)
|> Enum.map(fn(line) ->
striped = String.strip(line)
#Assumption comments are in their own lines
res = cond do
striped =~ ~r/#/ -> [comments: 1]
striped =~ ~r/^defmodule/ -> [modules: 1]
striped =~ ~r/^defp/ -> [private_functions: 1]
striped =~ ~r/^def/ -> [functions: 1]
true -> []
end
merge_results(res, [lines: 1])
end)
|> merge_results
|> merge_results [files: 1]
end
# Display the results in a nice formatted way
defp display(info) when is_list(info) do
config = Mix.Project.config
IO.puts(IO.ANSI.white <> "Application : " <> IO.ANSI.yellow <> "#{config[:app]}")
IO.puts(IO.ANSI.white <> "version : " <> IO.ANSI.green <> "#{config[:version]}")
IO.puts(IO.ANSI.white <> "directories : " <> IO.ANSI.blue <> "#{info[:dirs]}")
IO.puts(IO.ANSI.white <> "files : " <> IO.ANSI.red <> "#{info[:files]}")
IO.puts(IO.ANSI.white <> "lines : " <> IO.ANSI.yellow <> "#{info[:lines]}")
IO.puts(IO.ANSI.white <> "modules : " <> IO.ANSI.magenta <> "#{info[:modules]}")
IO.puts(IO.ANSI.white <> "functions : " <> IO.ANSI.green <> "#{info[:functions]}")
IO.puts(IO.ANSI.white <> "private functions : " <> IO.ANSI.red <> "#{info[:private_functions]}")
IO.puts(IO.ANSI.white <> "comments : " <> IO.ANSI.cyan <> "#{info[:comments]}")
end
# merge a list of results(keyword lists)
defp merge_results(res) when is_list(res) do
Enum.reduce(res, Keyword.new, &merge_results/2)
end
#merge two keyword lists containing results
defp merge_results([], []), do: []
defp merge_results([], res), do: res
defp merge_results(res, []), do: res
defp merge_results(res1, res2) do
Keyword.merge(res1, res2, fn(_, v1, v2) -> v1+v2 end)
end
end