reasonml / reason-tools

Adds Reason to the browser

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

refmt - use less stric behaviour towards empty-lines

feluxe opened this issue · comments

Hi there!

I just started with Reason React and it's a really nice experience so far!

But one thing keeps bothering me, which is refmt's behaviour towards empty-lines.

For example, if I put a react component into a module, refmt force-removes all new-lines, so that I end up with a large, dense, hard to read code block:

module Nice = {
  type dog = string;
  type state =
    | Loading
    | Error
    | Loaded(array(dog));
  type action =
    | DogsFetch
    | DogsFetched(array(dog))
    | DogsFailedToFetch;
  module Decode = {
    let dogs = json : array(dog) =>
      Json.Decode.(
        json |> field("message", array(string)) |> Array.map(_, dog => dog)
      );
  };
  let component = ReasonReact.reducerComponent("Nice");
  let fetchDogs = () =>
    ReasonReact.UpdateWithSideEffects(
      Loading,
      self =>
        Js.Promise.(
          Fetch.fetch("https://dog.ceo/api/breeds/list")
          |> then_(Fetch.Response.json)
          |> then_(json =>
               json
               |> Decode.dogs
               |> (dogs => self.send(DogsFetched(dogs)))
               |> resolve
             )
          |> catch(_err => Js.Promise.resolve(self.send(DogsFailedToFetch)))
          |> ignore
        ),
    );
  let make = _children => {
    ...component,
    initialState: _state => Loading,
    reducer: (action, _state) =>
      switch (action) {
      | DogsFetch => fetchDogs()
      | DogsFetched(dogs) => ReasonReact.Update(Loaded(dogs))
      | DogsFailedToFetch => ReasonReact.Update(Error)
      },
    didMount: self => {
      self.send(DogsFetch);
      ReasonReact.NoUpdate;
    },
    render: self =>
      switch (self.state) {
      | Error =>
        <div> (ReasonReact.stringToElement("An error occurred!")) </div>
      | Loading => <div> (ReasonReact.stringToElement("Loading...")) </div>
      | Loaded(dogs) =>
        <div>
          <h1> (ReasonReact.stringToElement("Dogs")) </h1>
          <p> (ReasonReact.stringToElement("Source: ")) </p>
          <a href="https://dog.ceo">
            (ReasonReact.stringToElement("https://dog.ceo"))
          </a>
          <ul>
            (
              Array.map(dogs, dog =>
                <li key=dog> (ReasonReact.stringToElement(dog)) </li>
              )
              |> ReasonReact.arrayToElement
            )
          </ul>
        </div>
      },
  };
};

The same code with empty-lines:

module Nice = {

  type dog = string;

  type state =
    | Loading
    | Error
    | Loaded(array(dog));

  type action =
    | DogsFetch
    | DogsFetched(array(dog))
    | DogsFailedToFetch;

  module Decode = {
    let dogs = json : array(dog) =>
      Json.Decode.(
        json |> field("message", array(string)) |> Array.map(_, dog => dog)
      );
  };

  let component = ReasonReact.reducerComponent("Nice");

  let fetchDogs = () =>
    ReasonReact.UpdateWithSideEffects(
      Loading,
      self =>
        Js.Promise.(
          Fetch.fetch("https://dog.ceo/api/breeds/list")
          |> then_(Fetch.Response.json)
          |> then_(json =>
               json
               |> Decode.dogs
               |> (dogs => self.send(DogsFetched(dogs)))
               |> resolve
             )
          |> catch(_err => Js.Promise.resolve(self.send(DogsFailedToFetch)))
          |> ignore
        ),
    );

  let make = _children => {
    ...component,

    initialState: _state => Loading,

    reducer: (action, _state) =>
      switch (action) {
      | DogsFetch => fetchDogs()
      | DogsFetched(dogs) => ReasonReact.Update(Loaded(dogs))
      | DogsFailedToFetch => ReasonReact.Update(Error)
      },

    didMount: self => {
      self.send(DogsFetch);
      ReasonReact.NoUpdate;
    },

    render: self =>
      switch (self.state) {
      | Error =>
        <div> (ReasonReact.stringToElement("An error occurred!")) </div>
      | Loading => <div> (ReasonReact.stringToElement("Loading...")) </div>
      | Loaded(dogs) =>
        <div>
          <h1> (ReasonReact.stringToElement("Dogs")) </h1>
          <p> (ReasonReact.stringToElement("Source: ")) </p>
          <a href="https://dog.ceo">
            (ReasonReact.stringToElement("https://dog.ceo"))
          </a>
          <ul>
            (
              Array.map(dogs, dog =>
                <li key=dog> (ReasonReact.stringToElement(dog)) </li>
              )
              |> ReasonReact.arrayToElement
            )
          </ul>
        </div>
      },
  };
};

In this regard I really like the default behaviour of yapf (a popular Python code formatter). In general yapf simply allows you to add a single empty-line wherever you like, but it would reduce two and more empty-lines to one. This works really well.

Any love for this?

If I'm missing something, please excuse me for bothering!

This was fixed in Reason's master branch a little while ago with the merge of reasonml/reason#1873.

Neat! Thanks for the info!

Any ideas for a workaround until the next version gets released?

I guess this can be closed 🤔