diff --git a/base/client.jl b/base/client.jl index 25fb605d729e3..0ce4719d81eb4 100644 --- a/base/client.jl +++ b/base/client.jl @@ -30,6 +30,8 @@ answer_color() = text_colors[repl_color("JULIA_ANSWER_COLOR", default_color_answ stackframe_lineinfo_color() = repl_color("JULIA_STACKFRAME_LINEINFO_COLOR", :bold) stackframe_function_color() = repl_color("JULIA_STACKFRAME_FUNCTION_COLOR", :bold) +alt_light_black_color() = repl_color("JULIA_ALT_LIGHT_BLACK_COLOR", :light_black) + function repl_cmd(cmd, out) shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh"))) shell_name = Base.basename(shell[1]) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 2f6a956e8160f..ff148b6cdbfcf 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -150,7 +150,7 @@ function should_print_ssa_type(@nospecialize node) end function default_expr_type_printer(io::IO, @nospecialize(typ), used::Bool) - printstyled(io, "::", typ, color=(used ? :cyan : :light_black)) + printstyled(io, "::", typ, color=(used ? :cyan : :alt_light_black)) nothing end @@ -561,16 +561,16 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print for (i, x) in enumerate(stack) if i > length(last_stack) || last_stack[i] != x entry = code.linetable[x] - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) + printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :alt_light_black) print(io, bb_guard_rail) ssa_guard = " "^(maxlength_idx + 4 + (i - 1)) entry_label = "$(ssa_guard)$(method_name(entry)) at $(entry.file):$(entry[:line]) " hline = string("─"^(start_column-length(entry_label)-length(bb_guard_rail)+max_depth-i), "┐") - printstyled(io, string(entry_label, hline), "\n"; color=:light_black) + printstyled(io, string(entry_label, hline), "\n"; color=:alt_light_black) bb_guard_rail = bb_guard_rail_cont end end - printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :light_black) + printstyled(io, "\e[$(start_column)G$(rail)\e[1G", color = :alt_light_black) last_stack = stack else if idx <= length(loc_annotations) @@ -589,9 +589,9 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print if get(io, :color, false) method_start_column = cols - max_method_width - max_loc_width - 2 filler = " "^(max_loc_width-length(annotation)) - printstyled(io, "\e[$(method_start_column)G$(annotation)$(filler)$(loc_method)\e[1G", color = :light_black) + printstyled(io, "\e[$(method_start_column)G$(annotation)$(filler)$(loc_method)\e[1G", color = :alt_light_black) end - printstyled(io, lineno, " "^(max_lineno_width - length(lineno) + 1); color = :light_black) + printstyled(io, lineno, " "^(max_lineno_width - length(lineno) + 1); color = :alt_light_black) end idx != last(bbrange) && print(io, bb_guard_rail) print_sep = false @@ -688,23 +688,23 @@ function show_ir_stmt(io::IO, code::CodeInfo, idx::Int, line_info_preprinter, li # If invariants are violated, print a special leader linestart = " "^(max_bb_idx_size + 2) # not inside a basic block bracket inlining_indent = line_info_preprinter(io, linestart, idx) - printstyled(io, "!!! ", "─"^max_bb_idx_size, color=:light_black) + printstyled(io, "!!! ", "─"^max_bb_idx_size, color=:alt_light_black) else bbrange = cfg.blocks[bb_idx].stmts bbrange = bbrange.start:bbrange.stop # Print line info update - linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=:light_black), context=io) + linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=:alt_light_black), context=io) linestart *= " "^max_bb_idx_size inlining_indent = line_info_preprinter(io, linestart, idx) if idx == first(bbrange) bb_idx_str = string(bb_idx) bb_pad = max_bb_idx_size - length(bb_idx_str) bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" - printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=:light_black) + printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=:alt_light_black) elseif idx == last(bbrange) # print separator - printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=:light_black) + printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=:alt_light_black) else - printstyled(io, "│ ", " "^max_bb_idx_size, color=:light_black) + printstyled(io, "│ ", " "^max_bb_idx_size, color=:alt_light_black) end if idx == last(bbrange) bb_idx += 1 diff --git a/base/errorshow.jl b/base/errorshow.jl index f340df9738299..f5a480bf39daf 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -563,7 +563,7 @@ function replaceuserpath(str) end const STACKTRACE_MODULECOLORS = [:magenta, :cyan, :green, :yellow] -const STACKTRACE_FIXEDCOLORS = IdDict(Base => :light_black, Core => :light_black) +const STACKTRACE_FIXEDCOLORS = IdDict(Base => :alt_light_black, Core => :alt_light_black) stacktrace_expand_basepaths()::Bool = tryparse(Bool, get(ENV, "JULIA_STACKTRACE_EXPAND_BASEPATHS", "false")) === true @@ -663,7 +663,7 @@ function show_reduced_backtrace(io::IO, t::Vector) popfirst!(repeated_cycle) printstyled(io, "--- the last ", cycle_length, " lines are repeated ", - repetitions, " more time", repetitions>1 ? "s" : "", " ---", color = :light_black) + repetitions, " more time", repetitions>1 ? "s" : "", " ---", color = :alt_light_black) if i < length(displayed_stackframes) println(io) stacktrace_linebreaks() && println(io) @@ -718,12 +718,12 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, m StackTraces.show_spec_linfo(IOContext(io, :backtrace=>true), frame) if n > 1 - printstyled(io, " (repeats $n times)"; color=:light_black) + printstyled(io, " (repeats $n times)"; color=:alt_light_black) end println(io) # @ - printstyled(io, " " ^ (digit_align_width + 2) * "@ ", color = :light_black) + printstyled(io, " " ^ (digit_align_width + 2) * "@ ", color = :alt_light_black) # module if modul !== nothing @@ -735,22 +735,14 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, m pathparts = splitpath(file) folderparts = pathparts[1:end-1] if !isempty(folderparts) - printstyled(io, joinpath(folderparts...) * (Sys.iswindows() ? "\\" : "/"), color = :light_black) + printstyled(io, joinpath(folderparts...) * (Sys.iswindows() ? "\\" : "/"), color = :alt_light_black) end # filename, separator, line - # use escape codes for formatting, printstyled can't do underlined and color - # codes are bright black (90) and underlined (4) - function print_underlined(io::IO, s...) - colored = get(io, :color, false)::Bool - start_s = colored ? "\033[90;4m" : "" - end_s = colored ? "\033[0m" : "" - print(io, start_s, s..., end_s) - end - print_underlined(io, pathparts[end], ":", line) + printstyled(io, pathparts[end], ":", line; color = :alt_light_black, underline = true) # inlined - printstyled(io, inlined ? " [inlined]" : "", color = :light_black) + printstyled(io, inlined ? " [inlined]" : "", color = :alt_light_black) end diff --git a/base/show.jl b/base/show.jl index 814184c810af0..faa678c431799 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2187,7 +2187,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwa first || print(io, ", ") first = false if show_argnames - print_within_stacktrace(io, argnames[i]; color=:light_black) + print_within_stacktrace(io, argnames[i]; color = :alt_light_black) end print(io, "::") print_type_stacktrace(env_io, sig[i]) @@ -2198,7 +2198,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwa for (k, t) in kwargs first || print(io, ", ") first = false - print_within_stacktrace(io, k; color=:light_black) + print_within_stacktrace(io, k; color = :alt_light_black) print(io, "::") print_type_stacktrace(io, t) end @@ -2215,7 +2215,7 @@ function print_type_stacktrace(io, type; color=:normal) printstyled(io, str; color=color) else printstyled(io, str[1:prevind(str,i)]; color=color) - printstyled(io, str[i:end]; color=:light_black) + printstyled(io, str[i:end]; color = :alt_light_black) end end diff --git a/base/util.jl b/base/util.jl index 348b09f3f4c1c..128d0a9b3fbdf 100644 --- a/base/util.jl +++ b/base/util.jl @@ -67,7 +67,9 @@ 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) +function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}, io::IO, args...; + bold::Bool = false, underline::Bool = false, blink::Bool = false, + reverse::Bool = false, hidden::Bool = false) buf = IOBuffer() iscolor = get(io, :color, false)::Bool try f(IOContext(buf, io), args...) @@ -76,10 +78,24 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol} if !iscolor print(io, str) else + color === :alt_light_black && (color = Base.alt_light_black_color()) bold && color === :bold && (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] : "") - disable_ansi = (bold ? disable_text_style[:bold] : "") * + (bold ? text_colors[:bold] : "") * + (underline ? text_colors[:underline] : "") * + (blink ? text_colors[:blink] : "") * + (reverse ? text_colors[:reverse] : "") * + (hidden ? text_colors[:hidden] : "") + + disable_ansi = (hidden ? disable_text_style[:hidden] : "") * + (reverse ? disable_text_style[:reverse] : "") * + (blink ? disable_text_style[:blink] : "") * + (underline ? disable_text_style[:underline] : "") * + (bold ? disable_text_style[:bold] : "") * get(disable_text_style, color, text_colors[:default]) first = true for line in split(str, '\n') @@ -94,18 +110,23 @@ function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol} end """ - printstyled([io], xs...; bold::Bool=false, color::Union{Symbol,Int}=:normal) + printstyled([io], xs...; bold::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. `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. If the keyword `bold` is given as `true`, the result will be printed in bold. +If the keyword `underline` is given as `true`, the result will be printed underlined. +If the keyword `blink` is given as `true`, the result will blink. +If the keyword `reverse` is given as `true`, the result will have foreground and background colors inversed. +If the keyword `hidden` is given as `true`, the result will be hidden. +Keywords can be given in any combination. """ -printstyled(io::IO, msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) = - with_output_color(print, color, io, msg...; bold=bold) -printstyled(msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) = - printstyled(stdout, msg...; bold=bold, color=color) +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) +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) """ Base.julia_cmd(juliapath=joinpath(Sys.BINDIR::String, julia_exename())) diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index 5aee664d95669..802a456688c78 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -9,7 +9,7 @@ highlighting = Dict{Symbol, Bool}( llstyle = Dict{Symbol, Tuple{Bool, Union{Symbol, Int}}}( :default => (false, :normal), # e.g. comma, equal sign, unknown token - :comment => (false, :light_black), + :comment => (false, :alt_light_black), :label => (false, :light_red), :instruction => ( true, :light_cyan), :type => (false, :cyan), diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index ac4b17b59e14a..af80abf323b39 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -159,7 +159,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module if i == length(msglines) && !isempty(suffix) npad = max(0, justify_width - nonpadwidth) + minsuffixpad print(iob, " "^npad) - printstyled(iob, suffix, color=:light_black) + printstyled(iob, suffix, color=:alt_light_black) end println(iob) end diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index ecdb7595fb62e..cc10d8da69141 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -465,6 +465,13 @@ ENV["JULIA_WARN_COLOR"] = :yellow ENV["JULIA_INFO_COLOR"] = :cyan ``` +Some colorschemes define light black color to be the same color as background, so some messages +become invisible. You can override it by adding the following to your `~/.julia/config/startup.jl` file: + +```julia +ENV["JULIA_ALT_LIGHT_BLACK_COLOR"] = 10 +``` + ## TerminalMenus TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal. diff --git a/test/misc.jl b/test/misc.jl index 41b92785fa5b6..357a8cf3fd813 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -597,6 +597,43 @@ let buf = IOBuffer() # Check that boldness is turned off printstyled(buf_color, "foo"; bold=true, color=:red) @test String(take!(buf)) == "\e[31m\e[1mfoo\e[22m\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" + + # Check that blink is turned off + printstyled(buf_color, "foo"; color = :red, blink = true) + @test String(take!(buf)) == "\e[31m\e[5mfoo\e[25m\e[39m" + + # Check that reverse is turned off + printstyled(buf_color, "foo"; color = :red, reverse = true) + @test String(take!(buf)) == "\e[31m\e[7mfoo\e[27m\e[39m" + + # Check that hidden is turned off + printstyled(buf_color, "foo"; color = :red, hidden = true) + @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" + + # Check that :alt_light_black is :light_black by default + curr_color = pop!(ENV, "JULIA_ALT_LIGHT_BLACK_COLOR", nothing) + printstyled(buf_color, "foo"; color = :alt_light_black) + @test String(take!(buf)) == "\e[90mfoo\e[39m" + + # Check that we can change alt_light_black with environmental variable + ENV["JULIA_ALT_LIGHT_BLACK_COLOR"] = :red + printstyled(buf_color, "foo"; color = :alt_light_black) + @test String(take!(buf)) == "\e[31mfoo\e[39m" + + # recover previous state of environment + if !isnothing(curr_color) + ENV["JULIA_ALT_LIGHT_BLACK_COLOR"] = curr_color + else + pop!(ENV, "JULIA_ALT_LIGHT_BLACK_COLOR") + end end abstract type DA_19281{T, N} <: AbstractArray{T, N} end