Skip to content

Instantly share code, notes, and snippets.

@jakubpawlowicz
Created November 14, 2023 11:02
Show Gist options
  • Save jakubpawlowicz/3098c8fa9f63ef2248f320d61a9e758a to your computer and use it in GitHub Desktop.
Save jakubpawlowicz/3098c8fa9f63ef2248f320d61a9e758a to your computer and use it in GitHub Desktop.
Elixir script fixing indentation by replacing leading tabs with spaces

Usage

elixir fix.exs glob/wildcard/pattern

e.g.

elixir fix.exs project/\*\*/\*.eex

fixes whitespace in EEx files.

Note proper escaping of asterisk characters, otherwise some shells (like bash) may expand the wildcard before it reaches Elixir code.

defmodule Fix do
require Logger
@tab_as_spaces " "
@whitespace_pattern ~r/^(\s+)/
@spec process(String.t()) :: :ok
def process(filename) do
Logger.info(fn -> "Processing file #{filename}..." end)
filename
|> File.read!()
|> String.split("\n")
|> Enum.map(&normalize_leading_whitespace/1)
|> Enum.join("\n")
|> Kernel.tap(& File.write!(filename, &1))
:ok
end
@spec normalize_leading_whitespace(String.t()) :: String.t()
defp normalize_leading_whitespace(line) do
String.replace(line, @whitespace_pattern, &tabs_to_spaces/1)
end
@spec tabs_to_spaces(String.t()) :: String.t()
defp tabs_to_spaces("\t" <> rest) do
@tab_as_spaces <> tabs_to_spaces(rest)
end
defp tabs_to_spaces(<<whitespace::bytes-size(1)>> <> rest) do
whitespace <> tabs_to_spaces(rest)
end
defp tabs_to_spaces("") do
""
end
end
System.argv()
|> List.first()
|> Path.wildcard()
|> Enum.reject(& String.contains?(&1, "_build"))
|> Enum.reject(& String.contains?(&1, "deps"))
|> Enum.each(&Fix.process/1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment