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

add Doc.textWithLine for controlling how lines are parsed #664

Merged
merged 3 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions core/src/main/scala/org/typelevel/paiges/Doc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -863,11 +863,11 @@ object Doc {
/**
* Convert a string to text.
*
* This method translates newlines into an appropriate document
* representation. The result may be much more complex than a single
* `Text(_)` node.
* This method translates newlines into the given
* Doc, which should represent a new line and may be
* Doc.line, Doc.hardLine, Doc.lineOrSpace
*/
def text(str: String): Doc = {
def textWithLine(str: String, line: Doc): Doc = {
def tx(i: Int, j: Int): Doc =
if (i == j) Empty else Text(str.substring(i, j))

Expand All @@ -881,16 +881,25 @@ object Doc {
case _ => parse(i - 1, limit, doc)
}

if (str == "") Empty
else if (str.length == 1) {
val len = str.length

if (len == 0) Empty
else if (len == 1) {
val c = str.charAt(0)
if ((' ' <= c) && (c <= '~')) charTable(c.toInt - 32)
else if (c == '\n') line
else Text(str)
} else if (str.indexOf('\n') < 0) Text(str)
else parse(str.length - 1, str.length, Empty)
else parse(len - 1, len, Empty)
}

/**
* Convert a string to text.
*
* This method translates newlines into Doc.line (which can be flattened).
*/
def text(str: String): Doc = textWithLine(str, line)

/**
* Convert an arbitrary value to a Doc, using `toString`.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,4 +558,42 @@ class PaigesScalacheckTest extends OurFunSuite {
test("Doc.defer(x).representation(true) = x.representation(true)") {
forAll((x: Doc) => assertEq(Doc.defer(x).representation(true), x.representation(true)))
}

test("textWithLine with hardLine has lines <= textWithLine") {
forAll { (str: String, i0: Int) =>
// make a number between 0 and 199
val width = (i0 & 0x7fffffff) % 200
val str0 = Doc.text(str).flatten
val str1 = Doc.textWithLine(str, Doc.line).flatten
val str2 = Doc.textWithLine(str, Doc.hardLine).flatten

val r1 = str0.render(width)
val r2 = str1.render(width)
val r3 = str2.render(width)
assert(r1 == r2)

def maxLineLen(str: String): Int =
str.split("\n").foldLeft(0)((acc, line) => math.max(acc, line.length))

// hard lines can't be combined
assert(maxLineLen(r1) >= maxLineLen(r3))
}
}

test("textWithLine is different from text when there is a line and we render wide") {
forAll { (str: String) =>
val hasLine = str.exists(_ == '\n')

val tStr = Doc.text(str).flatten.renderWideStream.mkString
val hlStr = Doc.textWithLine(str, Doc.hardLine).flatten.renderWideStream.mkString

assert(hasLine == (tStr != hlStr))
}
}

test("Doc.textWithLine(\"\\n\", d) eq d") {
forAll { (doc: Doc) =>
assert(Doc.textWithLine("\n", doc) eq doc)
}
}
}
Loading