defmodule Babylon do @moduledoc """ Documentation for Babylon. """ @doc """ Detecting languages in a project and calculate a percentage. ## Examples iex> Babylon.languages("/current/directory/path") %{ "API Blueprint" => 0.7, "CSS" => 0.3, "HTML" => 41.7, "JavaScript" => 1.6, "Ruby" => 55.5, "Shell" => 0.2 } """ @spec languages(Path.t()) :: map def languages(path) do path |> Babylon.Utils.all_files |> group_files_by_extension |> match_extension_with_language |> perсent_ratio end defp group_files_by_extension(files) do Enum.reduce(files, %{}, fn file, acc -> case Path.extname(file) do "" -> acc ext -> aggregate_files_size(file, ext, acc) end end) end defp aggregate_files_size(file, ext, acc) do %{size: size} = File.stat!(file) Map.update(acc, ext, size, &(&1 + size)) end defp match_extension_with_language(extensions) do {:ok, list_of_languages} = YamlElixir.read_from_file("#{__DIR__}/languages.yml") Enum.reduce(extensions, %{}, fn {extension, size}, acc -> language_info = Enum.find(list_of_languages, fn {_, info} -> Enum.member?(info["extensions"] || [], extension) end) case language_info do nil -> acc {language, _} -> Map.update(acc, language, size, &(&1 + size)) end end) end defp perсent_ratio(evaluation) do sum = Enum.reduce(evaluation, 0, fn {_language, size}, acc -> size + acc end) {languages, _} = Enum.map_reduce(evaluation, 0.0, fn {language, size}, acc -> percent = (size / sum) * 100; { {language, Float.round(acc + percent, 1), Float.round(acc, 1)}, acc + percent } end) languages |> Enum.map(fn {language, round_sum, prev_sum} -> {language, Float.round(round_sum - prev_sum, 1)} end) |> Enum.filter(fn {_language, percent} -> percent >= 0.1 end) |> Enum.into(%{}) end end