Skip to content

Commit 1a54c32

Browse files
authored
Support multidimensional arrays (#7)
1 parent 8440044 commit 1a54c32

File tree

5 files changed

+115
-21
lines changed

5 files changed

+115
-21
lines changed

README.md

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ julia> ]add UnicodeGraphics
1212
```
1313

1414
## Examples
15+
By default, `uprint` prints all values in an array that are true or greater than zero:
1516
```julia
1617
julia> pac = [
1718
0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0
@@ -56,7 +57,7 @@ julia> uprint(pac, :block)
5657
▀▀██████▀▀
5758
```
5859

59-
It is also possible to pass a filtering function, filling values for which the function returns `true`:
60+
It is also possible to pass a filtering function, filling values for which the function returns `true`, e.g. all even numbers in the following array:
6061
```julia
6162
julia> ghost = [
6263
1 7 7 7 7 8 6 4 6 3 9 9 9 7
@@ -80,13 +81,65 @@ julia> uprint(iseven, ghost)
8081
⣿⢿⣿⠿⣿⡿⣿
8182
⠁⠀⠉⠀⠉⠀⠈
8283
```
83-
`uprint` can be used to write into any `IO` stream, defaulting to `stdout`.
8484

85-
`ustring` can be used to return a string instead of printing to IO:
85+
Non-number type inputs are also supported,
86+
as long as the filtering function returns boolean values:
87+
88+
```julia-repl
89+
julia> A = rand("abc123", 4, 4)
90+
4×4 Matrix{Char}:
91+
'3' 'c' '3' '1'
92+
'a' 'c' '1' 'c'
93+
'1' '1' '2' 'a'
94+
'b' 'a' '2' 'a'
95+
96+
julia> uprint(isletter, A, :block)
97+
▄█ ▄
98+
▄▄ █
99+
```
100+
101+
Multidimensional arrays are also supported:
102+
```julia-repl
103+
julia> A = rand(Bool, 4, 4, 1, 2)
104+
4×4×1×2 Array{Bool, 4}:
105+
[:, :, 1, 1] =
106+
0 1 0 0
107+
1 0 1 0
108+
0 1 1 1
109+
0 0 1 1
110+
111+
[:, :, 1, 2] =
112+
1 1 0 0
113+
1 1 0 0
114+
0 0 1 0
115+
0 0 1 0
116+
117+
julia> uprint(A, :block)
118+
[:, :, 1, 1] =
119+
▄▀▄
120+
▀██
121+
122+
[:, :, 1, 2] =
123+
██
124+
125+
```
126+
127+
`uprint` can be used to write into any `IO` stream, defaulting to `stdout`.
86128
```julia-repl
87-
julia> ustring(iseven, ghost)
88-
"⢀⠴⣾⣿⠷⣦⡀\n⣴⠆⣸⣷⠆⣸⣧\n⣿⢿⣿⠿⣿⡿⣿\n⠁⠀⠉⠀⠉⠀⠈\n"
129+
julia> io = IOBuffer();
130+
131+
julia> uprint(io, pac)
89132
90-
julia> ustring(iseven, ghost, :block)
91-
" ▄▄████▄▄ \n ▄▀▀████▀▀██▄ \n ▄▄ ██▄▄ ██ \n██▀ ▄███▀ ▄███\n██████████████\n██▀███▀▀███▀██\n▀ ▀▀ ▀▀ ▀\n"
133+
julia> String(take!(io)) |> print
134+
⠀⣠⣴⣾⣿⣿⣷⣦⣄⠀
135+
⣰⣿⣿⣿⣧⣼⣿⡿⠟⠃
136+
⣿⣿⣿⣿⣿⣏⡁⠀⠀⠠
137+
⠹⣿⣿⣿⣿⣿⣿⣷⣦⡄
138+
⠀⠙⠻⢿⣿⣿⡿⠟⠋⠀
139+
```
140+
141+
To directly return a string instead of printing to IO, `ustring` can be used:
142+
```julia-repl
143+
julia> ustring(pac)
144+
"⠀⣠⣴⣾⣿⣿⣷⣦⣄⠀\n⣰⣿⣿⣿⣧⣼⣿⡿⠟⠃\n⣿⣿⣿⣿⣿⣏⡁⠀⠀⠠\n⠹⣿⣿⣿⣿⣿⣿⣷⣦⡄\n⠀⠙⠻⢿⣿⣿⡿⠟⠋⠀\n"
92145
```

src/UnicodeGraphics.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module UnicodeGraphics
55

66
const DEFAULT_METHOD = :braille
77
include("api.jl")
8+
include("ndarray.jl")
89
include("core.jl")
910
include("deprecate.jl")
1011

src/api.jl

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ julia> uprint(A, :block)
3030
▄▄▀▄▄█ ▀
3131
```
3232
"""
33-
uprint(A::AbstractMatrix, method::Symbol=DEFAULT_METHOD) = uprint(stdout, A, method)
34-
function uprint(io::IO, A::AbstractMatrix, method::Symbol=DEFAULT_METHOD)
33+
uprint(A::AbstractArray, method::Symbol=DEFAULT_METHOD) = uprint(stdout, A, method)
34+
function uprint(io::IO, A::AbstractArray, method::Symbol=DEFAULT_METHOD)
3535
return uprint(io, >(zero(eltype(A))), A, method)
3636
end
3737

@@ -67,18 +67,11 @@ julia> uprint(>(3), A, :block)
6767
██ ██▀█
6868
```
6969
"""
70-
function uprint(f::Function, A::AbstractMatrix, method::Symbol=DEFAULT_METHOD)
70+
function uprint(f::Function, A::AbstractArray, method::Symbol=DEFAULT_METHOD)
7171
return uprint(stdout, f, A, method)
7272
end
73-
function uprint(io::IO, f::Function, A::AbstractMatrix, method::Symbol=DEFAULT_METHOD)
74-
if method == :braille
75-
to_braille(io, f, A)
76-
elseif method == :block
77-
to_block(io, f, A)
78-
else
79-
throw(ArgumentError("Valid methods are :braille and :block, got :$method."))
80-
end
81-
return nothing
73+
function uprint(io::IO, f::Function, A::AbstractArray, method::Symbol=DEFAULT_METHOD)
74+
return _uprint_nd(io::IO, f::Function, A::AbstractArray, method::Symbol)
8275
end
8376

8477
"""
@@ -110,7 +103,7 @@ julia> ustring(A, :block)
110103
"█▀▀█▄█ \n█ ▄ █▄█▄\n ▄▄ ▄ ▀▄\n▄▄█▄ ▀██\n"
111104
```
112105
"""
113-
function ustring(A::AbstractMatrix, method::Symbol=DEFAULT_METHOD)
106+
function ustring(A::AbstractArray, method::Symbol=DEFAULT_METHOD)
114107
return ustring(>(zero(eltype(A))), A, method)
115108
end
116109

@@ -143,7 +136,7 @@ julia> ustring(>(3), A, :block)
143136
"██▀▀██ ▀\n▄██▄██ █\n▄██▄ ██\n█▀█▄▄▀██\n"
144137
```
145138
"""
146-
function ustring(f::Function, A::AbstractMatrix, method::Symbol=DEFAULT_METHOD)
139+
function ustring(f::Function, A::AbstractArray, method::Symbol=DEFAULT_METHOD)
147140
io = IOBuffer()
148141
uprint(io, f, A, method)
149142
return String(take!(io))

src/ndarray.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# For matrices, directly call core.jl method matching method Symbol.
2+
function _uprint_nd(io::IO, f::Function, A::AbstractMatrix, method::Symbol)
3+
if method == :braille
4+
to_braille(io, f, A)
5+
elseif method == :block
6+
to_block(io, f, A)
7+
else
8+
throw(ArgumentError("Valid methods are :braille and :block, got :$method."))
9+
end
10+
return nothing
11+
end
12+
# View vectors as 1xn adjoints
13+
function _uprint_nd(io::IO, f::Function, v::AbstractVector, method::Symbol)
14+
_uprint_nd(io, f, adjoint(v), method)
15+
return nothing
16+
end
17+
18+
# For multi-dimensional arrays, iterate over tail-indices
19+
function _uprint_nd(io::IO, f::Function, A::AbstractArray, method::Symbol)
20+
axs= axes(A)
21+
tailinds = Base.tail(Base.tail(axs))
22+
Is = CartesianIndices(tailinds)
23+
for I in Is
24+
idxs = I.I
25+
_show_nd_label(io, idxs)
26+
slice = view(A, axs[1], axs[2], idxs...) # matrix-shaped slice
27+
_uprint_nd(io, f, slice, method)
28+
print(io, idxs == map(last,tailinds) ? "" : "\n")
29+
end
30+
return nothing
31+
end
32+
# adapted from Base._show_nd_label
33+
function _show_nd_label(io::IO, idxs)
34+
print(io, "[:, :, ")
35+
for i = 1:length(idxs)-1
36+
print(io, idxs[i], ", ")
37+
end
38+
println(io, idxs[end], "] =")
39+
return nothing
40+
end

test/runtests.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ ghost2 = [
7777
@test_reference "references/braille_ghost.txt" @capture_out uprint(iseven, ghost2)
7878
@test_reference "references/block_ghost.txt" @capture_out uprint(iseven, ghost2, :block)
7979

80+
# Test vector and n-dimensional arrays
81+
v = [0, 1, 0, 1, 1, 0, 0, 1]
82+
@test ustring(v) == "⠈⠈⠁⠈\n"
83+
84+
A = reshape(v, 2, 2, 1, 1, 2)
85+
@test ustring(A) == "[:, :, 1, 1, 1] =\n\n\n[:, :, 1, 1, 2] =\n\n"
86+
8087
# Remove deprecations before next breaking release:
8188
@test_reference "references/braille_ghost.txt" (@test_deprecated brailize(ghost))
8289
@test_reference "references/block_ghost.txt" (@test_deprecated blockize(ghost))

0 commit comments

Comments
 (0)