Packages

A simple utility to find codetags within a project

Current section

Files

Jump to
ex_todo lib file_utils.ex
Raw

lib/file_utils.ex

defmodule ExTodo.FileUtils do
@moduledoc """
Utililities for deals with files and searching for code tags.
"""
alias ExTodo.{Config, CodetagEntry}
@glob_pattern "./**"
@doc "Get all of the files according to the fileglob"
def get_all_files(%Config{} = config, file_glob \\ @glob_pattern) do
file_glob
|> Path.wildcard(match_dot: true)
|> Enum.reject(fn entry ->
not_file?(entry) or path_in_ignore_list?(entry, config.skip_patterns)
end)
end
@doc "Read the contents of all the files in the provided list"
def read_file_list_contents(file_list) do
file_list
|> Enum.reduce([], fn file_path, acc ->
file_path
|> File.read()
|> case do
{:ok, file_contents} ->
[{file_path, file_contents} | acc]
{:error, _reason} ->
acc
end
end)
end
@doc "Get all of the codetags within the list of files given the config settings"
def get_file_list_codetags(file_contents_list, %Config{} = config) do
file_contents_list
|> Enum.reduce([], fn {file_path, file_contents}, acc ->
file_contents
|> String.split("\n")
|> get_lines_with_codetags(config)
|> case do
[] ->
acc
codetag_entries ->
[{file_path, codetag_entries} | acc]
end
end)
end
defp path_in_ignore_list?(path, skip_patterns) do
Enum.find_value(skip_patterns, false, fn skip_pattern ->
Regex.match?(skip_pattern, path)
end)
end
defp not_file?(path), do: not File.regular?(path)
defp get_lines_with_codetags(file_contents, config) do
get_lines_with_codetags(file_contents, config, 1, [])
end
defp get_lines_with_codetags([], _config, _line_num, acc) do
Enum.reverse(acc)
end
defp get_lines_with_codetags([current_line | tail], config, line_num, acc) do
fuzzy_match_list =
config.supported_codetags
|> Enum.map(fn keyword ->
[
{keyword, "#{keyword}:"},
{keyword, "#{keyword} :"},
{keyword, "#{keyword}-"},
{keyword, "#{keyword} -"},
{keyword, keyword}
]
end)
|> List.flatten()
{original, keyword_in_line} =
Enum.find(fuzzy_match_list, {:not_found, :not_found}, fn {_original, keyword} ->
String.contains?(current_line, keyword)
end)
acc =
if keyword_in_line != :not_found do
comment =
current_line
|> String.split(keyword_in_line, parts: 2)
|> Enum.at(1)
|> String.trim()
[%CodetagEntry{type: original, line: line_num, comment: comment} | acc]
else
acc
end
get_lines_with_codetags(tail, config, line_num + 1, acc)
end
end