# Runic.jl: A code formatter with rules set in stone

**URL:** <https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898>\
**Category:** Package Announcements\
**Created:** [August 6, 2024, 3:15pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898 "2024-08-06T15:15:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [August 6, 2024, 3:15pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/1 "2024-08-06T15:15:46Z")

</div>

I have been tinkering with a code formatter that I want to announce: [Runic.jl](https://github.com/fredrikekre/Runic.jl).

 ![image](https://global.discourse-cdn.com/julialang/original/3X/a/1/a15268fd4a7a0c02cc105eced7e6bde2acce765d.png)  
_Sample output from running Runic with check and diff mode enabled on a small code base._

Just like e.g. [gofmt](https://pkg.go.dev/cmd/gofmt) (Go formatter) and [black](https://github.com/psf/black) (Python formatter), Runic has _no configuration_. This is a feature that, in particular in the [Go community](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=523s), is very popular which is why I wanted to try this out also for Julia.

Refer to the [README](https://github.com/fredrikekre/Runic.jl/blob/master/README.md) for:

- [Installation instructions](https://github.com/fredrikekre/Runic.jl/blob/master/README.md#installation)
- [CLI usage](https://github.com/fredrikekre/Runic.jl/blob/master/README.md#cli)
- [Editor integration](https://github.com/fredrikekre/Runic.jl/blob/master/README.md#editor-integration)
- [Enforcing formatting](https://github.com/fredrikekre/Runic.jl/blob/master/README.md#checking-formatting)
- [Formatting specification](https://github.com/fredrikekre/Runic.jl?tab=readme-ov-file#formatting-specification)

I have tested the formatter on all julia code in base and all julia code in my `.julia` folder without errors (although I have not visually inspected all those tens of thousands lines of code, of course) so I would consider it safe to start trying out.

Note that the package is not yet registered so ideas for more transformations or feedback on current transformations are very much appreciated! Please [open an issue](https://github.com/fredrikekre/Runic.jl/issues/new) if you have any type of feedback.

Thanks!

---

<div class="post-metadata">

**Author:** ![\_bernhard](https://avatars.discourse-cdn.com/v4/letter/_/bc79bd/32.png) [@\_bernhard](https://discourse.julialang.org/u/_bernhard)\
**Post date:** [August 6, 2024, 6:09pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/2 "2024-08-06T18:09:33Z")

</div>

Thanks for contributing this great package!

Also, I very much agree, that the absent configurability can be a huge advantage.  
Of course formatting style is a matter of taste and the applied style does not need to (and certainly will not) be everyones favourite.

Also, I find all style choices at least reasonable.

Or rather all except one…

I feel like spaces around keyword arguments really decrese legibility.  
Also, I have never really seen this style in the wild and thus would be interested in why you made this decision?  
Do you prefer it like that? Do others prefer it like that? Or is it for the sake of parser simplicity and/or pragmatism, handling all `=`s in the same way?

If this is due to the latter, would you consider changing this - if an overwhelming majority of users have similar reservations?

However, irrespective of my critisism, I could see myself employing Runic.jl as default formatter. 😃

EDIT: After some healthy rumination, it became clear to me that my primary objection to space-flanked kwarg-`=` is in function definitions/calls formatted as a single line.  
As soon as the formatting is one line per kwarg I might still not find it appealing, but in terms of code legibility I think it’s perfectly fine.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [August 6, 2024, 10:20pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/3 "2024-08-06T22:20:47Z")

</div>

Thank you for having a look and for the comments.

> [@\_bernhard](#):
>
> spaces around keyword arguments […] is it for the sake of parser simplicity and/or pragmatism, handling all `=`s in the same way?

This is actually the original reason. This comes as a result of me implementing the “spaces around assignments” rule without restricting the context of it and realize afterwards it also happened to apply to keyword arguments in function definitions and function calls.

> [@\_bernhard](#):
>
> I have never really seen this style in the wild

It looks like at least [SciMLStyle](https://github.com/SciML/SciMLStyle) recommends it (although it is a bit cryptic).

> [@\_bernhard](#):
>
> Do you prefer it like that?

I realized after trying Runic on some code bases that I was very inconsistent. For example I think I (used to) prefer no spaces around “simple” keyword arguments like e.g. `foo(; bar=true)` but not more complicated ones like e.g. `foo(; bar = baz(foo + 3))` etc. I think that now I have come around to always use spaces because of consistency and because it seems kind of arbitrary to not use spaces in this specific context but everywhere else.

---

<div class="post-metadata">

**Author:** ![savq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/savq/32/22063_2.png) [@savq](https://discourse.julialang.org/u/savq)\
**Post date:** [August 6, 2024, 11:11pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/4 "2024-08-06T23:11:26Z")

</div>

Since you’ve mentioned “context”, I wanted to ask: Are there contextual transformations that would be in scope for this project?

I’ve never been a fan of Julia being team [TMTOWTDI](https://perldoc.perl.org/perlglossary#TMTOWTDI), and I wonder how practical it’d be to have a tool that does more complex normalizations. For example, transforming

```diff
-(foo; bar; baz)
+begin
+ foo
+ bar
+ baz
+end

```

but also:

```diff
-:(foo; bar; baz)
+quote
+ foo
+ bar
+ baz
+end

```

and things like

```diff
-() -> begin
+function()
    foo
    bar
    baz
 end

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [August 7, 2024, 2:36am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/5 "2024-08-07T02:36:31Z")

</div>

> [@\_bernhard](#):
>
> spaces around keyword arguments

I also usually prefer no spaces, but one argument for spaces is that they prevent syntax ambiguity errors. Specifically, if the keyword ends in a bang, like `foo! = bar`, the no-space version is parsed as `foo != bar`, which is obviously not valid keyword argument syntax.

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [August 7, 2024, 8:56am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/6 "2024-08-07T08:56:41Z")

</div>

Well, obviously, a package like this invites lots of comments because everyone’s preferences are different. But I can’t help myself 😃

```diff
- function test(a::Union{Int,Float64}, b::T; foo=:bar) where {T<:Number}
- # body
- end
+ function test(a::Union{Int, Float64}, b::T; foo = :bar) where {T <: Number}
+ # body
+ end

```

Personally, in addition to kw args not having spaces I really like not having spaces within `{ }` blocks, which is also part of some existing style guides.

For me, there are two reasons for that:

- Function signatures can be relatively complex without going crazy in length.
- Spaces are about separating different “semantic” blocks in an expression. I think function signatures should highlight the separation of arguments first. Type information and keywords are tightly bound to the respective argument

I think `{ }` blocks, in general, tend to be messy, especially when nested. Let’s embrace the chaos and omit spaces, they’re ugly either way!  
But of course everybody taste is different, which is why I quite like the approach of not having any options and would consider using your package, regardless of the rules you settle on.

Big up for the readme, it’s super nice that you included tutorials for git hooks and GitHub actions!

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [August 7, 2024, 9:06am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/7 "2024-08-07T09:06:09Z")

</div>

Obviously it’s all very subjective but I think the fact that these signatures can be complex and `{}` blocks can be too is, in my opinion, even more reason to want spaces.

And Runic is really nice, thanks for this great contribution @fredrikekre! I’m really pleased with how it looks in my code.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [August 7, 2024, 9:11am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/8 "2024-08-07T09:11:51Z")

</div>

> [@fredrikekre](#):
>
> I think that now I have come around to always use spaces because of consistency and because it seems kind of arbitrary to not use spaces in this specific context but everywhere else.

Agreed on this point. I’ve never understood why the reasoning that spaces around `=` improves readability should not apply to keyword arguments.

Not that I will use Runic anyway, since the multiline formatting is a dealbreaker for me.

---

<div class="post-metadata">

**Author:** ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)\
**Post date:** [August 7, 2024, 9:45am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/9 "2024-08-07T09:45:33Z")

</div>

Thank you for this package, this is very close to my preferred style so I am considering using it going forward. Small issues I noticed trying it out:

In some situations involving macros, Runic seems to change meaning. For example, in

```julia
using Catalyst
net = @network_component net begin
    r, X --> Y
end
net′ = extend(net, @network_component (@species Z(t);))

```

Runic removes the `;`, making the syntax invalid.

Another issue is related to linebreaks after `=`, both for short-form function definitions and variable assignments. Runic changes

```julia
y =
    if x
      1
    else
      2
    end

```

to

```julia
y =
    if x
    1
else
    2
end

```

which is probably not intended.

(The only style choice I disagree with is that

```julia
function f(
    x
)
    x
end

```

is formatted as

```julia
function f(
        x
    )
    x
end

```

because I feel that the `)` should be indented just like the start of the line containing the matching `(` and the double indentation is unnecessary in my opinion. Ideally I would also prefer

```julia
f([
    a
    b
])

```

to be allowed, that is, Runic not forcing a linebreak before `[` in situations like this, but I could get used to it.)

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [August 7, 2024, 9:58am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/10 "2024-08-07T09:58:53Z")

</div>

> [@hexaeder](#):
>
> I really like not having spaces within `{ }` blocks, which is also part of some existing style guides.

This is also such an arbitrary rule though. Why spaces in lists surrounded by `()` and `[]` but not `{}`?

> [@lmshk](#):
>
> In some situations involving macros, Runic seems to change meaning. For example […]

Can you open an issue about this?

> [@lmshk](#):
>
> Another issue is related to linebreaks after `=`

And this too?

> [@lmshk](#):
>
> The only style choice I disagree with is that […]

The reason I dislike your preferred style there is that arguments and the function body have the same indent which can make it a bit difficult to separate them at times. And the closing `)` as the first characther look like it closes the function like a closing `}` in e.g. C. I like that everything between `function` and `end` are indented for this reason.

While this was already my preferred style it isn’t actually directly encoded in Runic but just follows naturally from the two indenting rules saying that i) everything between `function` and `end` have an increased indent level of 1, and ii) argument list to multiline function calls (`f(\nx\n)`) result in another increase of indent level.

In general Runic style isn’t “my” style so I have also had to accept certain formatting results as the come. Instead Runic implement a set of rules and then it applies them ruthlessly everywhere.

---

<div class="post-metadata">

**Author:** ![lmshk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmshk/32/29632_2.png) [@lmshk](https://discourse.julialang.org/u/lmshk)\
**Post date:** [August 7, 2024, 11:25am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/11 "2024-08-07T11:25:51Z")

</div>

Your package, your rules. 😉  
(It’s not a big issue for me, I could probably get used to it.)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 7, 2024, 11:46am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/12 "2024-08-07T11:46:17Z")

</div>

> [@fredrikekre](#):
>
> Runic has _no configuration_.

I don’t know much about Go, but I am not sure that this is an ideal fit for a language like Julia, which has a very rich syntax. There may not be a single ideal formatting, even for one person, as it depends on the context (how much one wants to save vertical space, etc).

Given all the effort you have invested into writing this package, I wonder how much extra it would take to parse various options from a TOML file, put them in a `struct`, and use that for emitting output. Cf [#12](https://github.com/fredrikekre/Runic.jl/issues/12), [#34](https://github.com/fredrikekre/Runic.jl/issues/34) (semicolons could be useful in code meant for interactive use), and various tiny issues you may encounter in the future for rare corner cases. Instead of having to think about a “right” choice, you can leave it open, and just have a default for the choice you consider most sensible.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [August 7, 2024, 12:18pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/13 "2024-08-07T12:18:33Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t know much about Go, but I am not sure that this is an ideal fit for a language like Julia, which has a very rich syntax. There may not be a single ideal formatting, even for one person, as it depends on the context (how much one wants to save vertical space, etc).

The point is that there is no ideal formatting, but that global consistency improves readability in new code bases! Any particular decision has tradeoffs in different contexts, but those tradeoffs are far out weighed just making a call and sticking with it.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [August 7, 2024, 12:39pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/14 "2024-08-07T12:39:05Z")

</div>

> [@mrufsvold](#):
>
> Any particular decision has tradeoffs in different contexts, but those tradeoffs are far out weighed just making a call and sticking with it.

I roughly agree that consistency in style is good, but IMO style is an aesthetic issue that would ideally be left to the programmer to decide upon on a case-by-case basis, just as programming itself is done.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 7, 2024, 12:47pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/15 "2024-08-07T12:47:32Z")

</div>

> [@mrufsvold](#):
>
> global consistency improves readability in new code bases

To a small extent, maybe. That said, I doubt that the very minor choices have a huge impact on readability. Eg I can read both

```julia
a = 1
ab = 2

```

and

```julia
a = 1
ab = 2

```

just fine. Personally I use the first, but if I am contributing to a codebase that uses the second, I try to do it like that.

It is my impression that the Julia community is much more _laissez-faire_ than Go with its single best way for everything. The Julian approach, IMO, is to go for Swiss army knives that include a chainsaw.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 7, 2024, 1:30pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/16 "2024-08-07T13:30:27Z")

</div>

I’m also in the “No way, I’m going to format my code the way I want to” camp. But carry on. 🙂

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [August 7, 2024, 1:40pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/17 "2024-08-07T13:40:16Z")

</div>

I imagine the use case is less for formatting your own code and more for formatting pull requests and collaborative code bases into consistency: an automatically enforced style guide.

> [@Tamas\_Papp](#):
>
> Personally I use the first, but if I am contributing to a codebase that uses the second, I try to do it like that.

Then you can write your code however you are used to and let the formatter adjust it later.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 7, 2024, 1:47pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/18 "2024-08-07T13:47:14Z")

</div>

> [@Nathan\_Boyer](#):
>
> I imagine the use case is less for formatting your own code and more for formatting pull requests and collaborative code bases into consistency: an automatically enforced style guide.

No doubt. But I still don’t like the idea of my formatting being changed. Luckily for me most of my coding is on individual projects, so I can follow my own style anyways.

---

<div class="post-metadata">

**Author:** ![brianguenter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brianguenter/32/29519_2.png) [@brianguenter](https://discourse.julialang.org/u/brianguenter)\
**Post date:** [August 7, 2024, 4:54pm UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/19 "2024-08-07T16:54:08Z")

</div>

The README only describes how to make Runic work with NeoVim. Does Runic also work with VSCode?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 8, 2024, 6:17am UTC](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898/20 "2024-08-08T06:17:59Z")

</div>

> [@Nathan\_Boyer](#):
>
> formatting pull requests and collaborative code bases into consistency

Yes, but this does not imply that _all_ such projects have the same formatting style down to the tiniest details. Configuration is still needed.

Sorry, I still do not understand why lack of configuration is a _feature_ for a task where reasonable people can have different preferences.

[Next page](https://discourse.julialang.org/t/runic-jl-a-code-formatter-with-rules-set-in-stone/117898.md?page=2)
