typelevel/paiges

Doc.lineOrSep?

DavidGregory084 opened this issue · 4 comments

I've been using this library to pretty print ASTs for a little toy programming language and it's great! Thanks for your work on this.

However, I was wondering if there is a way to use an optional separator character other than a single space when a doc is flattened.

e.g.

val imps = Doc.intercalate(Doc.char(';') + Doc.line, imports.map {
  case ImportModule(pkg, name) =>
    Doc.text("import ") + Doc.text((pkg :+ name).mkString("."))
  case ImportSymbols(pkg, name, syms) =>
    val impPrefix = Doc.text("import ") + Doc.text((pkg :+ name).mkString(".")) + Doc.char('.') + Doc.char('{')
    val impSuffix = Doc.char('}')
    val impBody = Doc.intercalate(Doc.comma + Doc.line, syms.map(Doc.text))
    impBody.bracketBy(impPrefix, impSuffix)
})

results in:

  import mpj6.{ dM };
  import oz4.nckur.ctsq.me5.lgG.cn;
  import kmF1.vu.ehy.yplf

I only really want the semicolon to be added when the Doc is flattened. Is there a good way to do that already that I have missed?

It's not possible on master at this time. However, we have some PRs in the works that would allow that. For example, #117's FlatAlt constructor is how the feature you are looking for is supported in the Haskell implementation. It's not actually exposed to callers in #117, but we could easily do so now that there's a feature request!

We don't expose it now because some data-structure invariants we maintain will be broken by arbitrary flattened-alternatives, but since it's used in other libraries, I would think it's definitely something we can support.

That'd be great, I'll keep an eye out for #117 landing in master 👍

Related to #76

What do you think of this comment:
#117 (comment)

Would you be sad to lose flatten in exchange for this feature?

I have not used flatten for anything yet so so far, no :)