Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support italic style in printstyled. #45164

Merged
merged 1 commit into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ New library features
is now a no-op ([#47979]). It previously exposed unsafe behavior ([#47977]).
* `binomial(x, k)` now supports non-integer `x` ([#48124]).
* A `CartesianIndex` is now treated as a "scalar" for broadcasting ([#47044]).
* `printstyled` now supports italic output ([#45164]).

Standard library changes
------------------------
Expand Down
27 changes: 19 additions & 8 deletions base/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const text_colors = Dict{Union{Symbol,Int},String}(
:normal => "\033[0m",
:default => "\033[39m",
:bold => "\033[1m",
:italic => "\033[3m",
:underline => "\033[4m",
:blink => "\033[5m",
:reverse => "\033[7m",
Expand All @@ -35,6 +36,7 @@ end

const disable_text_style = Dict{Symbol,String}(
:bold => "\033[22m",
:italic => "\033[23m",
:underline => "\033[24m",
:blink => "\033[25m",
:reverse => "\033[27m",
Expand All @@ -47,7 +49,7 @@ const disable_text_style = Dict{Symbol,String}(
# Create a docstring with an automatically generated list
# of colors.
let color_syms = collect(Iterators.filter(x -> !isa(x, Integer), keys(text_colors))),
formatting_syms = [:normal, :bold, :default]
formatting_syms = [:normal, :bold, :italic, :default]
global const available_text_colors = cat(
sort!(intersect(color_syms, formatting_syms), rev=true),
sort!(setdiff( color_syms, formatting_syms));
Expand All @@ -69,7 +71,7 @@ Printing with the color `:nothing` will print the string without modifications.
text_colors

function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}, io::IO, args...;
bold::Bool = false, underline::Bool = false, blink::Bool = false,
bold::Bool = false, italic::Bool = false, underline::Bool = false, blink::Bool = false,
reverse::Bool = false, hidden::Bool = false)
buf = IOBuffer()
iscolor = get(io, :color, false)::Bool
Expand All @@ -80,12 +82,14 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}
print(io, str)
else
bold && color === :bold && (color = :nothing)
italic && color === :italic && (color = :nothing)
underline && color === :underline && (color = :nothing)
blink && color === :blink && (color = :nothing)
reverse && color === :reverse && (color = :nothing)
hidden && color === :hidden && (color = :nothing)
enable_ansi = get(text_colors, color, text_colors[:default]) *
(bold ? text_colors[:bold] : "") *
(italic ? text_colors[:italic] : "") *
(underline ? text_colors[:underline] : "") *
(blink ? text_colors[:blink] : "") *
(reverse ? text_colors[:reverse] : "") *
Expand All @@ -96,6 +100,7 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}
(blink ? disable_text_style[:blink] : "") *
(underline ? disable_text_style[:underline] : "") *
(bold ? disable_text_style[:bold] : "") *
(italic ? disable_text_style[:italic] : "") *
get(disable_text_style, color, text_colors[:default])
first = true
for line in eachsplit(str, '\n')
Expand All @@ -110,27 +115,33 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}
end

"""
printstyled([io], xs...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Symbol,Int}=:normal)
printstyled([io], xs...; bold::Bool=false, italic::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Symbol,Int}=:normal)
Print `xs` in a color specified as a symbol or integer, optionally in bold.
Keyword `color` may take any of the values $(Base.available_text_colors_docstring)
or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors.
Keywords `bold=true`, `underline=true`, `blink=true` are self-explanatory.
Keywords `bold=true`, `italic=true`, `underline=true`, `blink=true` are self-explanatory.
Keyword `reverse=true` prints with foreground and background colors exchanged,
and `hidden=true` should be invisible in the terminal but can still be copied.
These properties can be used in any combination.
See also [`print`](@ref), [`println`](@ref), [`show`](@ref).
!!! note
Not all terminals support italic output. Some terminals interpret italic as reverse or
blink.
!!! compat "Julia 1.7"
Keywords except `color` and `bold` were added in Julia 1.7.
!!! compat "Julia 1.9"
Support for italic output was added in Julia 1.9.
"""
@constprop :none printstyled(io::IO, msg...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) =
with_output_color(print, color, io, msg...; bold=bold, underline=underline, blink=blink, reverse=reverse, hidden=hidden)
@constprop :none printstyled(msg...; bold::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) =
printstyled(stdout, msg...; bold=bold, underline=underline, blink=blink, reverse=reverse, hidden=hidden, color=color)
@constprop :none printstyled(io::IO, msg...; bold::Bool=false, italic::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) =
with_output_color(print, color, io, msg...; bold=bold, italic=italic, underline=underline, blink=blink, reverse=reverse, hidden=hidden)
@constprop :none printstyled(msg...; bold::Bool=false, italic::Bool=false, underline::Bool=false, blink::Bool=false, reverse::Bool=false, hidden::Bool=false, color::Union{Int,Symbol}=:normal) =
printstyled(stdout, msg...; bold=bold, italic=italic, underline=underline, blink=blink, reverse=reverse, hidden=hidden, color=color)

"""
Base.julia_cmd(juliapath=joinpath(Sys.BINDIR, julia_exename()); cpu_target)
Expand Down
8 changes: 6 additions & 2 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,10 @@ let buf = IOBuffer()
printstyled(buf_color, "foo"; bold=true, color=:red)
@test String(take!(buf)) == "\e[31m\e[1mfoo\e[22m\e[39m"

# Check that italic is turned off
printstyled(buf_color, "foo"; italic=true, color=:red)
@test String(take!(buf)) == "\e[31m\e[3mfoo\e[23m\e[39m"

# Check that underline is turned off
printstyled(buf_color, "foo"; color = :red, underline = true)
@test String(take!(buf)) == "\e[31m\e[4mfoo\e[24m\e[39m"
Expand All @@ -876,8 +880,8 @@ let buf = IOBuffer()
@test String(take!(buf)) == "\e[31m\e[8mfoo\e[28m\e[39m"

# Check that all options can be turned on simultaneously
printstyled(buf_color, "foo"; color = :red, bold = true, underline = true, blink = true, reverse = true, hidden = true)
@test String(take!(buf)) == "\e[31m\e[1m\e[4m\e[5m\e[7m\e[8mfoo\e[28m\e[27m\e[25m\e[24m\e[22m\e[39m"
printstyled(buf_color, "foo"; color = :red, bold = true, italic = true, underline = true, blink = true, reverse = true, hidden = true)
@test String(take!(buf)) == "\e[31m\e[1m\e[3m\e[4m\e[5m\e[7m\e[8mfoo\e[28m\e[27m\e[25m\e[24m\e[22m\e[23m\e[39m"
end

abstract type DA_19281{T, N} <: AbstractArray{T, N} end
Expand Down