Mix.Tasks.Format behaviour (Mix v1.13.0-dev) View Source

Formats the given files and patterns.

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

If any of the files is -, then the output is read from stdin and written to stdout.

Formatting options

The formatter will read a .formatter.exs file in the current directory for formatter configuration. Evaluating this file should return a keyword list.

Here is an example of a .formatter.exs file that works as a starting point:

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

Besides the options listed in Code.format_string!/2, the .formatter.exs file supports the following options:

  • :inputs (a list of paths and patterns) - specifies the default inputs to be used by this task. For example, ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]. Patterns are expanded with Path.wildcard/2.

  • :plugins (a list of modules) (since v1.13.0) - specifies a list of modules to customize how the formatter works. See the "Plugins" section below for more information.

  • :subdirectories (a list of paths and patterns) - specifies subdirectories that have their own formatting rules. Each subdirectory should have a .formatter.exs that configures how entries in that subdirectory should be formatted as. Configuration between .formatter.exs are not shared nor inherited. If a .formatter.exs lists "lib/app" as a subdirectory, the rules in .formatter.exs won't be available in lib/app/.formatter.exs. Note that the parent .formatter.exs must not specify files inside the "lib/app" subdirectory in its :inputs configuration. If this happens, the behaviour of which formatter configuration will be picked is unspecified.

  • :import_deps (a list of dependencies as atoms) - specifies a list of dependencies whose formatter configuration will be imported. See the "Importing dependencies configuration" section below for more information.

  • :export (a keyword list) - specifies formatter configuration to be exported. See the "Importing dependencies configuration" section below.

Task-specific options

  • --check-formatted - checks that the file is already formatted. This is useful in pre-commit hooks and CI scripts if you want to reject contributions with unformatted code. If the check fails, the formatted contents are not written to disk. Keep in mind that the formatted output may differ between Elixir versions as improvements and fixes are applied to the formatter.

  • --dry-run - does not save files after formatting.

  • --dot-formatter - path to the file with formatter configuration. Defaults to .formatter.exs if one is available. See the "Formatting options" section above for more information.

When to format code

We recommend developers to format code directly in their editors, either automatically when saving a file or via an explicit command or key binding. If such option is not available in your editor of choice, adding the required integration is usually a matter of invoking:

cd $project && mix format $file

where $file refers to the current file and $project is the root of your project.

It is also possible to format code across the whole project by passing a list of patterns and files to mix format, as shown at the top of this task documentation. This list can also be set in the .formatter.exs file under the :inputs key.

Plugins

It is possible to customize how the formatter behaves. Plugins must implement the Mix.Tasks.Format behaviour. For example, imagine that your project uses Markdown in two distinct ways: via a custom ~M sigil and via files with the .md and .markdown extensions. A custom plugin would look like this:

defmodule MixMarkdownFormatter do
  @behaviour Mix.Tasks.Format

  def features(_opts) do
    [sigils: [:M], extensions: [".md", ".markdown"]]
  end

  def format(contents, opts) do
    # logic that formats markdown
  end
end

The opts passed to format/2 contains all the formatting options and either:

* `:sigil` (atom) - the sigil being formatted, e.g. `:M`.

* `:modifiers` (charlist) - list of sigil modifiers.

* `:extension` (string) - the extension of the file being formatted, e.g. `".md"`.

Now any application can use your formatter as follows:

# .formatters.exs
[
  # Define the desired plugins
  plugins: [MixMarkdownFormatter],
  # Remember to update the inputs list to include the new extensions
  inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}", "posts/*.{md,markdown}"]
]

Remember that, when running the formatter with plugins, you must make sure that your dependencies and your application have been compiled, so the relevant plugin code can be loaded. Otherwise a warning is logged.

Importing dependencies configuration

This task supports importing formatter configuration from dependencies.

A dependency that wants to export formatter configuration needs to have a .formatter.exs file at the root of the project. In this file, the dependency can list an :export option with configuration to export. For now, only one option is supported under :export: :locals_without_parens (whose value has the same shape as the value of the :locals_without_parens in Code.format_string!/2).

The functions listed under :locals_without_parens in the :export option of a dependency can be imported in a project by listing that dependency in the :import_deps option of the formatter configuration file of the project.

For example, consider you have a project called my_app that depends on another one called my_dep. my_dep wants to export some configuration, so my_dep/.formatter.exs would look like this:

# my_dep/.formatter.exs
[
  # Regular formatter configuration for my_dep
  # ...

  export: [
    locals_without_parens: [some_dsl_call: 2, some_dsl_call: 3]
  ]
]

In order to import configuration, my_app's .formatter.exs would look like this:

# my_app/.formatter.exs
[
  import_deps: [:my_dep]
]

Link to this section Summary

Callbacks

Returns which features this plugin should plug into.

Receives a string to be formatted with options and returns said string.

Functions

Returns a formatter function and the formatter options to be used for the given file.

Returns formatter options to be used for the given file.

Link to this section Callbacks

Specs

features(Keyword.t()) :: [sigils: [atom()], extensions: [binary()]]

Returns which features this plugin should plug into.

Specs

format(String.t(), Keyword.t()) :: String.t()

Receives a string to be formatted with options and returns said string.

Link to this section Functions

Link to this function

formatter_for_file(file, opts \\ [])

View Source

Returns a formatter function and the formatter options to be used for the given file.

The function must be called with the contents of the file to be formatted. The options are returned for reflection purposes.

Link to this function

formatter_opts_for_file(file, opts \\ [])

View Source
This function is deprecated. Use formatter_for_file/2 instead.

Returns formatter options to be used for the given file.