This article explains all about the new mix task mix format which formats our code base.

Elixir version: 1.6.0-rc.0

Code formatting is easy now with the help of mix task mix format . It will take care of all you care about cleaning and refactoring as well. It can assure a clean code base or simply universal code base which maintains some useful standards.

Now, you no need to ask your team member to do things like

  1. provide some room for variables
  2. add white spaces around , etc…

Most of things which we have to take care of will taken care by mix format . Letting us to focus on just code logic.

Main Intention

A single style to follow consistently as a whole.

Usage

1
$ mix format filename

Let me assume that you are in the root of your elixir project and this is how you can format all files inside your project.

1
mix format mix.exs lib/**/*.{ex,exs} test/**/*.{ex,exs}

Before getting down into details, I will show you an example here which is purposely written the code mess and how this looks after running the task mix format .

I have written some possible code mess in a file and applied mix format and took screenshots of some code snippets.

Indentation & Brackets

Let’s observe some descent changes by mix format inside the file.

img

before mix format — indentation/brackets

In the above screenshot, the definition print doesn’t use () for parameters. and the line number 3 is not indented properly.

img

after mix format — indentation/brackets

So, to achieve this we no need to spend the time now as mix format is taking care of all such things whichever it feels odd and maintains the code readability and legibility.

let’s go a bit deeper inside

Breaking and Joining lines

Joining a Line

img

before mix format multi line to single function

If you observe the above screenshot at line number **2, **I have written the definition in two lines unlikely we do in single line and this how the mix format converted

img

after mix format multi line to single function

The mix format has taken care of putting those lines into a single line which makes a sense of writing them in a single line instead of writing in multi-lines.

The mix format is much smart enough to understand the situation or state of **LOC **where the multi-lines are required and where they don’t.

Now observe the other situation of multi-lines

Breaking a Line

img

before mix format single line to multi function

You can clearly observe the crushed map user=%{...} which I intentionally wrote the map with such keys together by not allowing the code to take a breath. The line looks like a squeezed bottle.

Even though this works fine, the mix format thinks smarter and will write each key-value pair in its own line.

Have a look at the following screenshot. How beautifully crafted the squeezed map.

img

after mix format single to multi line

Now the map can easily let some air inside and live longer. I am just kidding.

White Spaces

One last thing I would like to show you is a very common mistake that most of the developers including me used to forget to do. Of course, we will take the help of linter to remind.

We usually not all but most of us will forget to provide a white space after the coma , while writing a list or the function parameters. We end up with no spaces between the elements in a list later we come back to fix.

Take a look how nicely the mix format did that for us.

img

img

left side — before and right side — after mix format

Blank Lines or Empty lines

Any continuous blank lines are joined into a single blank line.

.formatter.exs

For automatically formatting your code base, you can run the new mix format task.

However, a .formatter.exs file may be added to your project root for custom configuration.

The formatter will read a .formatter.exs in the current directory for formatter configuration. It should return a** keyword list** with any of the options supported by Code.format_string!/2.

You can specify things like

  • which files to format
  • specifying coding line length I mean minimum letters in a line
  • importing the formatter configuration from another hex package that project depends
  • exporting path for formatter configuration etc …

How to configure ?

You have to just return a **Key-Word List **like [atom: any,...]

Example File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# project_root/.formatter.exs

    [

      # functions to let allow the no parens like def print value
      locals_without_parens: [hello: 2, get_user: 1, addtion: *],  

      # files to format
      inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],

      line_length: 80,                                             

      # importing configs from other libraries it is depending
      import_deps: [:dependency1, :dependency2],                  

      # configuration export to other projects to use in their projects
      export: [                                                    
        [
          locals_without_parens: [hello: 2, get_user: 1, addtion: *]
        ]
      ]
    ]   

Understanding the File

1
locals_without_parens: [hello: 2, get_user: 1, addtion: :*],

By default the formatter will turn any definition with out () like below

1
2
3
def hello user,country do
 IO.inspect("hello #{user} from #{country}")
end

into

1
2
3
def hello(user, country) do
 IO.inspect("hello #{user} from #{country}")
end

But, as you specified this definition inside the formatter config under locals_without_parens it will let this definition to stay without () .

Check it in live

Elixir Formatter configurationChecking locals_without_parens option in formatter configurationasciinema.org

1
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],

Here nothing is fancy. We are just giving the scope to the formatter and telling which files to be formatted. According to above line, we are letting the formatter to format a file mix.exs in the current directory and also files with extension ex and exs recursively inside the directories of config, lib, test . It digs deeper inside those three folders and if any file with the specified extension found is formatted according to the formatter configuration.

1
line_length: 80

The line length to aim for when formatting the document. Defaults to 98.

1
import_deps: [:dependency1, :dependency2]

Here we are telling the formatter to import the configuration from the project dependencies [:dependency1, :dependency2] . These two project dependencies should have an export option inside their .formatter.exs file. What ever exported from their .formatter.exs are imported inside the current .formatter.exs.

1
2
3
4
5
export: [
  [
   locals_without_parens: [hello: 2, get_user: 1, addtion: *]
  ]
]  

These exported configuration options are used in another projects which depends and this project like explained in import_deps . There are other options too.

**Note: **Elixir community recommend developers to format code directly in their editors.

Hope you got some idea about code formatter.