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

Formatting for a Ruby-like language #1

Open
akimd opened this issue Oct 30, 2021 · 5 comments
Open

Formatting for a Ruby-like language #1

akimd opened this issue Oct 30, 2021 · 5 comments

Comments

@akimd
Copy link

akimd commented Oct 30, 2021

Hi,

I was about to implement Wadler's prettier printer, and I'm very happy to find that you already did that. Thanks for this.

I have a few questions:

  1. In a language such as Ruby where \n is meaningful, it's important to be able to emit a line break. I don't see how to do that with the current API. Am I missing something?

  2. Likewise, in Ruby in many places you can drop a separator when you are on a single line, or just do with a \n otherwise. For instance expressions in a block can be separated by ; , or \n (in which case the ; is useless). Or the then-part of an if can be on the same line with then, or simply separated with \n.
    I can't see a way to express that in the current api. I can see that this violates some invariants stated by Wadler ("As an invariant, we require in (x <|> y) that all layouts in x and y flatten to the same layout"), but I can't see how this invariant would break the correctness of the rendered layout. It does not break the second invariant, that appears to be more critical to get correct results ("we require that no first line of a document in x is shorter than some first line of a document in y; or, equivalently, that every first line in x is at least as long as every first line in y").

  3. What are the known uses of this library?

  4. I'd like to suggest to modify the documentation (I can provide a PR) which is misleading. It says in several places something like "By default, the class assumes that primitive elements are strings and each byte in the strings have single column in width". This is wrong: since the library uses str.length it does count the number of characters, not of bytes.

Cheers!

@akimd
Copy link
Author

akimd commented Oct 31, 2021

Wrt to Item 2, I have finally seen that breakable takes an optional argument. This is exactly what I was looking for!

@akimd
Copy link
Author

akimd commented Nov 3, 2021

Wrt to Item 1, I have been using with the following method (extracted from breakable), and it seems to do the job.

  def break
    flush
    @output << @newline
    @output << @genspace.call(@indent)
    @output_width = @indent
    @buffer_width = 0
  end

I can provide a PR if there is interest.

@stackmystack
Copy link

The fix PR :)

@akimd
Copy link
Author

akimd commented Dec 21, 2021

Wrt to Item 1, I have been using with the following method (extracted from breakable), and it seems to do the job.

  def break
    flush
    @output << @newline
    @output << @genspace.call(@indent)
    @output_width = @indent
    @buffer_width = 0
  end

This does not work well, it's broken. @stackmystack's solution, on the other hand, perfectly addressed my needs.

@kddnewton
Copy link

@akimd if you're interested, check out my recent PR: #3. It includes all of the necessary functionality behind https://github.com/ruby-syntax-tree/syntax_tree, which is a formatter for Ruby itself.

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

No branches or pull requests

3 participants