White space in AST and parenthesis removal

I did this in iex

    iex(1) x = quote do
    ...(1)> defmodule One do
    ...(1)>    def area({:square,x}) do
    ...(1)>      x*x
    ...(1)>    end
    ...(1)>    def area({:rectangle,x,y}) do
    ...(1)>      x*y
    ...(1)>    end
    ...(1)> end
    ...(1)> end
    {:defmodule, [context: Elixir, import: Kernel],
     [{:__aliases__, [alias: false], [:One]},
      [do: {:__block__, [],
        [{:def, [context: Elixir, import: Kernel],
          [{:area, [context: Elixir], [square: {:x, [], Elixir}]},
           [do: {:*, [context: Elixir, import: Kernel],
             [{:x, [], Elixir}, {:x, [], Elixir}]}]]},
         {:def, [context: Elixir, import: Kernel],
          [{:area, [context: Elixir],
            [{:{}, [], [:rectangle, {:x, [], Elixir}, {:y, [], Elixir}]}]},
           [do: {:*, [context: Elixir, import: Kernel],
             [{:x, [], Elixir}, {:y, [], Elixir}]}]]}]}]]}

But when I print it I see this

    iex(2)> x |> Macro.to_string |> IO.puts
    defmodule(One) do
      def(area({:square, x})) do
        x * x
      def(area({:rectangle, x, y})) do
        x * y

I’ve lost the white space between the definitions
and extra parentheses have been added around the def
so it prints def(area({:square,x}) do which is rather ugly
compared to def area({:square,x}) do

Is there any way of retaining the white space in the AST?
And is it easy to change the pretty printer to remove the additional



1 Like

As far as I can remember white space is already thrown away in the lexingphase.

But when you read code from a file or string into an ast, positional information is retained in the ast afaik. Maybe it is also used to reconstruct white space in the pretty printer?

I can’t test because I’m on my mobile…

Probably could I’d bet. It will not work in iex though but in a file it should (I doubt the current to_string uses it though). This would also require Elixir 1.6 as it added column information and some other metadata.

There is a fully featured code formatter being worked on here:


@josevalim talked about it at the recent ElixirConf, it’s scheduled to become part of the language in 1.6