ocamlformat icon indicating copy to clipboard operation
ocamlformat copied to clipboard

Feature request: more consistent formatting of extension nodes containing lambdas

Open craigfe opened this issue 2 years ago • 0 comments

Is your feature request related to a problem? Please describe.

On ocamlformat.0.19.0, with the conventional profile, the formatting of AST nodes of the form [%ext ...]; ... is oddly context-sensitive. For instance, the following example works well:

let _ =
  [%ext 1];
  [%ext 2];
  [%ext 3];
  ()

but changing 1 to a lambda causes the sequence to be formatted all on one line:

let _ = [%ext fun () -> 1] ; [%ext 2] ; [%ext 3] ; ()

Both the single-line sequence and the spaces before ; look odd to me, as AFAIK this isn't otherwise achievable with profile=conventional. Interestingly, this doesn't happen if 2 is changed to a lambda instead:

let _ =
  [%ext 1];
  [%ext fun () -> 2];
  [%ext 3];
  ()

Multi-line lambdas If the lambda takes multiple lines, the parameters are docked, but the ; is bumped onto its own line (and all subsequent ;s in the sequence still have spaces added before them):

let _ =
  [%ext fun () ->
    let () = () in
    1]
  ;
  2 ;
  3 ;
  ()

However, this docking behaviour doesn't happen for subsequent lambdas in the chain:

let _ =
  [%ext fun () ->
    let () = () in
    1]
  ;
  [%ext
    fun () ->
      let () = () in
      2] ;
  3 ;
  ()

It also doesn't happen if the extension node is not within a sequence:

let _ =
  [%ext
    fun () ->
      let () = () in
      1]

Describe the solution you'd like

I like that multi-line lambdas have their arguments docked, and so propose keeping that behaviour but applying it more consistently. I also think that the breaking of sequences onto multiple lines shouldn't depend on whether the first expression is an extension node. I think approach would lead to the following changed outputs:

let _ =
  [%ext fun () -> 1];
  [%ext 2];
  [%ext 3];
  ()

let _ =
  [%ext fun () ->
    let () = () in
    1];
  2;
  3;
  ()

let _ =
  [%ext fun () ->
    let () = () in
    1];
  [%ext fun () ->
    let () = () in
    2];
  3;
  ()

let _ =
  [%ext fun () ->
    let () = () in
    1]

Thanks!

craigfe avatar Sep 21 '21 12:09 craigfe