Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve more newlines #449

Closed
nojaf opened this issue Jul 12, 2019 · 9 comments
Closed

Preserve more newlines #449

nojaf opened this issue Jul 12, 2019 · 9 comments

Comments

@nojaf
Copy link
Contributor

nojaf commented Jul 12, 2019

In light of recent improvements by the Trivia PR (#434) we would like to discuss the addition of a new setting.

With this setting, we could preserve newlines that were found in the source after certain tokens.
Example:

let add a b =
    a + b

This sample would now be formatted on one line as it is very short.
If personal preference allows it, we could keep the newline after the = sign.

A similar thing could be done with chained function calls.

let config =
    Builder()
      .A()
      .B()
      .C()

Fantomas would format this one line because it is short.
With this new setting, we could detect that if a line begins with ., we keep the newline.

By default, we would set this setting to false.

Thoughts and opinions?

//cc @jindraivanek @auduchinok

@auduchinok
Copy link
Contributor

auduchinok commented Jul 13, 2019

I'm very much in favor of having such an option and most probably we'd enable it by default in Rider to work similarly to other languages in the platform.

An exception where I'd expect these newlines not to be preserved is when the line doesn't fit to desired width.

@nojaf
Copy link
Contributor Author

nojaf commented Jul 15, 2019

Another example I can come up with is pattern matching:

match meh with
| Foo -> 
  printfn "foo"
| Bar ->
  printfn "bar"

We could detect that nothing (or all spaces) follow after the -> sign. Meaning we should add a newline after the pattern.

nojaf added a commit that referenced this issue Aug 9, 2019
@resolritter
Copy link

resolritter commented Sep 1, 2019

When I'm writing something, I always do line-breaking regardless, be it after = or ->. That's because I'm still figuring out what I exactly want to do and I want to keep typing forward without causing syntactical problems.

On the contrary: imagine another mindset of, as I'm typing something, I need to constantly keep thinking about whether I should've added a newline or not way back there; that's just interrupting my train of thought to care about formatting, something Fantomas should care about for me.

I'm also afraid that such option would make the code look inconsistent after refactoring. A case where you refactor a large function with a lot of code:

let bigFunction myArgument =
    let myVariable =
        myArgument
        |> function1
        |> function2
        |> function3
     ...
     ...

But later you break this big function into two separate functions and its body becomes small

let bigFunction =
     bigpStep1 >> bigStep2

Now you have a "lingering" newline there that's probably unintended, as trivia would normally format everything in a single line. I guess it also opens up the question of whether composition/piping operators should always split everything vertically, because I'm noticing it only splits up the body if there are three of more functions being chained in a row.

@resolritter
Copy link

resolritter commented Sep 1, 2019

Another example I can come up with is pattern matching:

match meh with
| Foo -> 
  printfn "foo"
| Bar ->
  printfn "bar"

We could detect that nothing (or all spaces) follow after the -> sign. Meaning we should add a newline after the pattern.

Now, about match my opinion is different. I think code looks disconcerting when it's like this:

One of the branches is small, so only THAT ONE branch is kept inline

If one of the branches need to go to the next line, then every single branch should follow suit and go under also, but maybe that's a different setting or something.

@nojaf
Copy link
Contributor Author

nojaf commented Nov 18, 2019

I would also like to preserve newlines before |>.
Consider the following code:

    let watchFiles =
        async {
            printfn "after start"
            use _ =
                !!(serverPath </> "*.fs") ++ (serverPath </> "*.fsproj") // combines fs and fsproj
                |> ChangeWatcher.run (fun changes ->  
                                      printfn
                                          "FILE CHANGE %A"
                                          changes
                                      // stopFunc()
                                      //Async.Start (startFunc())
                                      )
            ()
        }

When this is formatted it will look something like:

let watchFiles =
    async {
        printfn "after start"
        use _ =
            !!(serverPath </> "*.fs") ++ (serverPath </> "*.fsproj") |> ChangeWatcher.run (fun changes ->  // combines fs and fsproj
                                                                                                      printfn
                                                                                                          "FILE CHANGE %A"
                                                                                                          changes
                                                                                                      // stopFunc()
                                                                                                      //Async.Start (startFunc())
                                                                                                      )
        ()
    }

If #559 was not a problem I would have a workaround for this so it is not a big must to have this.
@jindraivanek what do you think? Does it make sense to you to also include |> as scenario for KeepNewline?

@nojaf
Copy link
Contributor Author

nojaf commented Jul 9, 2020

The KeepNewline setting will be removed in v4.

@nojaf nojaf closed this as completed Jul 9, 2020
@reijerh
Copy link
Contributor

reijerh commented Dec 14, 2021

@nojaf I think I'm running into a situation where this feature would come in handy: example in online tool

Perhaps I'm just missing some obvious setting, but it's the first thing I ran into when trying to use Elmish.WPF in Rider.

// Can't figure out how to have nice lists AND nice piping at the same time
// If I set 'MaxInfixOperatorExpression' to a high value I have nice lists, but the piped calls are moved to one line
//
// Options I can think of:
// 1. Respect newlines for infix expressions
// 2. Have special treatment for pipeline operators

// Contrived
let baz () = [
    foobar "asdsadsadasdsdsadasdasdasdasdasdsaadsaasdasdasdsadsadsadsadsadasdsa"
    "asdsadsadasdsdsadasdasdasdasdasdsaadsaasdasdasdsadsadsadsadsadasdsa" |> foobar
    "2"
    foobar "4"
    "asdsads" |> foobar
    "5"
]

// Real-world
let bindings () = [
    "CounterValue" |> Binding.oneWay (fun m -> m.Count)
    "Decrement" |> Binding.cmd (fun m -> Decrement)
    // Unusual, but shows the difference
    Binding.cmd (fun m -> Increment) "asdsadsadasdsdsadasdasdasdasdasdsaadsaasdasdasdsadsadsadsadsadasdsa"
    "StepSize" |> Binding.twoWay ((fun m -> float m.StepSize), (fun newVal m -> int newVal |> SetStepSize)) 
]

let foobar =
    [ 1; 2 ]
    |> List.map (fun x -> x + 1)
    |> List.map (fun x -> x + 2)
    |> ignore

@nojaf
Copy link
Contributor Author

nojaf commented Dec 14, 2021

Hello, this feature was removed for good reason.
Are your examples in the same file? Perhaps you could tweak some values for a specific file.

@reijerh
Copy link
Contributor

reijerh commented Dec 14, 2021

Yeah, I mean this is just the basic Elmish sample app, but I suppose it happens anytime you have a longish pipeline expression and a list with a pipeline expression in the same file.

Per-file style configuration doesn't seem really viable to me in the long term for larger (team) projects, but I'll look into it, thanks.

I guess it's just an odd experience that newlines aren't preserved coming from e.g. R#.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants