 
       def my_function(%User{} = user, arg1, arg2) do
         %{name: name, age: age, ...} = user
-
-  Since the formatter cannot change the semantics of your code,
-  sometimes it is necessary to tweak the code to get optimal formatting.
+        ...
+      end
+
+  In some situations, you can use the fact the formatter does not generate
+  elegant code as a hint for refactoring. Take this code:
+
+      def board?(board_id, %User{} = user, available_permissions, required_permissions) do
+        Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
+          required_permissions == Enum.to_list(MapSet.intersection(MapSet.new(required_permissions), MapSet.new(available_permissions)))
+      end
+
+  The code above has very long lines and running the formatter is not going
+  to address this issue. In fact, the formatter may make it more obvious that
+  you have complex expressions:
+
+      def board?(board_id, %User{} = user, available_permissions, required_permissions) do
+        Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
+          required_permissions ==
+            Enum.to_list(
+              MapSet.intersection(
+                MapSet.new(required_permissions),
+                MapSet.new(available_permissions)
+              )
+            )
+      end
+
+  Take such cases as a suggestion that your code should be refactored:
+
+      def board?(board_id, %User{} = user, available_permissions, required_permissions) do
+        Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
+          matching_permissions?(required_permissions, available_permissions)
+      end
+
+      defp matching_permissions?(required_permissions, available_permissions) do
+        intersection =
+          required_permissions
+          |> MapSet.new()
+          |> MapSet.intersection(MapSet.new(available_permissions))
+          |> Enum.to_list()
+
+        required_permissions == intersection
+      end
+
+  To sum it up: since the formatter cannot change the semantics of your
+  code, sometimes it is necessary to tweak or refactor the code to get
+  optimal formatting. To help better understand how to control the formatter,
+  we describe in the next sections the cases where the formatter keeps the
+  user encoding and how to control multiline expressions.
+
+  ## Keeping user's formatting
+
+  The formatter respects the input format in some cases. Those are
+  listed below:
+
+    * Insignificant digits in numbers are kept as is. The formatter
+      however always inserts underscores for decimal numbers with more
+      than 5 digits and converts hexadecimal digits to uppercase
+
+    * Strings, charlists, atoms and sigils are kept as is. No character
+      is automatically escaped or unescaped. The choice of delimiter is
+      also respected from the input
+
+    * Newlines inside blocks are kept as in the input except for:
+      1) expressions that take multiple lines will always have an empty
+      line before and after and 2) empty lines are always squeezed
+      together into a single empty line
+
+    * The choice between `:do` keyword and `do/end` blocks is left
+      to the user
+
+    * Lists, tuples, bitstrings, maps, structs and function calls will be
+      broken into multiple lines if they are followed by a newline in the
+      opening bracket and preceded by a new line in the closing bracket
+
+    * Pipeline operators, like `|>` and others with the same precedence,
+      will span multiple lines if they spanned multiple lines in the input
+
+  The behaviours above are not guaranteed. We may remove or add new
+  rules in the future. The goal of documenting them is to provide better
+  understanding on what to expect from the formatter.
 
   ### Multi-line lists, maps, tuples, etc
 

        arg1,
        arg2
      ) do

  While the code above is completely valid, you may prefer to match on
  the struct variables inside the function body in order to keep the


    1. calls that have do/end blocks
    2. local calls without parens where the name and arity of the local
       call is also listed under `:locals_without_parens` (except for
       calls with arity 0, where the compiler always require parens)

  The choice of parens and no parens also affects indentation. When a
  function call with parens doesn't fit on the same line, the formatter
