Skip to content

Commit 4706184

Browse files
committed
reimplement show context global/tls variables as local state contained in a new IOContext lightweight wrapper type
1 parent 1fe1391 commit 4706184

23 files changed

Lines changed: 344 additions & 282 deletions

base/Enums.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,12 @@ macro enum(T,syms...)
9393
end
9494
end
9595
function Base.show(io::IO,x::$(esc(typename)))
96-
print(io, x, "::", $(esc(typename)), " = ", Int(x))
96+
if Base.limit_output(io)
97+
print(io, x)
98+
else
99+
print(io, x, "::", $(esc(typename)), " = ", Int(x))
100+
end
97101
end
98-
Base.showcompact(io::IO,x::$(esc(typename))) = print(io, x)
99102
function Base.writemime(io::IO,::MIME"text/plain",::Type{$(esc(typename))})
100103
print(io, "Enum ", $(esc(typename)), ":")
101104
for (sym, i) in $vals

base/complex.jl

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,24 @@ complex(x::Real, y::Real) = Complex(x, y)
5959
complex(x::Real) = Complex(x)
6060
complex(z::Complex) = z
6161

62-
function complex_show(io::IO, z::Complex, compact::Bool)
62+
function show(io::IO, z::Complex)
6363
r, i = reim(z)
64-
compact ? showcompact(io,r) : show(io,r)
64+
compact = limit_output(io)
65+
showcompact_lim(io, r)
6566
if signbit(i) && !isnan(i)
6667
i = -i
6768
print(io, compact ? "-" : " - ")
6869
else
6970
print(io, compact ? "+" : " + ")
7071
end
71-
compact ? showcompact(io, i) : show(io, i)
72+
showcompact_lim(io, i)
7273
if !(isa(i,Integer) && !isa(i,Bool) || isa(i,AbstractFloat) && isfinite(i))
7374
print(io, "*")
7475
end
7576
print(io, "im")
7677
end
77-
complex_show(io::IO, z::Complex{Bool}, compact::Bool) =
78+
show(io::IO, z::Complex{Bool}) =
7879
print(io, z == im ? "im" : "Complex($(z.re),$(z.im))")
79-
show(io::IO, z::Complex) = complex_show(io, z, false)
80-
showcompact(io::IO, z::Complex) = complex_show(io, z, true)
8180

8281
function read{T<:Real}(s::IO, ::Type{Complex{T}})
8382
r = read(s,T)

base/dict.jl

Lines changed: 66 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -61,87 +61,79 @@ function _truncate_at_width_or_chars(str, width, chars="", truncmark="…")
6161
end
6262

6363
showdict(t::Associative; kw...) = showdict(STDOUT, t; kw...)
64-
function showdict{K,V}(io::IO, t::Associative{K,V}; limit::Bool = false, compact = false,
64+
function showdict{K,V}(io::IO, t::Associative{K,V}; compact = false,
6565
sz=(s = tty_size(); (s[1]-3, s[2])))
66-
shown_set = get(task_local_storage(), :SHOWNSET, nothing)
67-
if shown_set === nothing
68-
shown_set = ObjectIdDict()
69-
task_local_storage(:SHOWNSET, shown_set)
70-
end
71-
t in keys(shown_set) && (print(io, "#= circular reference =#"); return)
72-
73-
try
74-
shown_set[t] = true
75-
if compact
76-
# show in a Julia-syntax-like form: Dict(k=>v, ...)
77-
if isempty(t)
78-
print(io, typeof(t), "()")
66+
(:SHOWN_SET => t) in io && (print(io, "#= circular reference =#"); return)
67+
68+
recur_io = IOContext(io, :SHOWN_SET => t)
69+
limit::Bool = limit_output(io)
70+
if compact
71+
# show in a Julia-syntax-like form: Dict(k=>v, ...)
72+
if isempty(t)
73+
print(io, typeof(t), "()")
74+
else
75+
if isleaftype(K) && isleaftype(V)
76+
print(io, typeof(t).name)
7977
else
80-
if isleaftype(K) && isleaftype(V)
81-
print(io, typeof(t).name)
82-
else
83-
print(io, typeof(t))
84-
end
85-
print(io, '(')
86-
first = true
87-
n = 0
88-
for (k, v) in t
89-
first || print(io, ',')
90-
first = false
91-
show(io, k)
92-
print(io, "=>")
93-
show(io, v)
94-
n+=1
95-
limit && n >= 10 && (print(io, ""); break)
96-
end
97-
print(io, ')')
78+
print(io, typeof(t))
79+
end
80+
print(io, '(')
81+
first = true
82+
n = 0
83+
for (k, v) in t
84+
first || print(io, ',')
85+
first = false
86+
show(recur_io, k)
87+
print(io, "=>")
88+
show(recur_io, v)
89+
n+=1
90+
limit && n >= 10 && (print(io, ""); break)
9891
end
99-
return
92+
print(io, ')')
10093
end
94+
return
95+
end
10196

102-
# Otherwise show more descriptively, with one line per key/value pair
103-
rows, cols = sz
104-
print(io, summary(t))
105-
isempty(t) && return
106-
print(io, ":")
107-
if limit
108-
rows < 2 && (print(io, ""); return)
109-
cols < 12 && (cols = 12) # Minimum widths of 2 for key, 4 for value
110-
cols -= 6 # Subtract the widths of prefix " " separator " => "
111-
rows -= 2 # Subtract the summary and final ⋮ continuation lines
112-
113-
# determine max key width to align the output, caching the strings
114-
ks = Array(AbstractString, min(rows, length(t)))
115-
keylen = 0
116-
for (i, k) in enumerate(keys(t))
117-
i > rows && break
118-
ks[i] = sprint(show, k)
119-
keylen = clamp(length(ks[i]), keylen, div(cols, 3))
120-
end
97+
# Otherwise show more descriptively, with one line per key/value pair
98+
rows, cols = sz
99+
print(io, summary(t))
100+
isempty(t) && return
101+
print(io, ":")
102+
if limit
103+
rows < 2 && (print(io, ""); return)
104+
cols < 12 && (cols = 12) # Minimum widths of 2 for key, 4 for value
105+
cols -= 6 # Subtract the widths of prefix " " separator " => "
106+
rows -= 2 # Subtract the summary and final ⋮ continuation lines
107+
108+
# determine max key width to align the output, caching the strings
109+
ks = Array(AbstractString, min(rows, length(t)))
110+
keylen = 0
111+
for (i, k) in enumerate(keys(t))
112+
i > rows && break
113+
ks[i] = sprint(0, show, k, env=recur_io)
114+
keylen = clamp(length(ks[i]), keylen, div(cols, 3))
121115
end
116+
end
122117

123-
for (i, (k, v)) in enumerate(t)
124-
print(io, "\n ")
125-
limit && i > rows && (print(io, rpad("", keylen), " => ⋮"); break)
118+
for (i, (k, v)) in enumerate(t)
119+
print(io, "\n ")
120+
limit && i > rows && (print(io, rpad("", keylen), " => ⋮"); break)
126121

127-
if limit
128-
key = rpad(_truncate_at_width_or_chars(ks[i], keylen, "\r\n"), keylen)
129-
else
130-
key = sprint(show, k)
131-
end
132-
print(io, key)
133-
print(io, " => ")
122+
if limit
123+
key = rpad(_truncate_at_width_or_chars(ks[i], keylen, "\r\n"), keylen)
124+
else
125+
key = sprint(0, show, k, env=recur_io)
126+
end
127+
print(recur_io, key)
128+
print(io, " => ")
134129

135-
if limit
136-
val = with_output_limit(()->sprint(show, v))
137-
val = _truncate_at_width_or_chars(val, cols - keylen, "\r\n")
138-
print(io, val)
139-
else
140-
show(io, v)
141-
end
130+
if limit
131+
val = sprint(0, show, v, env=recur_io)
132+
val = _truncate_at_width_or_chars(val, cols - keylen, "\r\n")
133+
print(io, val)
134+
else
135+
show(recur_io, v)
142136
end
143-
finally
144-
delete!(shown_set, t)
145137
end
146138
end
147139

@@ -158,8 +150,9 @@ summary{T<:Union{KeyIterator,ValueIterator}}(iter::T) =
158150
show(io::IO, iter::Union{KeyIterator,ValueIterator}) = show(io, collect(iter))
159151

160152
showkv(iter::Union{KeyIterator,ValueIterator}; kw...) = showkv(STDOUT, iter; kw...)
161-
function showkv{T<:Union{KeyIterator,ValueIterator}}(io::IO, iter::T; limit::Bool = false,
153+
function showkv{T<:Union{KeyIterator,ValueIterator}}(io::IO, iter::T;
162154
sz=(s = tty_size(); (s[1]-3, s[2])))
155+
limit::Bool = limit_output(io)
163156
rows, cols = sz
164157
print(io, summary(iter))
165158
isempty(iter) && return
@@ -176,7 +169,7 @@ function showkv{T<:Union{KeyIterator,ValueIterator}}(io::IO, iter::T; limit::Boo
176169
limit && i >= rows && (print(io, ""); break)
177170

178171
if limit
179-
str = with_output_limit(()->sprint(show, v))
172+
str = sprint(0, show, v, env=io)
180173
str = _truncate_at_width_or_chars(str, cols, "\r\n")
181174
print(io, str)
182175
else

base/docs/helpdb/Base.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3043,9 +3043,10 @@ Show an expression and result, returning the result.
30433043
"""
30443044
showcompact(x)
30453045
3046+
30463047
Show a more compact representation of a value. This is used for printing array elements. If
3047-
a new type has a different compact representation, it should overload `showcompact(io, x)`
3048-
where the first argument is a stream.
3048+
a new type has a different compact representation,
3049+
it should test `Base.limit_output(io)` in its normal `show` method.
30493050
"""
30503051
showcompact
30513052

base/grisu.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, nanstr, infstr)
116116
nothing
117117
end
118118

119-
Base.show(io::IO, x::AbstractFloat) = _show(io, x, SHORTEST, 0, true)
119+
Base.show(io::IO, x::AbstractFloat) = Base.limit_output(io) ? showcompact(io, x) : _show(io, x, SHORTEST, 0, true)
120120

121121
Base.print(io::IO, x::Float32) = _show(io, x, SHORTEST, 0, false)
122122
Base.print(io::IO, x::Float16) = _show(io, x, SHORTEST, 0, false)

base/interactiveutil.jl

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,23 +220,19 @@ versioninfo(verbose::Bool) = versioninfo(STDOUT,verbose)
220220
# displaying type-ambiguity warnings
221221

222222
function code_warntype(io::IO, f, t::ANY)
223-
task_local_storage(:TYPEEMPHASIZE, true)
224-
try
225-
ct = code_typed(f, t)
226-
for ast in ct
227-
println(io, "Variables:")
228-
vars = ast.args[2][1]
229-
for v in vars
230-
print(io, " ", v[1])
231-
show_expr_type(io, v[2])
232-
print(io, '\n')
233-
end
234-
print(io, "\nBody:\n ")
235-
show_unquoted(io, ast.args[3], 2)
236-
print(io, '\n')
223+
emph_io = IOContext(io, :TYPEEMPHASIZE => true)
224+
ct = code_typed(f, t)
225+
for ast in ct
226+
println(emph_io, "Variables:")
227+
vars = ast.args[2][1]
228+
for v in vars
229+
print(emph_io, " ", v[1])
230+
show_expr_type(emph_io, v[2])
231+
print(emph_io, '\n')
237232
end
238-
finally
239-
task_local_storage(:TYPEEMPHASIZE, false)
233+
print(emph_io, "\nBody:\n ")
234+
show_unquoted(emph_io, ast.args[3], 2)
235+
print(emph_io, '\n')
240236
end
241237
nothing
242238
end

base/io.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,39 @@ function eof end
2727
read(s::IO, ::Type{UInt8}) = error(typeof(s)," does not support byte I/O")
2828
write(s::IO, x::UInt8) = error(typeof(s)," does not support byte I/O")
2929

30+
# Generic wrappers around other IO objects
31+
abstract AbstractPipe <: IO
32+
function pipe_reader end
33+
function pipe_writer end
34+
35+
write(io::AbstractPipe, byte::UInt8) = write(pipe_writer(io), byte)
36+
write(io::AbstractPipe, bytes::Vector{UInt8}) = write(pipe_writer(io), bytes)
37+
write{T<:AbstractPipe}(io::T, args...) = write(pipe_writer(io), args...)
38+
write{S<:AbstractPipe}(io::S, a::Array) = write(pipe_writer(io), a)
39+
buffer_or_write(io::AbstractPipe, p::Ptr, n::Integer) = buffer_or_write(pipe_writer(io), p, n)
40+
buffer_writes(io::AbstractPipe, args...) = buffer_writes(pipe_writer(io), args...)
41+
flush(io::AbstractPipe) = flush(pipe_writer(io))
42+
43+
read(io::AbstractPipe, byte::Type{UInt8}) = read(pipe_reader(io), byte)
44+
read!(io::AbstractPipe, bytes::Vector{UInt8}) = read!(pipe_reader(io), bytes)
45+
read{T<:AbstractPipe}(io::T, args...) = read(pipe_reader(io), args...)
46+
read!{T<:AbstractPipe}(io::T, args...) = read!(pipe_reader(io), args...)
47+
readuntil{T<:AbstractPipe}(io::T, args...) = readuntil(pipe_reader(io), args...)
48+
readbytes(io::AbstractPipe) = readbytes(pipe_reader(io))
49+
readavailable(io::AbstractPipe) = readavailable(pipe_reader(io))
50+
51+
isreadable(io::AbstractPipe) = isreadable(pipe_reader(io))
52+
iswritable(io::AbstractPipe) = iswritable(pipe_writer(io))
53+
isopen(io::AbstractPipe) = isopen(pipe_writer(io)) || isopen(pipe_reader(io))
54+
close(io::AbstractPipe) = (close(pipe_writer(io)); close(pipe_reader(io)))
55+
wait_readnb(io::AbstractPipe, nb::Int) = wait_readnb(pipe_reader(io), nb)
56+
wait_readbyte(io::AbstractPipe, byte::UInt8) = wait_readbyte(pipe_reader(io), byte)
57+
wait_close(io::AbstractPipe) = (wait_close(pipe_writer(io)); wait_close(pipe_reader(io)))
58+
nb_available(io::AbstractPipe) = nb_available(pipe_reader(io))
59+
eof(io::AbstractPipe) = eof(pipe_reader(io))
60+
reseteof(io::AbstractPipe) = reseteof(pipe_reader(io))
61+
62+
3063
## byte-order mark, ntoh & hton ##
3164

3265
const ENDIAN_BOM = reinterpret(UInt32,UInt8[1:4;])[1]

base/iostream.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,6 @@ function takebuf_raw(s::IOStream)
200200
return buf, sz
201201
end
202202

203-
function sprint(size::Integer, f::Function, args...)
204-
s = IOBuffer(Array(UInt8,size), true, true)
205-
truncate(s,0)
206-
f(s, args...)
207-
takebuf_string(s)
208-
end
209-
210-
sprint(f::Function, args...) = sprint(0, f, args...)
211-
212203
write(x) = write(STDOUT::IO, x)
213204

214205
function readuntil(s::IOStream, delim::UInt8)

base/irrationals.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ log(::Irrational{:e}) = 1 # use 1 to correctly promote expressions like log(x)/l
130130
log(::Irrational{:e}, x) = log(x)
131131

132132
# align along = for nice Array printing
133-
function alignment(x::Irrational)
134-
m = match(r"^(.*?)(=.*)$", sprint(showcompact_lim, x))
135-
m === nothing ? (length(sprint(showcompact_lim, x)), 0) :
133+
function alignment(io::IO, x::Irrational)
134+
m = match(r"^(.*?)(=.*)$", sprint(0, showcompact_lim, x, env=io))
135+
m === nothing ? (length(sprint(0, showcompact_lim, x, env=io)), 0) :
136136
(length(m.captures[1]), length(m.captures[2]))
137137
end

base/methodshow.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,4 @@ end
181181

182182
# override usual show method for Vector{Method}: don't abbreviate long lists
183183
writemime(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method}) =
184-
showarray(io, mt, limit=false)
184+
showarray(IOContext(io, :limit_output => false), mt)

0 commit comments

Comments
 (0)