This feels like a feature request to me: I understand why sigils are generally not touched by the formatter without plugins, but I feel like the sigil_w included in the standard library should have smarter formatting by default.
*NOTE: I'm using Elixir 1.14.2 here to observe the behaviour of the formatter, this may be out-of-date with the mainline branch.* *General formatting of sigils* Conceptually, to the compiler, the contents of a sigil is a potentially multi-line string. However, actually using a multiline string does get forced into a format as expected: @words """ ONE TWO THREE FOUR FIVE """ |> String.split |> Enum.filter(&String.contains?(&1, "F")) Elixir *literal* multiline strings have special semantics for stripping the whitespace on the left, based on the indentation of the closing """. Try increasing and decreasing the indentation of that lexeme and watch how the formatter reacts. I'd personally intuitively expect the sigil_w case to do the same, but you can see why we cannot apply multiline string semantics to every sigil—the sigil macro, called at compile-time, receives the verbatim contents of the string, extra whitespace and all. Correctly handling that whitespace, including stripping it, is the job of the sigil itself, which may vary depending on the intentions of the sigil developer. (Consider: a custom sigil for parsing the Whitespace esolang <https://en.wikipedia.org/wiki/Whitespace_(programming_language)> or a python program has different multiline-stripping semantics than literal multiline strings or sigil_w.) Since the formatter cannot know what whitespace semantics any particular sigil expects, it cannot modify the contents of the string with the knowledge that it will not impact the program, unlike multiline string literals. So it will do absolutely no work on the sigil's contents; leaving your awkward indentation in place. The good news is that if you correct the indentation manually, knowing how this particular sigil handles whitespace, that rewriting will pass formatting and stay unchanged. *Formatting stdlib sigils* That being said, the documentation for extending the formatter <https://hexdocs.pm/mix/main/Mix.Tasks.Format.html#module-plugins> is very sigil-special-casing-oriented. It should be easy to implement a plugin that knows how to normalize the currently un-touched ~w( ONE TWO THREE FOUR FIVE ) However, *I'd really imagine that the stdlib formatter would understand the special whitespace semantics of the stdlib sigil_w and format it out-of-the-box*. This is the feature request I see here. I also think that other stdlib sigil formatting could be improved; for example I feel like ~D[2022-01-01 ] should automatically be formatted to ~D[2022-01-01] without any plugins. *Formatting module attributes* > Is there reason why when I pipe the module attribute that it gets intended differently than when I do not pipe it (compare @other with @xs)? I believe this is an emergent behaviour of whatever order the formatter calculates rules for determining: - the indentation of the module attribute's argument - the indentation of the pipeline - the indentation of the (list) argument to the pipeline - the indentation of list items within the list These determinations add up in an unexpected way I do not understand. Essentially, Pipelines want to have their indentation flush with the leftmost character of their argument, so that you get: [1, 2, 3] |> Enum.map(&(&1 * 2)) |> Enum.reject(&(&1 < 5)) |> length() [ 1, 2, 3 ] |> Enum.map(&(&1 * 2)) |> Enum.reject(&(&1 < 5)) |> length() Somehow this interacts with how module attributes want to indent things, and we get @nums [ 1, 2, 3 ] |> Enum.map(&(&1 * 2)) |> Enum.reject(&(&1 < 5)) |> length() This does not seem like a bug per se, but I also personally think that this should format as @nums [ 1, 2, 3 ] |> Enum.map(&(&1 * 2)) |> Enum.reject(&(&1 < 5)) |> length() This seems like it would be a backwards-compatible enhancement. *Summary* The combination of sigil_w not being internally normalized with sigil_w whitespace semantics, alongside the current behaviour of multi-line expressions in module attributes, leads to this particularly unexpected appearance. I feel like improvements to both would be welcome in PRs. It may be worth first discussing the impact of releasing changes to the formatter, though. Even semantically backwards-compatible changes have the potential to lead to a lot of syntactic line diff noise and churn when upgrading Elixir, so I'm not certain if there is a more cautious release policy for such things—such as only releasing major formatter changes in minor version bumps. On Wednesday, December 28, 2022 at 5:59:17 AM UTC-6 dario.h...@gmail.com wrote: > Running `mix format --check-formatted` passes with success on the > following code: > > defmodule Example do > @xs [ > 1, > 2, > 3, > 4, > 5, > 6, > 7 > ] > > @other [ > 1, > 2, > 3, > 4, > 5, > 6, > 7 > ] > |> Enum.map(&(&1 * 2)) > |> Enum.reject(&(&1 < 5)) > |> length() > > @words ~w( > ONE > TWO > THREE > FOUR > FIVE > ) > |> Enum.filter(&String.contains?(&1, "F")) > end > > I am wondering whether that is intended or if I should open an issue on > Github and look into fixing it. > > `@words` does not seem to be formatted in the same way as `@other` which I > would kinda expect and the formatting of `@words` looks kinda weird. > > Secondly is there reason why when I pipe the module attribute that it gets > intended differently than when I do not pipe it (compare @other with @xs)? > > Best regards, > Dario > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/35cedeec-9456-4d80-9346-09ab1d739229n%40googlegroups.com.