ocamlformat icon indicating copy to clipboard operation
ocamlformat copied to clipboard

Feature request: trailing parentheses on new line

Open kwshi opened this issue 4 years ago • 1 comments

Is your feature request related to a problem? Please describe. Currently, multiline-parenthesized-expressions are formatted Lisp-style, with everything stacked together on a single line at the end of the expression:

let x =
  List.map (fun a ->
      a_pretty_long_function_application
        ( match a with
        | Ok some_name -> some_body
        | Error other_name -> other_body ))

Personally, I find Lisp-style parentheses extremely cumbersome and difficult to track/read after a while. Of course, this problem could be mitigated by having an IDE highlight matching parentheses, but reliance on external tools for readability seems like a second-class solution to a problem that could be solved by formatting.

I recognize that what I said above is a matter of preference, some may actually like Lisp parentheses and disagree with my assessment, so let me offer some objective considerations:

  • As tuple delimiters, Lisp-parentheses are inconsistent with the default behavior for other collections, e.g. records, lists:

    (* default profile: break-separators=after, dock-collection-brackets=true *)
    let long_list =
      [
        a very long tuple;
        a very long tuple;
        a very very very long tuple;
        with_many many items;
      ]
    
    let long_tuple =
      ( a very long tuple,
        a very long tuple,
        a very very very long tuple,
        with_many many items )
    
    (* break-separators=before, dock-collection-brackets=false *)
    let long_list =
      [ a very long tuple
      ; a very long tuple
      ; a very very very long tuple
      ; with_many many items
      ]
    
    let long_tuple =
      ( a very long tuple
      , a very long tuple
      , a very very very long tuple
      , with_many many items )
    

    (It's also worth observing, as an aside, that dock-collection-brackets have no effect on tuple parentheses, which always behave as though it were set to false. Perhaps that is also behavior worth considering changing?)

    The only way to make them consistent is via profile = compact (I'm not sure exactly which options set by that profile cause this behavior), which gives lists and records Lisp-style behavior too.

  • Per above, if profile = compact allows the setting of options that enable Lisp-spacing on records/lists (which is not the default), then for consistency's sake it seems parentheses should be configurable as well. And this can be done without necessarily adding extra options; simply adjust parentheses behavior to match that of list/record braces/brackets.

Describe the solution you'd like

Unify the behavior of brackets/braces and parentheses, so that dock-collection-brackets is not ignored by parentheses, and trailing-parentheses occur on a newline by default, same as brackets/braces.

let x =
  List.map (fun a ->
    a_pretty_long_function_application
      ( match a with
      | Ok some_name -> some_body
      | Error other_name -> other_body
      )
  )

kwshi avatar Dec 25 '20 04:12 kwshi

indicate-multiline-delimiters = closing-on-separate-line should give at least some of what you want. I use it in all of my projects. And ocamlformat 0.16.0 and newer have some big improvements related to closing delimited placement.

hcarty avatar Dec 27 '20 17:12 hcarty