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

Always treat multiline {|delimited strings|} as though they are long #2480

Merged
merged 2 commits into from
Nov 22, 2023

Conversation

dvulakh
Copy link
Contributor

@dvulakh dvulakh commented Nov 15, 2023

Currently, ocamlformat determines whether a delimited string is "long" enough to split a box across multiple lines simply by its length. However, a multiline string should always be treated as long enough to split a box, even if it doesn't have so many characters. This feature implements the desired behavior.

We implement the fix by exposing str_as in Fmt.mli so that we can use it to append short strings that get treated as very long after multiline strings.

@dvulakh dvulakh marked this pull request as ready for review November 15, 2023 17:30
@@ -1,4 +1,5 @@
let _ = {|
let _ =
{|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous output was expected. We call this "docking" in other contextes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll restrict the change to the janestreet profile, then. It is surprising to me, though, that the property used to determine whether to "dock" is the number of characters in the string and not something that more closely relates to how it "looks", like whether the first line is empty, the number of lines, or the length of the longest line.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also surprising to me. I tried various rules in #2448 without success, as the changes to existing code is always large and the rule is always arbitrary. Thanks for the ideas, I'll try to come back to this change later.

@@ -185,11 +185,13 @@ let this_function_has_a_long_name plus very many arguments =

[%%expect {||}] ;;

[%expect {|
[%expect
{|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with let, the previous output is expected.

spf
{|(with-accepted-exit-codes 1
(run %s))|}
cmd_string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This output can be achieved by tweaking fmt_args_grouped instead of adding breaks as experimented in #2448

lib/Fmt_ast.ml Outdated
(* If a multiline string has newlines in it, it should get treated as a
"long" box element. To do so, we append a length-1000 empty
string. *)
$ fmt_if_k (String.mem s '\n') (str_as 1000 "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's generally not a good idea to put a break at the end of a box as it interferes with the formatting of the containing expression:

let _ =
  {|
    foo
    bar
  |}
  ;
  ""

Instead, we write rules that can be followed when formatting the containing expression. For example, is_simple, break_between, and more defined in Ast. This is more or less done in fmt_args_grouped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out, I'll take a look at the PR you linked above and try to come up with a fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that, as far as I can tell, semicolons after multiline strings still format fine in the janestreet profile.

I have pushed a commit that restricts the new behavior to the janestreet profile, though.

after this commit, only the js_source.ml.* tests change as compared to
the trunk
Copy link
Collaborator

@Julow Julow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's merge :)

@@ -3154,7 +3154,8 @@ module FM_valid = F (struct
type t = int
end)

[%%expect {|
[%%expect
{|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docking behavior could be specially supported again if needed.

@Julow Julow merged commit 74215ea into ocaml-ppx:main Nov 22, 2023
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants