Skip to content

Commit

Permalink
Account for unicode characters of width 2
Browse files Browse the repository at this point in the history
According to alacritty/alacritty#265 (comment) , unicode in monospace can only have width 0, 1, or 2, so, just accounting for width 2 (in addition to what we already do) should be enough.
  • Loading branch information
aaruni96 committed Feb 8, 2024
1 parent ac382ea commit c0e77bb
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 11 deletions.
83 changes: 72 additions & 11 deletions src/PrettyPrinting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1597,22 +1597,83 @@ function _write_line(io::IOCustom, str::AbstractString)
firstiter = Base.Iterators.take(_graphemes, firstlen)
restiter = Base.Iterators.drop(_graphemes, firstlen)
firststr = join(firstiter)
if io.lowercasefirst
written += write(io.io, lowercasefirst(firststr))
io.lowercasefirst = false
if length(firstiter) == textwidth(firststr)
if io.lowercasefirst
written += write(io.io, lowercasefirst(firststr))
io.lowercasefirst = false
else
written += write(io.io, firststr)
io.lowercasefirst = false
end
io.printed += textwidth(firststr)
else
written += write(io.io, firststr)
io.lowercasefirst = false
#firstline is wider than number of graphemes
partcollect = collect(firstiter)
printstr = ""
j = 1
while textwidth(printstr) < (c - ind > 0 ? c - ind : c)
printstr *= partcollect[j]
j += 1
if j > length(partcollect)
break
end
end
if io.lowercasefirst
written += write(io.io, lowercasefirst(printstr))
else
written += write(io.io, printstr)
end
io.printed += textwidth(printstr)

#the spillover string
written += write(io.io, "\n")
written += write_indent(io)
printstr = join(collect(firstiter)[j:end])
if io.lowercasefirst
written += write(io.io, lowercasefirst(printstr))
io.lowercasefirst = false
else
written += write(io.io, printstr)
io.lowercasefirst = false
end
io.printed += textwidth(printstr)
end
io.printed += textwidth(firststr)
it = Iterators.partition(1:length(restiter), c - ind > 0 ? c - ind : c)
for i in it
# partitions of the spillover text
written += write(io.io, "\n")
written += write_indent(io)
written += write(io.io, join(collect(restiter)[i]))
io.printed = textwidth(join(collect(restiter)[i]))
println()
partcollect = collect(restiter)[i]
partstr = join(collect(restiter)[i])
if (textwidth(partstr) < (c - ind > 0 ? c - ind : c)) || length(i) == textwidth(partstr)
written += write(io.io, "\n")
written += write_indent(io)
written += write(io.io, partstr)
io.printed = textwidth(partstr)
println()
else
# width is more than the number of graphemes
# we can only ever get double length lines (assuming non standard width can only be 2...)
# bad assumption to make ?
printstr = ""
j = 1
while textwidth(printstr) < (c - ind > 0 ? c - ind : c)
printstr *= partcollect[j]
j += 1
if j > length(partcollect)
break
end
end
written += write(io.io, "\n")
written += write_indent(io)
written += write(io.io, printstr)
io.printed = textwidth(printstr)
println()

Check warning on line 1669 in src/PrettyPrinting.jl

View check run for this annotation

Codecov / codecov/patch

src/PrettyPrinting.jl#L1665-L1669

Added lines #L1665 - L1669 were not covered by tests
printstr = join(partcollect[j+1:end])
written += write(io.io, "\n")
written += write_indent(io)
written += write(io.io, printstr)
io.printed = textwidth(printstr)

Check warning on line 1674 in src/PrettyPrinting.jl

View check run for this annotation

Codecov / codecov/patch

src/PrettyPrinting.jl#L1671-L1674

Added lines #L1671 - L1674 were not covered by tests
println()
end
end
return written
end
Expand Down
61 changes: 61 additions & 0 deletions test/PrettyPrinting-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,67 @@ let
" " * evil_a^(c-4) * "\n" *
" " * evil_a^4

# Test graphemes with non standard width
io = IOBuffer()
io = AbstractAlgebra.pretty(io, force_newlines = true)
_, c = displaysize(io)
boat = String([0xe2, 0x9b, 0xb5])
family = String([0xf0, 0x9f, 0x91, 0xaa])
print(io, AbstractAlgebra.Indent())
println(io, (boat * family)^40)
print(io, (boat * family)^40)
@test String(take!(io)) == " " * (boat*family)^19 * boat * "\n" *
" " * (family*boat)^19 * family * "\n" *
" " * boat * family * "\n" *
" " * (boat*family)^19 * boat * "\n" *
" " * (family*boat)^19 * family * "\n" *
" " * boat * family

# Test graphemes with standard and non standard width mixed in
io = IOBuffer()
io = AbstractAlgebra.pretty(io, force_newlines = true)
_, c = displaysize(io)
ellipses = String([0xe2, 0x80, 0xa6])
wedge = String([0xe2, 0x88, 0xa7])
iacute = String([0xc3, 0xad])
evil_a = String([0x61, 0xcc, 0x81, 0xcc, 0xa7, 0xcc, 0xa7])
wide_boat = String([0xe2, 0x9b, 0xb5])
family = String([0xf0, 0x9f, 0x91, 0xaa])
print(io, AbstractAlgebra.Indent())
println(io, "Ŏ"^c)
println(io, ellipses^c)
println(io, "aa", "Ś"^c)
println(io, wide_boat^80)
println(io, "bb", wedge^c)
print(io, AbstractAlgebra.Indent())
println(io, "aa", "Ŗ"^c)
println(io, family^c)
println(io, iacute^c)
println(io, evil_a^c)
print(io, evil_a^c)
@test String(take!(io)) == " " * "Ŏ"^(c-2) * "\n" *
" ŎŎ" * "\n" *
" " * ellipses^(c-2) * "\n" *
" " * ellipses^2 * "\n" *
" aa" * "Ś"^(c-4) * "\n" *
" ŚŚŚŚ" * "\n" *
" " * boat^39 * "\n" *
" " * boat^39 * "\n" *
" " * boat^2 * "\n" *
" bb" * wedge^(c-4) * "\n" *
" " * wedge^4 * "\n" *
" aa" * "Ŗ"^(c-6) * "\n" *
" ŖŖŖŖŖŖ" * "\n" *
" " * family^38 * "\n" *
" " * family^38 * "\n" *
" " * family^4 * "\n" *
" " * iacute^(c-4) * "\n" *
" " * iacute^4 *"\n" *
" " * evil_a^(c-4) * "\n" *
" " * evil_a^(4) * "\n" *
" " * evil_a^(c-4) * "\n" *
" " * evil_a^4

# Test too much indentation
io = IOBuffer()
io = AbstractAlgebra.pretty(io, force_newlines = true)
Expand Down

0 comments on commit c0e77bb

Please sign in to comment.