Skip to content

Commit 6e54660

Browse files
authored
printing with styled/non-unit-textwidth-character contents (#443)
Previously, BlockArrays with elements that used styling would throw off the printing, because the textwidth computation didn't account for the fact that some contents might have a different `length` relative to how much space they take up when printed. This fixes that by using the `ANSIIterator` from Base, ala JuliaLang/julia#47430. Unfortunately, `ANSIIterator` isn't exported at the moment - but the alternative is to depend on StringManipulations.jl or copy over the Base implementation. I added a test that shows the problem. Previously, it displayed as: ![image](https://github.com/user-attachments/assets/722037b0-aeb1-4aca-b8aa-2c603290cf02) With this, it displays as: ![image](https://github.com/user-attachments/assets/a0d5098d-8d5a-4019-a733-2a1acbcdaa4a)
1 parent 4d386cf commit 6e54660

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function _blockarray_print_matrix_row(io::IO,
4848
print(io, l, prettysx, r)
4949

5050
# Jump forward
51-
n_chars += length(l) + length(prettysx) + length(r) + 2
51+
n_chars += length(l) + textwidth(Base.ANSIIterator(prettysx)) + length(r) + 2
5252

5353
cumul += 1
5454
if ndims(X) == 2

test/test_blocks.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,35 @@ using Test, BlockArrays
1717
@test blocks(mortar(matrix_blocks)) === matrix_blocks
1818
end
1919

20+
@testset "blocks::BlockMatrix{::MyString}" begin
21+
# test printing with ANSI escape sequences & textwidth(::Char) ≠ 1
22+
struct MyString
23+
s::String
24+
end
25+
function Base.show(io::IO, x::MyString)
26+
if all(isnumeric, x.s)
27+
printstyled(io, x.s; bold=true, color=:green)
28+
elseif all(isascii, x.s)
29+
printstyled(io, x.s, color=:red)
30+
print(io, " ascii!")
31+
else
32+
print(io, x.s)
33+
end
34+
end
35+
36+
B = BlockArray(undef_blocks, Matrix{MyString}, [1,2], [1,2])
37+
B[Block(1), Block(1)] = [MyString("abc");;]
38+
B[Block(1), Block(2)] = [MyString("123") MyString("γ");]
39+
B[Block(2), Block(1)] = [MyString("γ"); MyString("1");;]
40+
B[Block(2), Block(2)] = [MyString("⛵⛵⛵⛵⛵") MyString("x"); MyString("⛵⛵⛵") MyString("4")]
41+
42+
strip_ansi(s) = reduce(*, filter(c->!(c isa Base.ANSIDelimiter),
43+
map(last, Base.ANSIIterator(s))))
44+
reference_str = "2×2-blocked 3×3 BlockMatrix{$(@__MODULE__).MyString}:\n \e[31mabc\e[39m ascii! │ \e[32m\e[1m123\e[22m\e[39m γ \n ────────────┼──────────────────────\n γ │ ⛵⛵⛵⛵⛵ \e[31mx\e[39m ascii!\n \e[32m\e[1m1\e[22m\e[39m │ ⛵⛵⛵ \e[32m\e[1m4\e[22m\e[39m "
45+
@test strip_ansi(sprint(show, "text/plain", B; context=stdout)) == strip_ansi(reference_str)
46+
@test strip_ansi(sprint(show, "text/plain", B)) == strip_ansi(reference_str)
47+
end
48+
2049
@testset "blocks(::BlockedVector)" begin
2150
v0 = rand(3)
2251
vb = BlockedArray(v0, [1, 2])

0 commit comments

Comments
 (0)