diff --git a/NEWS.md b/NEWS.md index e626b7a276197..4f9c315659ae5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,6 +38,7 @@ New library functions New library features -------------------- +* The optional keyword argument `context` of `sprint` can now be set to a tuple of `:key => value` pairs to specify multiple attributes. ([#39381]) Standard library changes ------------------------ diff --git a/base/strings/io.jl b/base/strings/io.jl index 30ffe03354604..6003a6d503b90 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -79,14 +79,19 @@ println(io::IO, xs...) = print(io, xs..., "\n") Call the given function with an I/O stream and the supplied extra arguments. Everything written to this I/O stream is returned as a string. -`context` can be either an [`IOContext`](@ref) whose properties will be used, -or a `Pair` specifying a property and its value. `sizehint` suggests the capacity -of the buffer (in bytes). +`context` can be an [`IOContext`](@ref) whose properties will be used, a `Pair` +specifying a property and its value, or a tuple of `Pair` specifying multiple +properties and their values. `sizehint` suggests the capacity of the buffer (in +bytes). -The optional keyword argument `context` can be set to `:key=>value` pair -or an `IO` or [`IOContext`](@ref) object whose attributes are used for the I/O -stream passed to `f`. The optional `sizehint` is a suggested size (in bytes) -to allocate for the buffer used to write the string. +The optional keyword argument `context` can be set to a `:key=>value` pair, a +tuple of `:key=>value` pairs, or an `IO` or [`IOContext`](@ref) object whose +attributes are used for the I/O stream passed to `f`. The optional `sizehint` +is a suggested size (in bytes) to allocate for the buffer used to write the +string. + +!!! compat "Julia 1.7" + Passing a tuple to keyword `context` requires Julia 1.7 or later. # Examples ```jldoctest @@ -99,7 +104,9 @@ julia> sprint(showerror, BoundsError([1], 100)) """ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) s = IOBuffer(sizehint=sizehint) - if context !== nothing + if context isa Tuple + f(IOContext(s, context...), args...) + elseif context !== nothing f(IOContext(s, context), args...) else f(s, args...) diff --git a/test/strings/io.jl b/test/strings/io.jl index 0ebb16bd42e60..91ad83b24e328 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -187,6 +187,38 @@ join(myio, "", "", 1) @test_throws ArgumentError unescape_string(IOBuffer(), string('\\',"N")) @test_throws ArgumentError unescape_string(IOBuffer(), string('\\',"m")) end + +@testset "sprint with context" begin + function f(io::IO) + println(io, "compact => ", get(io, :compact, false)) + println(io, "limit => ", get(io, :limit, false)) + end + + str = sprint(f) + @test str == """ + compact => false + limit => false + """ + + str = sprint(f, context = :compact => true) + @test str == """ + compact => true + limit => false + """ + + str = sprint(f, context = (:compact => true, :limit => true)) + @test str == """ + compact => true + limit => true + """ + + str = sprint(f, context = IOContext(stdout, :compact => true, :limit => true)) + @test str == """ + compact => true + limit => true + """ +end + @testset "#11659" begin # The indentation code was not correctly counting tab stops @test Base.indentation(" \t") == (8, true)