@@ -484,10 +484,70 @@ function repl_backend_loop(backend::REPLBackend, get_module::Function)
484
484
return nothing
485
485
end
486
486
487
+ SHOW_MAXIMUM_BYTES:: Int = 20480
488
+
489
+ # Limit printing during REPL display
490
+ mutable struct LimitIO{IO_t <: IO } <: IO
491
+ io:: IO_t
492
+ maxbytes:: Int
493
+ n:: Int # max bytes to write
494
+ end
495
+ LimitIO (io:: IO , maxbytes) = LimitIO (io, maxbytes, 0 )
496
+
497
+ struct LimitIOException <: Exception
498
+ maxbytes:: Int
499
+ end
500
+
501
+ function Base. showerror (io:: IO , e:: LimitIOException )
502
+ print (io, " $LimitIOException : aborted printing after attempting to print more than $(Base. format_bytes (e. maxbytes)) within a `LimitIO`." )
503
+ end
504
+
505
+ function Base. write (io:: LimitIO , v:: UInt8 )
506
+ io. n > io. maxbytes && throw (LimitIOException (io. maxbytes))
507
+ n_bytes = write (io. io, v)
508
+ io. n += n_bytes
509
+ return n_bytes
510
+ end
511
+
512
+ # Semantically, we only need to override `Base.write`, but we also
513
+ # override `unsafe_write` for performance.
514
+ function Base. unsafe_write (limiter:: LimitIO , p:: Ptr{UInt8} , nb:: UInt )
515
+ # already exceeded? throw
516
+ limiter. n > limiter. maxbytes && throw (LimitIOException (limiter. maxbytes))
517
+ remaining = limiter. maxbytes - limiter. n # >= 0
518
+
519
+ # Not enough bytes left; we will print up to the limit, then throw
520
+ if remaining < nb
521
+ if remaining > 0
522
+ Base. unsafe_write (limiter. io, p, remaining)
523
+ end
524
+ throw (LimitIOException (limiter. maxbytes))
525
+ end
526
+
527
+ # We won't hit the limit so we'll write the full `nb` bytes
528
+ bytes_written = Base. unsafe_write (limiter. io, p, nb)
529
+ limiter. n += bytes_written
530
+ return bytes_written
531
+ end
532
+
487
533
struct REPLDisplay{Repl<: AbstractREPL } <: AbstractDisplay
488
534
repl:: Repl
489
535
end
490
536
537
+ function show_limited (io:: IO , mime:: MIME , x)
538
+ try
539
+ # We wrap in a LimitIO to limit the amount of printing.
540
+ # We unpack `IOContext`s, since we will pass the properties on the outside.
541
+ inner = io isa IOContext ? io. io : io
542
+ wrapped_limiter = IOContext (LimitIO (inner, SHOW_MAXIMUM_BYTES), io)
543
+ # `show_repl` to allow the hook with special syntax highlighting
544
+ show_repl (wrapped_limiter, mime, x)
545
+ catch e
546
+ e isa LimitIOException || rethrow ()
547
+ printstyled (io, """ …[printing stopped after displaying $(Base. format_bytes (e. maxbytes)) ; call `show(stdout, MIME"text/plain"(), ans)` to print without truncation]""" ; color= :light_yellow , bold= true )
548
+ end
549
+ end
550
+
491
551
function display (d:: REPLDisplay , mime:: MIME"text/plain" , x)
492
552
x = Ref {Any} (x)
493
553
with_repl_linfo (d. repl) do io
@@ -504,7 +564,7 @@ function display(d::REPLDisplay, mime::MIME"text/plain", x)
504
564
# this can override the :limit property set initially
505
565
io = foldl (IOContext, d. repl. options. iocontext, init= io)
506
566
end
507
- show_repl (io, mime, x[])
567
+ show_limited (io, mime, x[])
508
568
println (io)
509
569
end
510
570
return nothing
0 commit comments