Efmt - Erlang code formatter

Hi all,

Let me share about a new Erlang code formatter efmt that just released v0.1.0.

Features

  • Opinionated: only maximum line length is configurable by users
  • Emacs Erlang Mode friendly indentation
  • Preserves non-whitespace tokens of the original text as-is
    • Ensures the code after formatting keeps the same semantic meaning
  • Provides a rebar3 plugin: rebar3_efmt
  • Thorough macro support

Example

The original code:

-module(example).
-export(
  [fac/1]
).

fac(1) -> 1; fac(N) -> N*fac(N-1).

After running $ efmt example.erl:

-module(example).
-export([fac/1]).

fac(1) ->
    1;
fac(N) ->
    N * fac(N - 1).

If you are interested, please see the README.md and give it a try.

12 Likes

I skimmed the README and it’s “diff” output seems weird. Is there a way to get unified diff which one could use as patchfiles?

2 Likes

Thank you for taking a look.

Currently, there is no direct way to show the output using a unified diff style.
As a workaround, if you are in a git repo directory, the following commands can show that.

$ git commit -am'save'

// Formats files in place.
$ efmt -w

// Show the diff by using `git`.
$ git diff

BTW, I created efmt#6 to track this issue. Thanks for your feedback!

4 Likes

Good job! The output format is pretty nice. The problem I’ve had with all available erlang formatters I’ve seen so far is that they seem to place more focus on making the code uniform than on making it nice to read. At first glance it looks like efmt comes close to my personal style.

(Though I have to admit I like the unformatted version in Differences with other Erlang formatters the best…)

4 Likes

Thanks! I’m very glad to hear that!

Though I have to admit …

Oh, the formatted code in the section is intendedly ugly. The maximum line length option is set to an unrealistically small value (i.e, --print-width=30) to show the differences between efmt and erlfmt in the cases where many line-wrappings should happen.

I’m going to add a note about the above point to README.md later.

4 Likes

BTW, I tried applying the formatter to jsone library by jsone#71. So you can see a real diff that efmt generated there.

2 Likes

I’d consider this change a bug in the formatter.

Since macros in Erlang are pure string replacement surrounding white space can be significant.

2 Likes

Thank you for your comment.
Indeed, the result ( ?CAPTURE_STACKTRACE->) is a point that should be improved in the future version.
However, as far as the semantic meaning of the code is concerned, I think the current result is okay. This is because, AFAIK, Erlang macros are processed token-level (not string-level), and it’s impossible to make a new token by macro expansions (c.f. The BEAM book – 2.3.1. Compiler Pass: The Erlang Preprocessor (epp).

4 Likes

You are right. I was thinking of some case like

-define(OP, andalso).

f() -> true?OP false.

But that expands correctly on the token level, of course. Never mind. :grinning_face_with_smiling_eyes:

3 Likes

Hi there,

Let me briefly share the current status of efmt.
After the initial release in November last year, the formatter has been continuously being improved (the latest version is v0.12.0).
A lot of bugs have been fixed and the formatting style has been almost stabilized.
So I think now is a good time to try efmt (my colleagues and I heavily use efmt in daily work).

Besides, currently, there are,

3 Likes

Can it be made to put the semicolons at the front?
case E
of …
; …
; …
end

No. efmt doesn’t support that style.

What a real pity, because the “comb” style is an important aid to readability.

Sorry, but one of the efmt’s goals is to unify coding style as much as possible. So, it’s difficult to support all good styles in the world.

1 Like

I shall have to stick with my own formatter, then.
I did once try to conduct an experiment on a question relating to
coding style. I was horrified to discover that my 3rd year Comp.Sci.
students claimed to be unable to read 2 pages of code in black and
white print. They also claimed to be unable to find any mistake in
even a short amount of code if they could not step through it in a
debugger.
In the absence of experimental evidence showing that one style
variant is superior to another, the only way to unify styles is
compulsion. Successful code formatters are configurable for a reason.

1 Like

I think it’s good to keep using your formatter if it satisfies your needs. As efmt is an opinionated formatter, it enforces the formatting style to the users. But fortunately, there are several Erlang formatters and Erlang programmers can select their favorite one (or no formatter).

1 Like

Sorry to steal the thread @sile, but it was too good an opportunity to let it pass…

@nzok: Do you have a formatter that formats the code comma-first style as you showed above? If so… How hard would it be to use your code (or even your formatter as a whole) to solve Support comma-first indentation · Issue #36 · AdRoll/rebar3_format · GitHub ? That is to add comma-first support to rebar3_format.

It could be a great SpawnFest project, just saying… :roll_eyes:

2 Likes

[FYI] Just published the VSCode extension: efmt - Visual Studio Marketplace

2 Likes