Green
An Elixir code formatter.
Currently, it can enforce lexmag's Elixir style guide.
Motivation
The standard Elixir formatter only enforces a small number of certain rules. This project aims to enforce enough rules so that the "house style" of a project can be enforced by the formatter.
Name
The name "Green" is a reference to bikeshedding, i.e. "All bike shed shoul be green."
Status
Currently, Green provides Green.Lexmag.ElixirStyleGuideFormatter
which,
as far as is possible, implements the rules of lexmag's style guide
that are not already implemented by mix format
.
Limitations
Two rules change the order of lines:
PreferPipelines
groupsuse
,import
,assign
andrequire
statements,RemoveNilFromStructDefinition
places the list ofnil
-default fields at the top of the struct definition.
Where possible, when shifting lines around, Green will try to keep associated comments with the lines that follow them. However, this is not always possible. Please check the output of the formatter to ensure that comments are in the correct place.
Roadmap
Implement the other well-known Elixir style guides:
Lexmag.ElixirStyleGuideFormatter
Usage
Add the following to your mix.exs
:
defp deps do
[
{:green, "~> (See the badge above)"}
]
end
Modify .formatter.exs
to include the following:
[
plugins: [Green.Lexmag.ElixirStyleGuideFormatter]
]
Limitations
Some rules cannot be enforced by a formatter. For example, the rule that comments should be critical. This is a matter of opinion and cannot be automatically enforced.
The implemented rules are marked with a check ✓
.
When it is possible to transform the code to match the style guide, Green will do so. However, it is not always possible to do so. In these cases, Green will leave the code as it is and print a warning.
Linting
- [x] Transform nested function calls into pipelines (L1),
- [x] Transform one-element pipelines into function calls (L2),
❔ Don't use anonymous functions in pipelines (L3),
- [x] Transform
unless...else...
intoif...else...
(L4), - [x] Transform
if...else nil
intoif...
(L5), - [x] Ensure match-all condition of
cond
hastrue
(L6),
❔ Use and
and or
instead of &&
and ||
when the arguments are boolean (L7),
- [x] Use
<>
instead of bitstrings when pattern-matching binaries (L8).
Naming
- [x] Enforce snake_case for atoms, functions, variables, attributes (N1),
NO Enforce CamelCase for modules (N2),
❔ Enforce predicate functions to end with a question mark (N3),
Comments
❔ Use only critical comments (C1),
❔ Avoid superfluous comments (C2).
Modules
- [x] Group and order
use
,import
,assign
andrequire
statements (M1), - [x] Replace the current module name with
__MODULE__
(M2).
Notes:
- M1:
This transformation does not take into account comments. Any comment before
or on the same line as a
use
,import
,assign
orrequire
statement will be left where it is.
Regular Expressions
❔ Prefer pattern matching over regular expressions (R1),
❔ Use non-capturing regular expressions (R2).
Structs
- [x] Don't specify
nil
default values fordefstruct
fields (S1).
Exceptions
- [x] Use
Error
suffix for exception names (E1),
❔ Use non-capitalized error messages (except for Mix error messages) without trailing punctuation (E2).
ExUnit
❔ Put the expression being tested by comparison on the left side (U1).