Elixir file formatting with vscode (removing whitespaces and documentation)

Hello everyone!

A little while ago I opened this issue in the vscode repository:
Make distinction when removing leading whitespace from trailing whitespace · Issue #113235 · microsoft/vscode · GitHub, which I think would help improve the way we edit Elixir files.

This is a problem that I and my coworkers noticed some time ago, where it’s not possible to use a file formatter that trims whitespace because vscode would remove trailing and leading whitespaces butchering Elixir’s markdown documentation in the process.

I was reluctant to post here at first, but if you use Elixir and vscode, please consider upvoting this request so it can get picked up by the dev team (we have one more day to get at least 20 upvotes).

Cheers!

1 Like

I don’t understand the issue.

Can you provide an example where whitespace is removed where it shouldn’t?

Can you specify exactly what you mean by leading white space?

@NobbZ, @axelson it’s very simple actually. Take the issue example itself:

@doc """
My function documentation markdown.
This will be part of the first line because the "line break" was removed when saved
"""
def hello(), do: :world

If you mark the option to trim whitespace in vscode today, it will remove whitespace from the line start and line ends (leading and trailing). This would result in the documentation of the hello function to be on the same line like this:

My function documentation markdown. This will be part of the first line because the "line break" was removed when saved

This happens because whitespace works as line breaks and vscode only has one option that removes all whitespace (around). Usually, you want to disable this option to work with markdown files so your markup doesn’t get butchered.

You can test this by enabling format on save/ trim on save in vscode, add documentation to a function, and then visualize it with elixir-ls (for example). The markdown won’t be properly formatted because of the lack of whitespaces (line breaks).

How is this related to leading vs. trailing whitespace though? Only trailing whitespace (two spaces) is converted to a line break in markdown.

I do not see any leading or trailing whitespace.

Also I do not see how existing leading whitespace would change anything.

defmodule M do
  @doc """
  My function documentation markdown.
  This will be part of the first line because the "line break" was removed when saved
  """
  def hello(), do: :world
end

If you have this construct, neither VScode, nor the elixir formatter will remove any leading whitespace, but still the documentation will be rendered on a single line.

So I still do not see a problem, and I never have observed leading whitespace getting removed by VScode. Though language specific formatters might of course reformat into something that has more or less whitespace leading, but that is nothing VScode can do about, and neither should change any semantics by that.

A thing I would indeed give you support for, if that was an issue, is that within a “string” whitespace should always be preserved by VScode and/or formatters, as removing whitespace there changes semantics.

Wow, it seems that there’s a lot of confusion going on…
I recorded a gif to better explain, but you could also test it locally by doing the same steps:

  • Install elixir-ls
  • Add the config "files.trimTrailingWhitespace": true and "editor.formatOnSave": true
  • Add documentation to a function with multiple lines
  • Save the file and see the markup getting messed up because vscode removes all spaces around a line and there’s no counterpart option to prevent that (like only removing spaces at the start of the line and not the end)

2 Likes

This animation confirmed, that your problem is not removal of leading whitespace, but trailing whitespace within a string literal.

As I’ve said already, open a report that describes the correct problem and you’ll get the votes.

Your video did not show any modification of leading whitespace.

Well in markdown a single line break is converted to a simple space in HTML. There were “flavours” of markdown that changed this behaviour. Github did that one. And it was really bad as most of the time your HTML is not displayed with monospaced fonts.

If you want the line break in the docs, just make two paragraphs:

@doc """
My function documentation markdown.

This will be part of the first line because the "line break" was removed when saved
"""

Edit: oh no, I understand now, you want to keep two spaces at the end of the line. Sorry. I’ve never liked this markdown feature as it is not visible when writing. I would like markdown to have a symbol for linebreaks, like -/-, but I guess you can always try with <br/> ; i don’t know if ex_doc will escape it though.

@NobbZ When exactly did you get the impression I was talking about leading whitespaces only?
If you read the Github issue you’ll see that I talk about how in vs code we have an option to remove trailing whitespace, that actually removes trailing and leading whitespace.

If we have control over what kind of whitespace we can remove for each file extension (in this case, .ex), this wouldn’t be a problem with embedded markdown. Actually, this is useful not just for Elixir files.

As I’ve said already, open a report that describes the correct problem and you’ll get the votes.

I’m not a native English speaker, though. So, please… How could I be more clear than this?
The very first paragraph of the issue says:

Hi, I’ve noticed that there’s only the files.trimTrailingWhitespace without a files.trimLeadingWhitespace counterpart. This has been a problem for editing files that mix markdown documentation with another syntax for a while.

And the very last also says:

If possible, I’d like to be able to remove only leading or trailing whitespace

Perhaps you don’t agree with the solution or were expecting a more elaborate description, but to say that this does not describe the “correct” problem, honestly, I don’t even know how to respond to that.

@lud Exactly! And this is not currently possible because vs code treats both leading and trailing whitespace under the same option.

There is no “leading” whitespace involved in this problem. The problem is just that vscode removes two trailing spaces. It does not remove any leading space otherwise your code would not be indented.

There is no “leading” whitespace involved in this problem. The problem is just that vscode removes two trailing spaces. It does not remove any leading space otherwise your code would not be indented.

The current option called files.trimTrailingWhitespace, also trims ““leading”” whitespaces in files, which is the root cause of the problem. Because of that, you can’t have one or the other.

So, for this scenario, we still want to be able to trim leading whitespace in our files without affecting elixir markdown documentation.

The problem is not caused directly because of leading whitespace and this was never (in my perception) even suggested. It’s caused because of trailing whitespace being removed as well as leading whitespaces - because you only have one option to configure it and it does both.


Update:

To illustrate a little more:

image

image

You can clearly see that the current behavior considers all whitespace as ““trailing”” (hence the option). The editor doesn’t make the distinction between whitespace that goes before (leading) or after (trailing) content. Indentation would still be preserved, just not for “blank” lines.

Another example:

image

image

If whitespace were by default considered leading whitespace until there’s content, this file could be formatted without losing the markdown line breaks at the end. It would also be easier to remove blank lines after this.

I think there is some confusion about the “leading” word. The only “leading” whitespace on your 3rd image is the one that is still there on the 4th image.

Whitespace is considered “per line”. The editor doesn’t care about what the code means, it just removes whitespace at the end of the line, except for the line break.

On line 1 there is none leading or trailing.
On line 2, there are only spaces, and no content. The editors considers this space to be at the end of the line (trailing), and removes it.
On line 3 there are two leading spaces before @doc, and they are still there after the cleanup.
On line 4, there are two leading spaces too, before “Some”, and they are still there. After the content (after the word “here”) there is trailing whitespace, and it gets removed.
And so on.

So no, the editor does not consider all whistespace as trailing. It does not remove leading whitespace.

2 Likes

Thanks to everyone that contributed, we reached our goal!

While we are here jousting about semantics, there are at least 27 people (so far) that shared our pain, regardless of the “proposed” solution.

I hope this gets picked up and the team back at Microsoft can propose a nice solution that helps us solve this issue. So, thanks to you all!

1 Like

Requested by OP