elm radio
Tune in to the tools and techniques in the Elm ecosystem.
elm-format
We discuss the core features and philosophy of elm-format, as well as some hidden productivity tricks for getting more out of it.
Published
February 1, 2021
Episode
#23
elm-format
prettier
gofmt
, the built-in Go formatting tool
Some discussion of
IntelliJ trailing whitespace issues
elm-format
editor integrations table
elm-tooling
elm-tooling
Elm Radio episode
Jeroen's
elm-format
tips tweet
NoExposingEverything
rule
Discussion about
single-line conditionals
The original Elm style guide
Join lines (
J
in vim, also
available with intellij keybindings
)
Transcript
[00:00:00]
Hello Jeroen. Hello Dillon. How are you doing today? I'm doing very good. How about you?
[00:00:06]
I'm doing well and I'm ready to take on this topic which I think this episode might have
[00:00:12]
a bit of a unique format. This sounds so bad. You want to tell people what's going on today?
[00:00:24]
Well, I think you pretty much did. Today we're going to talk about Elm format, if you didn't
[00:00:30]
already guess it from just what Dillon said and from the title. I'm surprised that we
[00:00:37]
didn't talk about this before actually because it's such a unique and fundamental tool to
[00:00:43]
Elm in my opinion. Yeah, it's a little bit like water to a fish.
[00:00:48]
It's omnipresent and you rely on it heavily but you don't always think about it because
[00:00:54]
it's just there and it's just part of how you think of writing. For me, it's part of
[00:01:00]
writing Elm. I was actually pairing with someone the other day who didn't have Elm format set
[00:01:08]
up on their machine and in their editor and it was very interesting. It was actually writing
[00:01:13]
some 0.18 code. The IntelliJ plug in wasn't set up to work with Elm 0.18 and if you set
[00:01:23]
it up, it had all these red squigglies. He just had it turned off and it's really strange
[00:01:29]
trying to write Elm code. In my mind, it's like writing Elm somehow without the compiler
[00:01:37]
where it's like, how do I know it works? If I don't have syntax highlighting, if things
[00:01:42]
don't snap into place when I run Elm format and if I don't get compiler errors, it's completely
[00:01:48]
foreign to me and it feels wrong in my head.
[00:01:52]
Here let's go over what Elm format is for the few people who don't know what it is.
[00:01:59]
Elm format is a code formatter for the Elm language. It's made by Aaron Vonderhaar. What
[00:02:08]
it does is it takes all the Elm files on your project and it formats them in a reasonably
[00:02:15]
predefined way. It's made configuration. It has no configuration that you can set.
[00:02:24]
Which is an intentional philosophy.
[00:02:28]
With that in mind, all Elm code will look very similar. You can go from one project
[00:02:33]
to another. The styling will be very similar. That is very nice.
[00:02:39]
I would say for people who may be new to Elm or the Elm format tool, one of the things
[00:02:46]
that comes up for beginners or people who are new to the community is, how do I change
[00:02:52]
the indentation level? I want it to use two spaces instead of four spaces. The Elm styling
[00:03:01]
is very white space heavy to what a lot of people are used to.
[00:03:06]
There are white space and empty lines.
[00:03:09]
I believe there are two empty lines separating each top level definition.
[00:03:15]
Unless there are comments in between. In which case there are three lines above and two lines
[00:03:20]
under the comment. So that's six lines.
[00:03:23]
Good trivia. It's a very generous white space. To some people that feels off, but you get
[00:03:31]
so used to it as an Elm developer. It just is what Elm looks like.
[00:03:37]
Let's talk about that for a second. To somebody who is coming to Elm and is asking, how do
[00:03:42]
I set these configuration options? As with many things in Elm, it's sort of like, this
[00:03:47]
is sort of how things are done. If you don't like that, then you might not like Elm. It's
[00:03:54]
somewhat opinionated. It's a feature that this is what Elm code looks like. It's certainly
[00:03:59]
something that I've come to appreciate. You don't have to think about it. You don't have
[00:04:04]
to argue with your team about it. As far as I'm concerned, in general with editor configurations,
[00:04:10]
I remember in the olden days using these linting tools. This was a common thing that linting
[00:04:18]
tools used to do.
[00:04:20]
Yeah, and they still do in some languages.
[00:04:23]
Right. Yeah, they'll complain about this formatting is not acceptable. In the old days, it was
[00:04:32]
pretty common for a linting tool to complain that the formatting was incorrect, but not
[00:04:37]
do anything about it. As far as I'm concerned, I don't care what the formatting is, as long
[00:04:44]
as a tool just does it for me in an automated way, and I don't have to think about it. That's
[00:04:48]
what I care about. I'm happy to accept any configuration.
[00:04:52]
I imagine there would be some settings, well, some choices where it would heavily disagree,
[00:04:58]
but I find the ones that Elm format chose are very reasonable. Even though if you come
[00:05:04]
from JavaScript, where the comma goes for lists and arrays, that's a bit off, but I
[00:05:10]
really like it and I want to do that in JavaScript now too.
[00:05:14]
Yeah.
[00:05:15]
I work that I have Predier running on the JavaScript code. It removes all those commas
[00:05:24]
or it moves it.
[00:05:25]
Yeah, Predier has taken over in the JavaScript ecosystem with JSON, JavaScript, TypeScript
[00:05:32]
files. If you're not familiar with that, go check out their site and try it out on your
[00:05:36]
projects. It's quite nice to work with. It is a slightly different philosophy. It has
[00:05:39]
a few more configuration options, but it's definitely been inspired by, I think, GoFmt,
[00:05:46]
Go format was probably the pioneer in these tools. Go was unique in that it was built
[00:05:54]
into the tooling. Out of the box, you've got a formatter and that just is what Go code
[00:06:00]
looks like. I imagine the Elm format was inspired by that to some extent and Predier as well,
[00:06:06]
but it's really taken over and transformed the programming world that formatters are
[00:06:12]
sort of becoming a standard these days.
[00:06:16]
I remember arguing, or maybe not arguing, but going back and forth in pull requests
[00:06:22]
on Ruby code and talking about, hey, we should line up these values with these values. You
[00:06:29]
have lists that you format into columns and depending on the length of the string in a
[00:06:36]
particular column, you need to have leading white space in front of these other commas.
[00:06:42]
People configure their Vim or Emacs setups to have special rules that automatically snap
[00:06:48]
things into place according to their own rules, which are different than the editor plugins
[00:06:53]
that other people on the team are using. Then people are taking time to talk about that
[00:06:58]
on pull requests, which I always found that really, that it took me out of the flow of
[00:07:04]
writing code when I had to think about formatting.
[00:07:07]
I think this is a key point for me is I don't want to think about formatting, I want to
[00:07:12]
think about code. This is one of the, hopefully something that might give some insight to
[00:07:20]
even people who are familiar with Elm format is one of the principles I think that makes
[00:07:24]
using Elm format really nice is the principle of the shortest path to valid code. Not even
[00:07:32]
the shortest path to valid code, but find the shortest path to something that Elm format
[00:07:38]
will transform into valid code. Basically, I think of it as almost like a Vim grammar
[00:07:47]
or it's part of my editor.
[00:07:50]
I'm starting to see what you mean. You mean when you're typing, you try to type as few
[00:07:56]
as characters as possible on your keyboard and then pressing save in your editor and
[00:08:01]
then it formats everything nicely.
[00:08:04]
Exactly. I deliberately want to write as few characters as possible. My goal is not
[00:08:10]
to try to get it close to Elm syntax on the first try and then hopefully Elm format doesn't
[00:08:16]
do its job. I almost consider it a failing on my part if Elm format doesn't have a lot
[00:08:22]
of work to do because it means that I've failed to efficiently express the code I want to.
[00:08:28]
That's my goal. I want the flow of code where I'm just thinking at a high level in terms
[00:08:33]
of the AST and having it interpret that and do some of the heavy lifting for me. For example,
[00:08:40]
the Elm format will format your lists if they're on multiple lines with a leading comma, which
[00:08:48]
a lot of people are not used to. You grow to love it. You don't need to put any
[00:08:58]
spaces between items in a list at all. You don't need to put new lines between items
[00:09:05]
in a multi line list. If you have a list that's spread across multiple lines. This is one
[00:09:09]
thing that even Elm format users may not be aware of. A lot of formatting tools are based
[00:09:14]
on line length and they'll start to break the line at a specific line length.
[00:09:21]
That is one of the configurations that's prettier allows you to set for instance.
[00:09:25]
It right so if you shorten the line or lengthen the line, it'll start to snap it back to one
[00:09:31]
line or multiple lines. Elm format doesn't work that way. It has multi line mode and
[00:09:36]
single line mode. If you have a list that's written out all on one line with any amount
[00:09:42]
of white space between the commas, but it's all on one line, then Elm format will consider
[00:09:47]
that to be single line mode for that list and it will clean it up and normalize the
[00:09:52]
white space with its formatting rules all on single line mode in one line. As soon as
[00:09:57]
you have a single new line in that list, it considers it multi line mode. It doesn't matter
[00:10:01]
if you have 100 items in the list and a single new line, it considers that to be multi line
[00:10:06]
mode. This economy of typing principle that I have for using Elm format, if you have a
[00:10:14]
single new line, what's the point in writing another new line in that list? If you know
[00:10:19]
it's already in multi line mode because there is a new line and you add a new item to the
[00:10:23]
list, all you need is to say comma new list item. You don't need a new line. You don't
[00:10:29]
need a space.
[00:10:31]
If you think that your list is way too big and it's currently on a single line, if you
[00:10:35]
want to put it on several lines, you only have to press the enter key once and then
[00:10:41]
control save or command save and then it will format it for you. You don't have to put all
[00:10:46]
the indentation right or add all the new lines, which would be annoying if you have a hundred.
[00:10:52]
It just does that with one enter and control save.
[00:10:56]
Yeah. Also, another part of this is when it formats, you know that the syntax is valid.
[00:11:02]
You know you don't have a syntax or you know you don't have a missing paren or square bracket
[00:11:07]
or whatever it may be. I use that as part of my feedback loop that I know I'm keeping
[00:11:13]
my syntax valid along the way. When you are intentionally writing minimal syntax to get
[00:11:19]
Elm Format to understand your code and format it the correct way, then that gives you that
[00:11:25]
additional benefit that you're going to see a change that lets you know, oh, it's valid.
[00:11:30]
Yeah. I use that trick all the time too. I don't rely on the editor to tell me, hey,
[00:11:37]
there's a syntax error. Although it does help me to find it when I have one. But yeah, that
[00:11:42]
is a really good check to get in your fingers. So we'll go more into the nitty gritty details
[00:11:49]
and tricks of how to use it and how to take advantage of Elm Format because it's an awesome
[00:11:54]
tool that you actually need to learn in a way to use it well.
[00:11:58]
Yes, exactly. Yeah. There are some hidden Easter eggs that a lot of people who use it
[00:12:02]
every day might not know about.
[00:12:03]
Yeah. And we'll go into that detail later. But why would someone start using Elm Format?
[00:12:10]
So as we said, it can help you write code, but for me, the biggest advantage, and that
[00:12:16]
is the one that you will see advertised in other tools like Predire, is that it will
[00:12:23]
stop the conversations around code style. So as you said before, do a pull request.
[00:12:28]
You don't want to think about code styles. I've worked in open source projects where
[00:12:32]
the only feedback I got was, this is great, but can you put this on the next line? I was
[00:12:37]
like, yeah, sure, no problem. But not having to do that would have taken the pull request
[00:12:43]
one less day to merge because of time zone differences or something.
[00:12:47]
Right. And it focuses your energy in another place. Maybe you notice something else when
[00:12:51]
you're not distracted by the formatting.
[00:12:53]
I think there was a time in my career where I was mostly looking at styling issues when
[00:12:58]
doing code reviews. That's not a good thing. Now I'm looking at other things, still not
[00:13:05]
looking at the grand picture, but there's an improvement to where I should focus my
[00:13:12]
energy doing code review.
[00:13:14]
Yeah, reducing the noise of those things really can change how you interpret what's going
[00:13:20]
on because you're not even thinking about formatting. You look at Elm code and you're
[00:13:26]
thinking, is this formatted with Elm format or not? And if it's formatted with Elm format,
[00:13:32]
then you're no longer thinking about formatting.
[00:13:34]
Yeah, you don't have those stray thoughts when you're working on a code basin. Like,
[00:13:38]
hey, I should probably reformat this code in a different way. Those thoughts don't happen
[00:13:44]
anymore when you have a code formatter. So that's another advantage.
[00:13:49]
Yeah. And you also know that the structure and indentation level is going to be reflected.
[00:13:56]
Now I mean, to a certain extent, Elm has that built in because it does have significant
[00:14:00]
white space in certain areas with indentation, like case statements, but not with parens
[00:14:06]
and things like that.
[00:14:09]
I think it's only for case statements where it's very...
[00:14:12]
Case statements, maybe if statements too, I can't remember.
[00:14:15]
No, not if statements.
[00:14:16]
No, okay. But it is white space sensitive for let's also. Let's are also white space
[00:14:24]
sensitive in certain...
[00:14:25]
Elm or Elm format?
[00:14:26]
In Elm.
[00:14:27]
Oh.
[00:14:28]
If you have a...
[00:14:29]
You need the declarations to be indented the same way.
[00:14:34]
Exactly. Yeah. So Elm at the language level enforces some of those sort of... I mean,
[00:14:40]
this is I think that Evan got this philosophy from Guido van Rassum of Python that the structure
[00:14:48]
of the code and the visual of the code should reflect the semantics of the code so that
[00:14:53]
you don't have the possibility that there's a mismatch where it appears that something
[00:14:59]
is indented at this level, but it's actually not.
[00:15:01]
Now I would argue that a white space significant language like that actually becomes less...
[00:15:09]
Actually having significant white space becomes less useful as a feature when you have a nice
[00:15:14]
formatter and in a certain sense, the formatter becomes harder to work with when you have
[00:15:19]
significant white space because if you have things like brackets indicating the scope
[00:15:25]
of if statements and switch statements, case statements, then the formatter doesn't have
[00:15:32]
to look at white space to figure out what's going on there. It can just say, oh, the scope
[00:15:36]
is clear. The curly braces determine the scope of this case statement. So I know exactly
[00:15:42]
how to indent it. So I actually kind of think that would be easier to work with from an
[00:15:48]
editor experience. And I'm sure it would make Aaron's job as the author of Elm Format easier
[00:15:54]
too. But the fact that you know that the white space and indentation isn't going to mislead
[00:16:02]
you about the scope of what you're looking at is definitely a feature wherever that comes
[00:16:06]
from, whether it's the language or the formatter.
[00:16:08]
So as we said before, Elm Format gives very white space and empty line heavy code. A lot
[00:16:15]
of people say that one of the reasons why it does that is for git diffs, which I think
[00:16:21]
is true, which I don't know if it's a happy accident or if it was, I don't know if the
[00:16:27]
intent was to make the code more readable by making separate things more separate visually
[00:16:32]
and whether git diffs are a nice side benefit of that or whether that was the intent. But
[00:16:38]
you do get better git diffs because things are further apart. Git makes them different,
[00:16:45]
considers them different. So you get a lot less things that look like they changed, but
[00:16:50]
they didn't.
[00:16:51]
Yeah. And having things formatted across multiple lines helps with that too. So if you have
[00:16:56]
a list with five items or a record with five items in general, you can have Elm Format
[00:17:02]
put its single line formatting mode on a record or a list with five items. But as far as git
[00:17:09]
diffs go, now if you change a single field in that five item record or change a single
[00:17:15]
item in that five item list, your git diff is harder to parse because it said this one
[00:17:20]
big line has changed instead of this one small precision change.
[00:17:24]
So in general, I know a lot of people recommend... Actually, does Elm Format? Elm Format does
[00:17:30]
allow you to have record definitions on a single line. You can do type alias for a record
[00:17:36]
on a single line, although it's actually not... You can't actually do it on a single line,
[00:17:39]
right? You can do it on two lines.
[00:17:41]
Two lines, yeah. Plus white space.
[00:17:43]
Right. Type alias record name equals new line indentation curly braces record definition.
[00:17:52]
That's the smallest one it will allow you to do, but it will allow you to do that actual
[00:17:56]
record definition on a single line.
[00:17:59]
Yeah. That was actually one of the linting rules in Elm Analyze where it says, hey, no
[00:18:05]
single...
[00:18:06]
I remember that.
[00:18:08]
No single... Sorry. No single... Yeah. No records with multiple fields on one line.
[00:18:14]
Yes.
[00:18:15]
That was it.
[00:18:16]
Exactly. Exactly. Yep. That's right. Yeah. And in some cases, it's nice to just, in preparation
[00:18:21]
for adding an item to a record or a list, it can be nice to just start with the new
[00:18:28]
line formatting, even though it only has a single item. So sometimes I find myself doing
[00:18:33]
that where you can say like type alias record equals new line indentation open curly brace
[00:18:40]
a single field new line closing curly brace. That would be a valid multi line mode for
[00:18:46]
a single field record. And sometimes that's nice for diffs and adding things to it because
[00:18:53]
once you add something to it, you don't need to change it to multi line mode because it's
[00:18:56]
already there.
[00:18:57]
There's another reason why I tried to have the ending curly brace on the separate line
[00:19:01]
is so that it makes it very clear that this record only has one field because if the opening
[00:19:08]
and the curly braces are on different lines, then you know that Elm format will make one
[00:19:13]
field, one line for every field. So if it's only in two lines, you know that it only has
[00:19:19]
one field.
[00:19:20]
So it's easier for your brain to process it's a single field. That's a great point.
[00:19:25]
Yeah, but if it was all in one line, then you would have to read through it. And then
[00:19:29]
you will find out whether yes or not, it would have more fields.
[00:19:33]
Yeah, that's a good point. Yeah. So I think this is an important point that even though
[00:19:37]
Elm format doesn't have configuration options, it is a modal formatter. And sometimes starting
[00:19:44]
with multi line mode can be a technique that helps you reduce churn. And that's that's
[00:19:50]
one of the things that I look for in the way that I format my code is to reduce churn.
[00:19:56]
I don't want I don't want something to introduce diff noise where I didn't change it. For example,
[00:20:02]
when you go from, you know, single line mode to multi line mode in a record when you add
[00:20:07]
a field, I don't want there to be noise around the closing curly part. And if it's already
[00:20:12]
in multi line mode, there will be no diff noise around the closing curly going from
[00:20:17]
the same line to a different line. There will just be a new line. That's the new field.
[00:20:22]
Yeah, that's actually the reason why the format for let in expressions changed. And I think
[00:20:30]
you remember that at some point, I don't know which version, but Elm formats indented whatever
[00:20:35]
was in the in section of let in expression. Right. I do remember that. Yeah. Yeah. So
[00:20:42]
the expression, the result expression of the let in variable, let in block, sorry, would
[00:20:48]
be as indented as all the variables. But the problem was that if you added a let in some
[00:20:56]
let clauses, then everything would be indented and that would not make for a very good get
[00:21:02]
diff. That was, I think, the main reasoning behind it. So now, yeah, the body is as indented
[00:21:11]
as if you did not have let clauses. Yeah, avoiding churn is it's one of those like sort
[00:21:17]
of quality of life things that I think just makes it reduces the resistance a little bit
[00:21:22]
when you're writing code and makes things a little smoother. I will say one thing that
[00:21:28]
I've always wished the Elm syntax supported is so, you know, I mean, languages that have
[00:21:35]
like a different formatting for commas would allow trailing commas, you know, like in JavaScript,
[00:21:41]
you can have an object or a list with trailing commas or yeah, yeah, objects and lists can
[00:21:47]
have trailing commas, meaning that, yeah, the last item in the list can have a comma
[00:21:50]
after it, even though there's nothing after that last item. Because what that means is
[00:21:55]
you add a new list item and there's no well, there's no list noise that you're adding it
[00:22:03]
or removing a comma. If you want to reorder the items, then you don't have to like change,
[00:22:09]
make sure you add a comma in the thing that moved up that didn't have a trailing comma
[00:22:14]
and then remove the comma in the place that needs to remove the comma. It just, there's
[00:22:18]
just this churn and this little resistance to changing things and having diffs. And so
[00:22:23]
I find that really nice and TypeScript allows in type definitions, if you like enumerate
[00:22:29]
types or if you're, if you're doing a union type, you can, you separate the union variants
[00:22:34]
with the pipe operator like you do in an Elm custom type, but you can have a leading pipe.
[00:22:42]
And so what it looks like is, you know, type, type name equals, and then every single line
[00:22:49]
underneath that is pipe, type, pipe, type, pipe, type. Whereas an Elm, it looks like
[00:22:54]
type, my type, new line equals variant, new line, pipe, variant, new line, pipe, variant.
[00:23:02]
So there's this asymmetry and moving it would create resistance and diff noise.
[00:23:07]
Yeah. Yeah. I don't know how I feel about that. I feel like it's an okay trade off,
[00:23:12]
but maybe I'm just too used to it, but same thing for the, the start of a list of a start
[00:23:18]
of a record.
[00:23:19]
Yeah. I definitely know that I prefer that it's not like a huge deal, but I definitely
[00:23:24]
know that I would prefer to work that way if I could, but that said it's not, not the
[00:23:29]
end of the world.
[00:23:30]
I think I would probably get used more used to that is especially as, as you said, it
[00:23:36]
would remove some churn and I would probably, and I would probably stop having to think
[00:23:40]
about it because my former owner would have handled that for me.
[00:23:42]
Yes. And just like moving things in your editor, reordering items in a list or the definitions
[00:23:48]
in a record or custom type variants, there's just that little bit of resistance. And I
[00:23:52]
I'm all about like removing those little like tiny pieces of resistance. I think that that
[00:23:58]
adds up to something that's greater than the sum of its parts.
[00:24:01]
Because Elm formats enforces one code style for all Elm projects that use Elm format,
[00:24:08]
but that it's like most Elm code basis. Yeah. The only configuration that you can choose
[00:24:14]
is whether you do single line or multi line expressions. The result of that is that you
[00:24:19]
can do some nice tricks. For instance, like if you have a record and you want to know
[00:24:26]
where a field is being set or updated, what you can do is say a field name space equals
[00:24:33]
and search for that string because you can only change a record field or set it in a
[00:24:41]
place where that exact syntax is set because that is how Elm format does it every time
[00:24:46]
for update or for setting of initial set or updating in a regular update expression.
[00:24:52]
So I find that sometimes more useful than whatever my ID gives me, depending on the
[00:24:57]
use case. And yeah, those kinds of little tricks. Like I know how to look through my
[00:25:05]
code base for finding a type. It's always type space, the name of my type.
[00:25:10]
Exactly. Yeah. Stuff like that. Yes, I totally agree. Yeah. And if you're looking for a type
[00:25:17]
annotation, you can search for top level value like function or value space colon because
[00:25:25]
it's always going to start with that if there is a type annotation.
[00:25:28]
I remember working in a like JavaScript projects where we didn't have a code formatter at the
[00:25:33]
time and I was looking for some piece of code or trying to find where something could have
[00:25:39]
been used and was looking for a specific pattern, like I don't know, some object fields, sorry,
[00:25:47]
like calling a method on a property. So it would be something like blah, blah, blah,
[00:25:53]
dot function name, parents. And I would look for dots that function and open parems. And
[00:26:01]
I remember finding after the fact that in some places people added a space between the
[00:26:07]
open parents. So I didn't find all those cases and therefore I probably introduced a bug.
[00:26:15]
Yes. So if you have something that always looks the same everywhere, it makes it so
[00:26:22]
much easier to find things in there. Yeah, I totally agree. And it does, when you're
[00:26:26]
looking for those things, it does help to know this small set of tricks that we've talked
[00:26:32]
about, which you can think of as the configuration options to Elm format. They're not options
[00:26:38]
that you configure through a configuration file. They're configured by having a new line
[00:26:43]
or not in a certain context. So when people are trying out Elm, they're not very used
[00:26:49]
to the syntax and they might say, oh, it's ugly. Yeah, I don't want to use that Elm format
[00:26:54]
because it makes the code too white spacey or I don't want single line ifs. What would
[00:27:00]
you tell them? Like, why should you use it actually? I mean, to me, it's, you know, as
[00:27:08]
I said earlier, even if I didn't agree with the decisions for the formatting rules or
[00:27:14]
if they weren't my personal preferences, which by and large, I do really like and have come
[00:27:20]
to really appreciate the design decisions for the formatting style. But even if I didn't,
[00:27:25]
I would accept that trade off that, okay, like, cause to me, the main thing is I don't
[00:27:32]
want to think about it. I don't want to talk about it. Don't talk to me about how you don't
[00:27:36]
like my style. Let's agree on an automation tool for it and then do it. And that's the
[00:27:43]
important thing to me. So that's the main thing. There's also the fact that, you know,
[00:27:47]
you can go to most, the vast majority of Elm code bases and expect it to be formatted in
[00:27:53]
that way. And also you can, you can tell pretty quickly if something is using Elm format or
[00:27:57]
not just cause your eyes get so used to seeing that format. So I think there are just so
[00:28:02]
many benefits that come from going in on Elm format that I happily make those trade offs.
[00:28:08]
Even if there are things that you're sacrificing, even if I didn't like those style choices,
[00:28:12]
I would still happily make that trade off. So I've talked to people who don't like prettier,
[00:28:18]
for instance, for their JavaScript code and their reasoning was like, it makes the code
[00:28:22]
pretty ugly, which is why it's called prettier, pretty ugly. Yeah, maybe. And I told them
[00:28:29]
like, yeah, come on. It's worth it because of all the reasons you just said. And then
[00:28:35]
he showed me some code, which was, which went through prettier and I was like, yep, you're
[00:28:41]
right. That's ugly. Because the thing is, JavaScript is a very complex language in the
[00:28:47]
sense that there's so many features and when you have plenty of features, you can arrange
[00:28:52]
them, you can combine them. So there will be cases where the code will be ugly because
[00:28:59]
there's so many possibilities and ever growing as well. TC39 committee is adding new features
[00:29:06]
left to right, which, you know, it has pros and cons, but that's one of the cons. But
[00:29:10]
in Elm, the language is relatively very simple, relatively to JavaScript. So there are no,
[00:29:18]
not a myriad of ways you can combine expressions. There will be cases where it can be kind of
[00:29:25]
very indented for instance, but I'm pretty happy with all the combinations that we have
[00:29:31]
currently. I think that's a really good point. And also as far as like overly indented code
[00:29:37]
goes, you could argue that that's a feature that you see that, that you can't hide the
[00:29:42]
actual complexity that you've introduced by deep nesting. So feeling that pain early is
[00:29:48]
actually a good thing. I want to feel that pain of deeply nesting things. And that's
[00:29:53]
one of the things with prettier that I've, I've enjoyed over just writing, writing it
[00:29:58]
by hand. I like knowing that it's going to reflect the actual structure of my code and
[00:30:04]
that I'm not being misled by the white space, that the white space isn't lying to me about
[00:30:09]
the semantics and the scope that I'm in. So what you mean is when you, when your code
[00:30:14]
is very indented, that's one sign, one smell that tells you, Hey, you should probably extract
[00:30:19]
this into a function or a constant or something. Right. And also just in terms of parsing the
[00:30:26]
code, because it happens all the time when, when I'm getting into callbacks with, you
[00:30:31]
know, deeply nested callbacks in JavaScript code or something like that. But for one thing,
[00:30:36]
you want to feel the pain that, Hey, this actually is introducing complexity and maybe
[00:30:40]
you should think about changing it. But also you want to know what scope you're in and
[00:30:44]
that you're not being lied to by the indentation that you wrote. So it gives me more confidence
[00:30:48]
about that. Yeah. I can imagine a colleague who says, Hmm, I need to add some indentation,
[00:30:55]
but I will not intend the code just so it doesn't look too ugly, but then something
[00:31:02]
where it shouldn't be. Exactly. Yeah. Yeah. I think that that's a huge benefit of using
[00:31:09]
automatic formatters. Also like this whole thing about, you know, should you have semi
[00:31:14]
colons in JavaScript code or not? I really don't care. I care if I need to type it or
[00:31:20]
not. And I don't type it with prettier. I actually just don't really configure prettier. And the
[00:31:26]
default setting is that it uses semi cons and that's fine with me. I really don't care.
[00:31:31]
I really don't care if it includes semi colons or not. You decide as a community what you
[00:31:35]
think is a good idea because of certain gotchas. If you don't include a semi colon, fine. I
[00:31:41]
really don't care at all as long as I don't have to type them and I don't have to worry
[00:31:45]
about being inconsistent, typing them someplace or another. I care about what my fingers are
[00:31:49]
doing and, and my ability to read the code. Semi cons don't really get in my way of reading
[00:31:55]
code. It's fine. So that's really what I care about. Yeah. Did you know that pretty, when
[00:31:59]
it launched, it didn't have that option for semi colons or not? It was that makes sense.
[00:32:04]
And it, the default or the only choice was to have semi cons. Yeah. Yeah. I know that
[00:32:10]
they attempted to start it out with a more zero configuration philosophy and then started
[00:32:15]
to sort of diverge from that over time. Yeah. They didn't hold the grounds. Yeah. Huge shout
[00:32:23]
out to Aaron for holding his ground and having state configuration. Yes, I agree. I think
[00:32:29]
it's a huge feature. Zero configuration is itself a feature, I think. And especially
[00:32:35]
for the author because you don't have to handle that configuration. Although it is, I'm sure
[00:32:39]
a burden to have to make choices to sort of make different groups happy who may have different
[00:32:45]
style preferences, but you know, thank you for doing that, Aaron. Yeah. In my mind, the,
[00:32:51]
the reason why it works so well for Elm format to have no configurations is because Elm format
[00:32:56]
is was there pretty early on in the, in the life of Elm. So pretty early came out after
[00:33:02]
like 22 years of JavaScript existing. So people have had careers where they were used to a
[00:33:11]
code style or maybe it grew, but they, they started to get entrenched. Is that, can you
[00:33:17]
say that? In a code style. And then it's very hard to, to go out of that code style, even
[00:33:23]
if there's a formatter for doing it all for you. So people who worked with JavaScript
[00:33:29]
for 20 years and without semicolons, like I can get why they didn't, wouldn't want a
[00:33:35]
formatter. Especially if there are plenty of other issues related to the code style.
[00:33:40]
But yeah, Elm format came up pretty early on. And for a lot of people, it was a new
[00:33:45]
language where they started using Elm along with the formatter. So yeah, it kind of helped
[00:33:52]
them and it you learned Elm at the same time as you learned the Elm syntax and indentation
[00:33:59]
and code style. So I think, I think that's a huge boost to Elm formats adoption and that's
[00:34:05]
why it's used all over the place now. That's, that's a great point. Yeah, I agree. I think
[00:34:11]
the adoption and widespread use is also a feature. Oh yeah. Yeah. If Elm format was
[00:34:17]
not as adopted. Yeah. That would be very different. Yes. Yeah. I'm very happy that there's no two
[00:34:27]
versions of Elm format. Elm format and Elm alternative version. Yeah. I'm very happy
[00:34:32]
about that. Yeah. Yeah. It's the defacto standard and it's yeah, it's a great asset to the community.
[00:34:39]
So there's one case where I could imagine that people would build an alternative to
[00:34:44]
Elm format. I recently talked to someone who was like, who was blind and he used a screen
[00:34:51]
reader for his code, which I just find impressive. It's very impressive. Yeah. Yeah. And the
[00:34:59]
problem was there, the empty lines and the buttload of empty lines that we have with
[00:35:04]
Elm format, they were actually really painful for them to work with. And it made it very
[00:35:12]
hard for them to follow indentation. And yeah, I can imagine hearing A equals B new line,
[00:35:21]
new line, new line, foo equals. Yeah. I don't know. But I can, that's how I imagine it.
[00:35:27]
And I can imagine that's painful. So I wouldn't be surprised that if some people had a blind
[00:35:33]
person or someone who needed screen reader on their team and they would fork Elm formats
[00:35:39]
for their use case to afford to have less empty lines. I could imagine that, but. That's
[00:35:45]
a really good point. I wasn't aware of that, but that is, yeah. I mean, it seems like it
[00:35:51]
would be difficult enough. I've seen like a video of someone programming with a screen
[00:35:56]
reader before and it is very impressive and difficult. I mean, imagine like navigating
[00:36:01]
code and, but yeah, I mean, it's hard enough as it is. So anything that eases that would
[00:36:06]
be great. Yeah. So if you do have such a person on your team, maybe think twice about using
[00:36:12]
Elm format or try to make their life easier one way or another. There's also some guttures
[00:36:18]
about Elm format that you sometimes need to know. So I'm writing Elm review rules as some
[00:36:24]
of you may know, and sometimes I need to work with white space issues. So I need to write
[00:36:31]
a block of Elm code in a string with white space at the end. The thing is, yeah, and
[00:36:40]
do it in a multi line string. The thing is Elm format removes that white space at the
[00:36:46]
end. It trims it. So that's one thing you need to know is that if you have multi lines,
[00:36:52]
it does change the value of the multi line strings by removing the white space at the
[00:36:57]
end. So if you have. Inside of the string? Inside of the triple
[00:37:01]
quoted string? Yeah. Really? Yeah. That's surprising. I didn't know about that. I guess
[00:37:07]
the use case for me has never come up of having, no, you can have like indentation. Are you
[00:37:13]
sure about that? It might actually be my editor. I haven't checked it. Could be my editor,
[00:37:18]
but that would be, no, that might not be that surprising actually. Oh, I need to look into
[00:37:23]
this right now. I just tried it out in IntelliJ with Elm format and I saw it format and it
[00:37:29]
did not remove the trailing white space within a triple quoted string. It is IntelliJ that
[00:37:36]
does it. My bad. Oh, it's IntelliJ. It's IntelliJ. It's IntelliJ itself? Yeah. Yeah. Did you
[00:37:42]
just Google and find something about IntelliJ doing that? No, but I've just tried it out.
[00:37:50]
Probably as right as I was before when I said it was Elm formats issue. Hmm. We may need
[00:37:56]
to look into this a little bit more. Yeah. Because I thought that it preserved pretty
[00:38:00]
faithfully what was in the triple quoted strings. It does like change if you have a backslash
[00:38:06]
N, it will turn that into a literal new line and it does a couple of things in the context
[00:38:10]
of normalizing a triple quoted string, but Elm format does it right. It doesn't remove
[00:38:16]
the white space at the end. But the thing is if you do try to trick Elm formats like
[00:38:23]
by having a unicode character for white space, then Elm format is trying to be too smart
[00:38:30]
and you replace it by a white space, which IntelliJ then removes. Oh, that's a good gotcha.
[00:38:35]
Yeah. So yeah, in that case I had to do string concatenation or replace the white space by
[00:38:44]
a stupid character like a dollar and do string.replace. That was annoying to find out. So it looks
[00:38:52]
like there are some IntelliJ settings for strip trailing white space. Yeah. Well, I
[00:38:58]
do want that, but I don't want it in some of my strings. Of course. Yeah. Yeah. No,
[00:39:03]
that's seems like a bug. There may be some bugs around that too. Maybe we can find some
[00:39:08]
links. I found like a little stack overflow thread about this as recent as 2020. So let's
[00:39:14]
gather a couple of resources about this topic and share them. But it seems like Elm format
[00:39:20]
is off the hook for this problem. It is off the hook. Problem is an editor issue, not
[00:39:25]
Elm format. So good. I'm very sorry, Aaron. The other issues that are raised in the repo
[00:39:33]
are still valid. Please look at them. Yeah. So while we're talking about multi line strings,
[00:39:41]
there are some helpful things it does. Like if you have, like I think if you have like
[00:39:44]
a literal tab, won't it turn that, or if you have a, like a backslash T, it turns that
[00:39:50]
into a literal tab. And if you have a backslash N, it turns that into a literal new line.
[00:39:56]
So it's opinionated about like regular strings in Elm. It will not use the literal tab. It
[00:40:04]
will use backslash T and triple quoted strings. It will use the literal. Yeah. It doesn't
[00:40:10]
do it for backslash T. It does it for backslash N. Only for backslash N. Yep. Okay. So it
[00:40:15]
preserves backslash T, which is probably good because visually it's harder to pick that
[00:40:19]
out. Yeah, probably. And I think it does the same for, I think in general for Unicode characters,
[00:40:25]
it normalizes them. Right? Yeah. I'm guessing there's a range where it does, where it applies
[00:40:31]
that and another range where it doesn't, but yeah. So in general, like one trick that I
[00:40:37]
sometimes use, Elm format is really interesting because it's a formatter, but you also sort
[00:40:42]
of use it as a tool to perform certain transformations. So like if you have a regular Elm string with
[00:40:49]
new lines in it, you can just add two quotes on either side of the string and turn it into
[00:40:54]
a triple string and it'll turn them into literal new lines, which is a nice feature. So if
[00:40:59]
that's what you wanted to, yeah. Well, yeah. I mean, I think that's a reasonable opinion
[00:41:05]
that it should, in the triple quoted string, it should visually look like a new line and
[00:41:09]
you shouldn't be able to mix backslash N with a literal new line. That would cause problems.
[00:41:15]
Yeah. Yeah. So I like that about it. It's worth noting that IntelliJ has a built in
[00:41:22]
feature which Joni Gibbs contributed, which you can convert a regular string to a triple
[00:41:28]
quoted string and it sort of performs some of those normalizations as well. So you don't
[00:41:32]
necessarily have to do it using that Elm format trick, but you can if you want to.
[00:41:36]
So we've talked about it a lot, but like the main thing you need to do when you use Elm
[00:41:42]
formats, in my opinion, is to enable it in your editor. If you already haven't, do it.
[00:41:47]
The Elm formats project ReadMe explains how to enable it in a lot of different editors.
[00:41:53]
Yeah. Yeah. You can look at that. We'll link to that, but it's basically just a table that
[00:41:59]
has which editors have an integration with Elm format and the instructions to set it
[00:42:05]
up. I would actually add, you said that basically what you need to do to use Elm format is to
[00:42:12]
configure it with your editor. I would add one other thing. In my opinion, you're not
[00:42:18]
really using Elm format unless you're running it in your CI because that's the central source
[00:42:22]
of truth. So for example, it's possible that you could have different Elm format versions
[00:42:29]
that people have set up with different editors. They could be pointing to their globally installed
[00:42:33]
Elm format version rather than a locally installed one in the project. There are all sorts of
[00:42:37]
things that could happen like that. So I would say that it's really important that your build
[00:42:43]
be the central source of truth for making sure that stuff is formatted so that you don't
[00:42:49]
ping pong back and forth between formatting with different versions or anything like that.
[00:42:53]
Yeah. The same thing for Elm review.
[00:42:55]
Yes. Right. Exactly. Yeah. I mean, I think it's equivalent to having frontend validations,
[00:43:04]
right? You can validate that somebody is an admin user on the frontend and don't expose
[00:43:11]
a certain thing in the UI unless you're an admin user, but that's not enough. That's
[00:43:16]
like helpful as far as user experience goes, but you need to enforce that in the backend
[00:43:22]
part and it's the same with your build. I would think of the build as the actual source
[00:43:26]
of truth for enforcing all of those configurations and rules.
[00:43:31]
And now it's easier than ever to enforce Elm format in your CI because as we've seen with
[00:43:36]
Elm tooling in the last episode, it's very easy to install and cache and run.
[00:43:42]
Exactly. Yeah. And that's another, I mean, as we were saying, you could have this issue
[00:43:47]
of having different Elm format versions and the CI should be the source of truth for which
[00:43:53]
Elm format version and which files it applies to, but it doesn't hurt and it's a very good
[00:43:58]
idea to also have a source of truth of which versions you're running for a project using
[00:44:03]
your package JSON or even better, the Elm tooling CLI, which you can listen to our episode
[00:44:09]
on that. Yeah. You don't want to check out someone's
[00:44:13]
branch and then press save and find that Elm format formats are differently. That is really
[00:44:19]
the scenario that you want to avoid because that will create a lot of noise that we said
[00:44:24]
we don't want. And then one last sort of caveat here. So
[00:44:30]
you can run, we didn't mention the actual command, but you can run Elm format with the
[00:44:35]
dash dash validate flag. And that's what we've been talking about running on the CI. So you
[00:44:41]
can run Elm format from the terminal rather than your editor. Your editor should be the
[00:44:47]
primary place you're using it. But if you wanted to, you can run it from the command
[00:44:51]
line and have it modify the files and format them in place. But more often what you'll
[00:44:57]
want to do from the command line version of Elm format is run the dash dash validate flag.
[00:45:02]
Yeah. I've run it once in my tests. Yeah. Yeah, exactly. Yeah. So one caveat to that.
[00:45:09]
And for those wondering, if you also have Elm review, you should run Elm format before
[00:45:14]
Elm review. That's something that I, the Elm review rules kind of expect the code to be
[00:45:21]
Elm formatted. That's how widespread Elm format is. And when it fixes something, it will reapply
[00:45:28]
Elm formats. Yeah. Right. Right. Interesting. Also, if you have generated code, you want
[00:45:35]
to skip running Elm format dash dash validate on the generated code. I usually like to have
[00:45:41]
a gen folder and a source folder in my Elm.json source directories. And so you can validate
[00:45:48]
on your source folder and your tests folder and not validate Elm format in your gen folder,
[00:45:53]
because as long as it compiles, you're happy. You don't care how it's formatted. What do
[00:45:58]
you do when you generate code? Do you try to make the code look kind of Elm formatish
[00:46:03]
or do you run Elm format afterwards? I run Elm format afterwards. I've tried with like
[00:46:09]
the Elm GraphQL generated code, for example. I tried, but so there are a couple of problems
[00:46:14]
with that. For one thing, what about different Elm format versions? How do you target those?
[00:46:21]
So that's a whole rabbit hole and an issue that you can't really solve that properly
[00:46:26]
and you shouldn't. That doesn't make sense. Well, then why do you run Elm format on it?
[00:46:31]
Because the user might actually use a different version. No, I run the user version. I'm actually
[00:46:38]
working to improve that. We talked about it a little bit in our last episode with Simon
[00:46:42]
Lydell, but I'm currently using NPX to run Elm format, which is not really what I should
[00:46:48]
be doing. I should be doing more what Elm review does to search for it in the path to
[00:46:53]
see if Elm tooling is set up and find that version and give different options. No, for
[00:46:58]
now, at least it does NPX and falls back to the path. To the path. Yeah. And that may
[00:47:03]
be at some point it should look at the Elm tooling JSON file. Yeah, which it should be
[00:47:10]
on the path ideally if you're using Elm tooling. So yeah, I mean, but in my opinion, it's sort
[00:47:16]
of a losing battle to try to automatically generate that code. On a similar note, and
[00:47:22]
you can also get very complex rules. It would get very sophisticated with particular types
[00:47:27]
of generated code. But the Elm format is relatively stable, so you wouldn't change all that much
[00:47:34]
to use Elm formats. But there are some cases that get quite complicated. I try to be relatively
[00:47:41]
close but not worry about it too much. Also, we sort of talked about the challenges with
[00:47:49]
formatting when you have a white space sensitive language like Elm. And that actually becomes
[00:47:55]
a really challenging issue when you're working with editor plugins. So when I've worked on
[00:48:00]
contributions to the IntelliJ Elm plugin, that is, believe it or not, in many cases,
[00:48:06]
that's by far the hardest part is getting the formatting right because you have to look
[00:48:11]
at the content. You can't just throw in some curly braces and say, all right, I'm creating
[00:48:14]
a new scope, a format or tool, figure it out. If you're adding something to a lead expression,
[00:48:21]
you have to figure out where to start that indentation. And I find that painful both
[00:48:27]
for writing automated editor tooling or automated tools to get the formatting right, but also
[00:48:34]
as a human. That's probably the most painful thing about the experience of typing Elm code
[00:48:40]
and formatting Elm code in my experience is getting the white space to line up in lead
[00:48:46]
expressions and case statements.
[00:48:48]
Yeah, that is probably the biggest, that is probably the hardest problem when you try
[00:48:53]
to fix a syntax error is trying to line it up. Which one is not lined up? When they're
[00:48:59]
all lined up, even if the rest is ugly, save and you're good. So it doesn't happen too
[00:49:04]
often, thankfully, but yeah.
[00:49:07]
So Jeroen, I think it might be time for our Elm format editing productivity tip section.
[00:49:13]
Let's do a lightning round. So you've got a really great tweet with a whole bunch of
[00:49:19]
great tips for sort of like Elm format workflow tips. These are like these little Easter eggs,
[00:49:25]
these little tricks that you can use to sort of leverage Elm format to have it do more
[00:49:30]
work for you or to get it to format a particular way. So let's go through a lightning round
[00:49:35]
and go through these.
[00:49:36]
Yeah, so a lot of them are about indentation. So unless we talk about case expressions,
[00:49:42]
we don't, Elm format doesn't really need to know the indentation. It can figure it out
[00:49:47]
on its own. So if you do A equals one, it will move the one to the new line. But if
[00:49:53]
the one is even on the next line, at the very beginning, it can figure out that it should
[00:50:02]
be indented. If you have a single, if you have a case expression with a single pattern,
[00:50:07]
then you can also handle pretty much everything on its own because there's no mismatch between
[00:50:12]
indentation between patterns because there's only one pattern.
[00:50:17]
And by the way, these are habits, just leveraging these little tricks to more efficiently use
[00:50:23]
Elm format and have it do more work for you and you do less work. They're habits. And
[00:50:27]
so I highly recommend, look at this tweet, take one of these and try building it in as
[00:50:34]
a habit. Also, just try things. If you're like, can Elm format handle this input? Just
[00:50:40]
try it, just save right away and get in the habit of saving more often and notice when
[00:50:46]
you're typing more than you need to, to get it to format properly and try to do as little
[00:50:50]
as possible.
[00:50:51]
Yeah, I sometimes amuse myself by counting how many keystrokes I type.
[00:50:55]
Nice Elm format golf.
[00:50:57]
Yeah, I do type in the white space usually, but that's about it because it still needs
[00:51:03]
to make sense in my head.
[00:51:05]
White space costs extra.
[00:51:06]
It costs only nothing. It's empty.
[00:51:09]
Tell that to your pinky.
[00:51:12]
Wait, my pinky?
[00:51:15]
Did you use your pinky for the space bar?
[00:51:20]
For a return.
[00:51:21]
Yeah, okay. Yeah, I use a pinky for that one. Okay. So there's one very nice thing that
[00:51:30]
Elm format does and that could help beginners without them even noticing is that Elm format
[00:51:36]
is smart enough to know when you should use colons or equals in records. So if you do
[00:51:43]
open curly brackets, B colon one and bracket, and you do that in an expression. Well, that's
[00:51:52]
a syntax error because you should be using equals instead of colon, but Elm format is
[00:51:57]
smart enough and it replaces the colon by an equal sign plus adds all the white space
[00:52:01]
and the indentation. So if you ever do that kind of error, well, Elm format handles it
[00:52:06]
for you and it does this for the other way around. So if you use equal in type annotation
[00:52:11]
then or in the type definition, then it uses the colon.
[00:52:16]
Right, which that's useful for beginners and for experienced Elm programmers who know that
[00:52:23]
that's the correct syntax, but maybe you copy paste a type alias for a record and you want
[00:52:31]
to create a literal value or you copy paste a literal value to define a type alias for
[00:52:37]
a record. Now you don't have to do the extra work. You can just let it figure it out and
[00:52:41]
you change the types to the right of the colons to concrete values or type annotations depending
[00:52:47]
on what it needs to be.
[00:52:49]
Yeah, if you have a lot of fields and the names are too long, then that's a big time
[00:52:55]
save. Everything is relative, but yeah.
[00:52:59]
What if it would be an interesting feature. What if Elm format took, so if you say like
[00:53:03]
if you have type alias and then a record and you say like first colon string, last colon
[00:53:09]
string, age colon int, and then copy paste that and try to create an instance of that.
[00:53:16]
What if Elm format changed the strings to empty string and the int to zero? I don't
[00:53:22]
know. Maybe that's like, maybe that could like cause issues or that's too strong of
[00:53:26]
an opinion, but I would find that useful for my own workflows because I find myself doing
[00:53:30]
that all the time where I just like multi select all of the word capital string and
[00:53:36]
change them to empty string so I can start, so I can get valid syntax and then start entering.
[00:53:40]
Yeah, that's where it's lying between a code formatter and a dev productivity tool.
[00:53:48]
Exactly.
[00:53:49]
Bit blurry, but yeah.
[00:53:51]
It sort of straddles those two categories, but that's also, by the way, that's another
[00:53:58]
principle that I try to follow when using Elm format and just in general is try to get
[00:54:02]
to valid syntax first as soon as possible. Don't like defer, have like a missing current
[00:54:09]
or curly brace or missing parenthesis or something like that for a long time and then start typing
[00:54:16]
a bunch of stuff. Do the thing that makes the syntax valid so Elm format is happy and
[00:54:21]
then start replacing.
[00:54:22]
Yeah. I very often do like, if I know I need to do a let's expression, I start typing let
[00:54:29]
a equals something.
[00:54:31]
Yes.
[00:54:32]
And then in, and I want to focus on the let declaration. So what I do is after the in
[00:54:38]
and type in like one or something and then press save. So at least the syntax is correct,
[00:54:43]
even though it doesn't compile.
[00:54:45]
Exactly. I do that as well and I do that also for like modules. If you define a new module,
[00:54:52]
module foo, you're going to need to define a top level value or top level definition.
[00:54:59]
So I'll usually just say foo equals one, two, three, just so it's now compiling. And now
[00:55:05]
I can write the thing I want and then delete that or replace it when I'm ready. But at
[00:55:08]
least I'm starting with valid syntax.
[00:55:11]
Those two and three are, you know, they have a cost, right?
[00:55:15]
That's true.
[00:55:16]
Yeah. Let's talk about module definitions. So if you don't have a module definition,
[00:55:22]
you know, where it says module a exposing blah, blah, blah, then Elm format will generate
[00:55:26]
one for you. I think by default it will add all the things that you defined in the file
[00:55:32]
and add them to the exposing clause. If you only have like module main and not exposing
[00:55:37]
something, exposing something, then it will do the same thing. So if you were...
[00:55:43]
Even though that's, as far as Elm is concerned, it's invalid syntax to say module main and
[00:55:49]
then start your module. But as far as Elm format is concerned, it can figure out, okay,
[00:55:54]
I'll create the exposing clause for you.
[00:55:56]
Yeah. So if you like to prototype with exposing parents dot dot parents, then once you're
[00:56:03]
happy, you can remove exposing dot dot and Elm format will add whatever is in your module.
[00:56:09]
And then you can only, you can go and remove the ones that you don't want to expose.
[00:56:14]
Exactly. And it's kind of interesting because Elm format can, or Elm review can also do
[00:56:19]
that for you. The Elm review no exposing all rule can automatically, there's an auto fix
[00:56:25]
available where you can allow it to find all the top level definitions and expose all of
[00:56:31]
those explicitly, which is the same thing that Elm format does essentially.
[00:56:34]
Yeah. No exposing everything. Yeah. Another thing that it will do is like, it's not very
[00:56:39]
tricky, but yeah. Another thing that it will do is remove duplicates. So if you do exposing
[00:56:46]
B comma B, then it will show that to just B. You don't need the parents. If you do exposing
[00:56:54]
B and you have only a single item, it will add the parents and for imports, they all,
[00:57:00]
it will also remove the duplicate imports. In this case, I think it is trying to be too
[00:57:06]
smart sometimes. So if you do like import A as B and you have another import A, then
[00:57:13]
it will remove the imports A. So that changes the behaviors slightly, but it's an easy fix.
[00:57:19]
So right. Also worth noting that it will alphabetize your import list. So it's deterministic.
[00:57:27]
I'm so happy about that one. Yeah. It's very nice. I'm also very happy that Elm chose to
[00:57:32]
have the module names before what is exposed because I've seen so many proposals in ESLint.
[00:57:39]
I've actually written in ESLint's imported order rule, which was part of my beginnings
[00:57:46]
with the open source, where we try to order the imports and having just the format and
[00:57:54]
handle that for us in, I think a pretty reasonable way. That's just a huge time saver. You don't
[00:58:02]
know how much people want to discuss import order in other languages. I still have issues
[00:58:09]
open like five years later about, Hey, can we add this sorting order for imports? No,
[00:58:19]
just leave it alone, please. It's a nice feature. So if you're writing a package with documentation,
[00:58:26]
or I guess just writing documentation for a module, you can use the module and top level
[00:58:33]
definition documentation feature, the doc comments, which are open curly dash vertical
[00:58:39]
bar. So if you use that functionality, Elm format has a few things it does with that.
[00:58:45]
It will snap the definitions. It associates those with the top level definition you have.
[00:58:51]
So if you do doc comment and then foo equals one, two, three. Now that comment is not floating
[00:58:58]
on an island in the middle of nowhere. It's attached to that top level definition of foo,
[00:59:04]
which is nice for formatting. So if you want to write a little comment describing a function,
[00:59:09]
you should use that even if you're not doing a package where it would use those docs for
[00:59:13]
the package. And a lot of your editor tooling will actually, if you hover above an internally
[00:59:19]
used function and stuff, it will show you the doc comments. So it's a good feature to
[00:59:24]
leverage for regular Elm applications as well.
[00:59:27]
In the exposing clause of the module, if you have a documentation for your module and you
[00:59:35]
have at docs clauses where you say at docs foo comma bar, then Elm format will order
[00:59:46]
whatever is in your exposing to match the order of that documentation.
[00:59:51]
Right. And it'll group those on the same line. For anyone who doesn't know, it's like the
[00:59:55]
at symbol, D O C S space, and then a comma separated list of top level definitions, types,
[01:00:03]
functions, values. And that's what package Elm package authors use to organize their
[01:00:10]
docs. If you notice that Elm packages will have like different sections with different
[01:00:14]
headings and then it'll have the documentation for specific functions and types and values
[01:00:21]
under those headings. That's how that's organized.
[01:00:23]
Yeah. And if you have several ones that are not documented, they will all be at the end
[01:00:28]
of the exposing clause on one line. So you know, oh, these are the ones that are not
[01:00:33]
exposed. They don't have doc comments. Interesting. So we've got a few more tips from your tips
[01:00:42]
tweet. Should we go through some more of those? Are there any other highlights? Oh, you sort
[01:00:48]
of covered it by describing the sort of general techniques. Cool. So that's worth scanning
[01:00:54]
through. Also, another thing that Elm format will do that people will probably notice from
[01:01:00]
using it pretty clearly, it will remove unnecessary parens in most cases, but not all.
[01:01:07]
I think there are plans to make that better. To do it everywhere.
[01:01:12]
Like one of the places it currently doesn't do it, that maybe there are plans being discussed
[01:01:18]
for doing is with pipelines. If you have right pipe expressions.
[01:01:23]
Yeah. In general, it's with operators and there are plans to improve that.
[01:01:28]
That would be great. Yeah. Cause there are cases where it's just provably equivalent
[01:01:36]
if you remove the parentheses, but I mean, it is difficult because parentheses can sometimes
[01:01:40]
mean semantics. Also in terms of workflow, sometimes you put in some parentheses and
[01:01:46]
you're like, Oh, great. I've got these nice little parentheses that I can start typing
[01:01:50]
my function calling. And then you like you save and you're like, Oh, the parentheses
[01:01:54]
are gone. So you have to sort of, or if you're using like IntelliJ with auto saving, you
[01:01:58]
have to like race to the finish to get in space arguments so that it sees that it needs
[01:02:04]
parentheses, because if you don't do it within the four second time or whatever the auto
[01:02:08]
save window is, it'll form at it. So I think it's interesting.
[01:02:13]
I wouldn't recommend using auto save, especially with a formatter.
[01:02:17]
I think it's on by default, isn't it? Oh, it's at least not enabled on my machine.
[01:02:22]
That's a, that's for sure. Oh, maybe. Yeah, maybe not. I'm not sure. Auto save cannot
[01:02:27]
be disabled completely. Is that an issue? I went, I went to the system settings in IntelliJ
[01:02:34]
and it literally says auto save cannot be disabled completely with a link. How it works.
[01:02:40]
Right. So there are probably plenty of things that
[01:02:43]
M4M1 does and that we don't know that I'm not aware of at least. I know that Aaron hints
[01:02:51]
that there are being more features to discover. So that's if you want to have fun, either
[01:02:57]
go through the tests of the project or like try to have fun and discover, Hey, can it
[01:03:03]
fix this? What happens if I do this? That could be a good five minutes of fun, I guess.
[01:03:09]
Yeah. I know Aaron's also been doing some live streams on Twitch with working on Elm
[01:03:15]
format occasionally. And he'll, I know he's been working towards getting it to 1.0 and
[01:03:20]
he's got like, I mean, it's so stable. It's like, I think of it as a very 1.0 stable tool,
[01:03:27]
but he's got a few things I know on his list of things he'd like to do before calling it
[01:03:32]
1.0 officially. I think one of the main ones there is single
[01:03:36]
online ifs and also patterns for... Oh, interesting. Maybe we can link to those
[01:03:43]
issues. Yeah, we can do that.
[01:03:45]
Cool. But yeah, you can go and have fun looking through
[01:03:48]
the issues to see what people talked about even years ago, when they thought that something
[01:03:56]
was a good idea. Right. There's an interesting, at this point,
[01:04:02]
effectively historical document. There's actually in the elmlang.org website, there's a style
[01:04:08]
guide, which you'll find in the show notes. And it's kind of interesting because I think
[01:04:14]
it was sort of the precursor to Elm format, sort of laying out principles like this one
[01:04:21]
says, types, do not be a maniac with indentation. Simplicity will be better in the long run.
[01:04:27]
And then it's got this example where you have like...
[01:04:29]
A line. Yeah.
[01:04:30]
You've aligned with all this white space before the colons in these record types definitions.
[01:04:38]
And it's like you align all the colons, even though the names of the field names are different
[01:04:44]
lengths. And it's like, I remember spending time doing that in Ruby and it's such a waste
[01:04:50]
of time. Just let the formatter have an opinion about it and do it.
[01:04:53]
Well, there are issues to enable that on Elm format.
[01:04:56]
Oh, really? Or behind a configuration flag, you know?
[01:05:00]
Interesting.
[01:05:01]
But they're pretty recent too, some of them. So yeah, I would really recommend against
[01:05:07]
that. It can be nice, but it's such a nightmare.
[01:05:11]
It creates a lot of churn with the diffs. And I think that churn is one of the core
[01:05:17]
values. I think that Elm format has tried to follow that. And that's just one of the
[01:05:21]
things I seek in my ideal formatting tools and the way I use those tools.
[01:05:27]
Yeah. But yeah, if you need to align things based on the size, based on the number of
[01:05:33]
characters of a variable or even expression on the right, that makes things very complex.
[01:05:40]
And you will have a lot of white space if you have very short variable names or field
[01:05:44]
names followed by a very long one. That's just not great, I think.
[01:05:49]
That said, if Elm format decided to go with that route, then I would probably get used
[01:05:55]
to it. And I would be fine with that. But that's not what I would advise for.
[01:06:00]
Another tiny little trick here, workflow trick, is for users who are using Vim or Vim emulation
[01:06:06]
in their editor, there's a Vim command join lines. I think actually IntelliJ has like
[01:06:12]
a built in join lines command too, even if you're not using Vim mode.
[01:06:17]
But in Vim, it's capital J. And that will take the current line you're on and effectively
[01:06:24]
remove the new line and combine it with the next line with a space. So if you have something
[01:06:29]
that's in multi line mode, like a record or a list, and you want to turn it into single
[01:06:34]
line formatting, capital J, capital J, capital J, capital J can be a handy little trick for
[01:06:40]
getting all those lines onto one line. Although in general, I lean towards multi line formatting
[01:06:45]
mode more often than not.
[01:06:48]
There's the same thing in most editors. The shortcut to the i sign was control J. But
[01:06:53]
that might be just me changing it to control J because that was the way it was in Atom.
[01:06:59]
But what you can do is select a code block and do that shortcut. And then you only have
[01:07:05]
to do it once because you know, pressing J multiple times has a cost.
[01:07:10]
Exactly. That's right. All right. Well, any last tricks that we missed or should we move
[01:07:17]
on to how to get started?
[01:07:20]
Yeah, maybe we should talk about how to get started now.
[01:07:25]
I mean, I think we kind of covered it. We talked about set it up in your CI. We talked
[01:07:31]
about share a common version in your project, either using npm install dash dash save dev
[01:07:36]
elm format, or using the elm tooling CLI, which we discussed on a previous episode.
[01:07:43]
And please integrate it into your editor. Don't just run it in the CLI. It's part of
[01:07:49]
the workflow.
[01:07:50]
Oh, and yeah, if you're working on a project and it doesn't use elm format, do talk to
[01:07:55]
your colleagues about enabling it and make the choice together. I think it's a very good
[01:08:00]
choice, but you should definitely talk about it with your colleagues.
[01:08:04]
That's a great point. Also, I've flipped the switch on code bases to elm format them before.
[01:08:11]
And just to give a brief overview of what that looks like and what I've done there.
[01:08:19]
I would say that, you know, I think it's best to do it as an atomic step to just have a
[01:08:24]
single commit that runs elm format across all files and introduces this is important
[01:08:30]
CI check that will fail the build if it's not formatted properly. So at that point, so
[01:08:36]
you're going to want, of course, you're going to want sort of team consensus before you
[01:08:40]
do this.
[01:08:41]
It would be very rude to just do that without talking to your team. And you're also going
[01:08:45]
to want to just help people get elm format set up and understand what it is and how to
[01:08:51]
use it in their editors.
[01:08:53]
You need to make that very simple for everyone to use.
[01:08:56]
Yeah, exactly. Often you'll want to create like a little intern internal wiki entry for
[01:09:00]
your company wiki or something like that, that links to like a couple of resources for
[01:09:05]
your specific setup instructions.
[01:09:08]
Or even have you like your test suite when it finds that elm format is not has problems.
[01:09:13]
Like add something in CI saying, hey, this is what you should do now to run elm format.
[01:09:19]
Right. And then I would recommend doing that as a single atomic change where you run elm
[01:09:25]
format and add the CI step as a single commit rather than sort of little by little formatting
[01:09:32]
files and running elm format and having diffs.
[01:09:35]
Also I recommend not combining code changing commits with elm review application commits.
[01:09:43]
I mean elm format, but yeah, sorry.
[01:09:47]
Maybe both. Yeah, maybe in general it's elm format is part of writing elm code, but the
[01:09:54]
initial step you don't want applying elm format the first time to a file to be the same commit
[01:10:01]
as writing that writing or changing that code.
[01:10:04]
And also be aware that it will destroy your git blame.
[01:10:08]
Yeah. But if you have just a single commit, there are like some git tricks.
[01:10:12]
Some people use like a destructive history destroying version where it applies elm format.
[01:10:17]
I don't think that that's a good idea.
[01:10:20]
Apparently there are ways to have git interpret a certain commit as something to skip over
[01:10:26]
when you do git blame.
[01:10:28]
Maybe I'll see if I can find a link and link to that in the show notes.
[01:10:32]
That'd be useful. I don't know about that either.
[01:10:35]
But all the more reason to do it as an atomic step with a single commit is just like rather
[01:10:40]
than having 50 different commits over time in a scattered way where the git blame is
[01:10:45]
pointing to just do it as a single commit.
[01:10:48]
Well, if you were curious about elm format, I'm pretty sure your curiosity has been satisfied
[01:10:56]
at this point.
[01:10:57]
And I'm pretty sure that you learned something.
[01:10:59]
I hope you learned something.
[01:11:03]
I hope you learned something whether you're new to it or familiar.
[01:11:07]
And if there's a tip that we missed, please let us know.
[01:11:10]
Tweet us at elm radio podcast on Twitter.
[01:11:13]
If you have an additional topic you would like to hear us talk about, then please submit
[01:11:17]
a question elm dash radio dot com slash question.
[01:11:20]
And don't forget to rate us and subscribe on Apple podcasts.
[01:11:24]
Well, Jeroen, until next time.
[01:11:27]
Until next time.
[01:11:28]
Bye bye.