Running the new Elixir formatter

Tags: #<Tag:0x00007f11420c4fe0>


That’s one of the things I am the most sure we will not do. The purpose of the formatter is get code as consistent as possible, and that would go straight against that purpose.

The underscores between digits in the project were a tough choice and they’re still under review. The rationale behind this was that years and ports look really bad with underscores. However there are still cases that are weird with/without underscores so it’s hard to find something that fits all use cases. We might start keeping what the user used, but we’re not sure yet.


I don’t think I understand what you mean. With strict/opinionated mode I mean that it should ignore personal stylistic choices like underscored digits and the number of lines between functions and force a consistent elixir style.

It would mean having two formatter codepaths, one that is more forgiving and one that just formats the code exactly like elixir wants it so it would increase the technical debt and add complexity.

With “consistent” do you mean “consistent with the rest of that projects code” or “consistent with all elixir projects code”?

shrug We use credo to detect numbers without underscores so we can always fall back to that. Besides, most of the code is text, not digits. :smile:


The formatter is strict and opinionated by default, right? What is it that you won’t do?


I believe the point @whatyouhide was getting at is that there aren’t different modes. If you want to call it strict/opinionated, then sure, but it is still a single mode.


Ok, thanks, that makes sense. Just to be clear, I’m not using strict/opinionated a term of derision. I mean opinionated as in “Does not accept configuration options and doesn’t care about the original formatting”. The opposite would be something like a “conservative” formatter, which would take plenty of configuration options and try to preserve some of the original formatting. It wouldn’t be useful to enforce a uniform style, but it would be useful for refactoring tools or something like that.


Thanks for clarifying. In any case, I didn’t get this impression at all. :slight_smile:


i am generally anti-vertical whitespace, but if the formatter is going to be put single lines between function clauses and case clauses, could it put two lines between distinct functions? ie

function foo(:ok) -> :ok

function foo(:error) -> :error

function bar(:ok) -> :ok

function bar(:error) -> :error

with the current rules, it’s really hard to quickly distinguish between different functions


The formatter doesn’t know what is a function definition. The only way it could do so would be if we hardcoded def, defmacro and friends. But then what would happen when you use defcall or similar from ex_actor or another library? That’s why we don’t hardcode names in the formatter.

However, I am also worried the lack of distinction between multiple definitions but I do not have an answer yet. I am trying a couple things in my personal projects, such as marking multiple definitions with a ## foo/3 or similar or a bodyless clause but I am not yet convinced.


You can always add a whitelist of def-like names to the formatter which can be extended by a user-supplied option. That’s what I do with Makeup and it seems to work well when documenting packages such as ExSpirit (which has defrule) and ProtocolEx (which has deftest). Then you could keep together groups of

deflike f(args) ...

According to the arity, which you can determine staticalky by counting the number of arguments.

But maybe it’s not worth it just to ensure the grouping of the clauses… That’s your call.


That’s our last option but an option nonetheless. Our plan is to introduce options to the API only when strictly necessary as they go against the formatter goals.

The formatter hasn’t been formally out yet so we would like to see people using it extensively before going ahead and introducing new options.


if it’s not possible to add extra vertical whitespace between functions (as compared to function clauses) i’d encourage you to reconsider adding vertical whitespace after case clauses. right now the formatter produces code with really monotonous vertical rhythm making it hard to navigate and scan


As said previously, we would like to play with other ideas in this area. The formatter has not had any kind of extensive usage yet, so we should wait and collect more feedback before doing more changes.


For me most functions do have documentation/typespec, which visually separates functions from each other and for private functions I’ve by now not felt the need, but would probably go with just a simple comment or typespecs where applicable.


Pardon my question but how do I use this Elixir formatter? Is it like go fmt in that it cleans up the code?

Do I need to have Elixir 1.6 installed? Is 1.6 production ready?

# install erlang with homebre
brew install erlang

# install asdf to manage Elixir versions
if [ -d "$HOME/asdf" ]; then
  git clone "$HOME/.asdf" --branch v0.4.0

# don't forget to add following part to your shell config (e.g. .bashrc)
. "$HOME/.asdf/"

# install elixir plugin if missing
plugins=$(asdf plugin-list)
if grep -q -v elixir <<< "$plugins"; then
  asdf plugin-add elixir

# install with asdf as in .tool-versions
asdf install

# install master version
asdf install elixir ref:master

# run mix format with elixir master
ASDF_ELIXIR_VERSION=ref-master mix format

I have mix_format alias in my ~/.alias

alias mix_format="ASDF_ELIXIR_VERSION=ref-master mix format"


Yes-ish, you need Elixir compiled from master, which is going to be 1.6.

It has not been released yet. Not even a release candidate. So, I do not consider it production ready. José once said, that 1.6 will probably released during Q1 '18.


Will something like
defining pattern

x y(different),...
x y(different),...
x y(different),...

in the formatter work?


A lot of it is for me too, but I already do a lot of what it does. I often separate function heads by a newline unless they are very short and are obviously blocked together, and I separate different head types altogether by 2 lines, and categories of functions by 3 lines with a (comment via ##) header then another blank line, which the formatter utterly destroys.

In addition, a lot of the baked tables I use become entirely unreadable. The formatter does some friggin-weird alignment on things like multi-line type declarations and wrapped maps/lists/tuples of things that just push things needless way right (wtf?). A lot of single expression function bodies get formatted very weird out onto multiple lines, making the whole structure horribly unreadable and multi-indentions deep (wtf?). It ‘does’ format a lot of my sub-blocks inside a function exactly how I already do it, so I like that more people will follow that style (I find it far more readable than what many people do). Overall it seems a good start but it does need some work, especially some way to mark a section as DO_NOT_FORMAT_THIS as it just breaks some things all to hell that require alignment to be readable, especially data tables, those just become wtf’s all around… o.O

Lisp has some very nice formatters, and nicely they work on any lisp style language. ^.^

Really though, if text was not so ubiquitous, editing source via a graph database or something would be awesome, you could make so many useful interconnections and such! Plus IDE’s would become practically trivial. ^.^

I will definitely be adding it to my macro string source debug output generation for sure! Convert all that horror of things like def(blah(x, y), do: 42) into actual usual looking code then! ^.^

I have no qualm with using up lots of space, I like space where it helps readability (like data tables and such), though I would really prefer tabs for indentation and spaces for alignment, always, spaces are not for indentation! o.O!

Yeah this is where I like to put heads together if the functions are very short, and separate by a single blank line if longer (using the same format for all heads of a function).

I do like this aspect of it a lot. ^.^

Yeah I do this same thing here quite a lot (except I had to set it to 3 for some reason that I forgot).

This is what I do!!!

Except for such short functions as you have there they’d have no blank lines between the heads and still have 2 blank lines between the different functions. :slight_smile:

I find this style of mine much more readable, and I’ve been using it across a lot of languages over a lot of years. :slight_smile:

Hmm, comments could do the separation I seek, but that would add a lot of noise, especially as I use semantic highlighting in my IDE’s so the comments would end up just glowing out of the screen (in semantic highlighting comments are considered as ‘way important’, if they aren’t then you should get rid of them and make the code clearer instead).

I keep up to date with elixir master on my dev server and I have to say that the formatter makes a lot of my code entirely unreadable as it is… I tend to use many short functions when at all possible and pre-generated quick lookup tables and etc, yeesh… ^.^;


Wow that is a lot of work for that, I just do cd /opt/elixir; git pull; make; _make install… o.O

Although I’m not running different versions here, so eh… I’v not had master elixir break on me yet. ^.^




I never really expressed how happy I am with the fact that elixir gets this formatter, so here goes: very happy :smiley: The negative aspects that are voiced here mostly have to do with each of us having our own style of doing things and our own subjective opinion on what is “right” or “beautiful”. These are results of Elixir allowing all the different ways to write the same thing.

In my opinion the most important aspect of having the formatter is to reduce these options and make the code more consistent. I can live with the resulting format being different from what I use now as long as there is one true way used by most other programmers, libraries etc :wink: It should also help adoption in the non-ruby community.

Brackets are now applied automatically44 so no more dealing with those warnings. This is a big win.

that’s just pure :heart: