From 250916f3a4e515e6edcfcf831e381c38828c4ccc Mon Sep 17 00:00:00 2001 From: tecosaur Date: Sat, 10 Feb 2024 11:09:31 +0800 Subject: [PATCH] Use StyledStrings for Logging (#51829) Transition from printstyled to the new approach to styling provided by StyledStrings. This both makes it possible for the styling used to be customised, and allows for other styled content to inherit/re-use the logging styles. --- doc/Manifest.toml | 1 + pkgimage.mk | 2 +- stdlib/Logging/Project.toml | 3 +++ stdlib/Logging/src/ConsoleLogger.jl | 33 ++++++++++++++++------------- stdlib/Logging/src/Logging.jl | 12 +++++------ stdlib/Logging/test/runtests.jl | 24 ++++++++++----------- test/precompile.jl | 1 + 7 files changed, 42 insertions(+), 34 deletions(-) diff --git a/doc/Manifest.toml b/doc/Manifest.toml index f3e4b08306bd2..b34942bbddd3a 100644 --- a/doc/Manifest.toml +++ b/doc/Manifest.toml @@ -134,6 +134,7 @@ uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" version = "1.17.0+0" [[deps.Logging]] +deps = ["StyledStrings"] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" version = "1.11.0" diff --git a/pkgimage.mk b/pkgimage.mk index b45b4ab89560b..c9de49d2f8421 100644 --- a/pkgimage.mk +++ b/pkgimage.mk @@ -80,7 +80,6 @@ $(eval $(call stdlib_builder,Base64,)) $(eval $(call stdlib_builder,CRC32c,)) $(eval $(call stdlib_builder,FileWatching,)) $(eval $(call stdlib_builder,Libdl,)) -$(eval $(call stdlib_builder,Logging,)) $(eval $(call stdlib_builder,Mmap,)) $(eval $(call stdlib_builder,NetworkOptions,)) $(eval $(call stdlib_builder,SHA,)) @@ -109,6 +108,7 @@ $(eval $(call stdlib_builder,OpenBLAS_jll,Artifacts Libdl)) $(eval $(call stdlib_builder,Markdown,Base64)) $(eval $(call stdlib_builder,Printf,Unicode)) $(eval $(call stdlib_builder,Random,SHA)) +$(eval $(call stdlib_builder,Logging,StyledStrings)) $(eval $(call stdlib_builder,Tar,ArgTools,SHA)) $(eval $(call stdlib_builder,DelimitedFiles,Mmap)) $(eval $(call stdlib_builder,JuliaSyntaxHighlighting,StyledStrings)) diff --git a/stdlib/Logging/Project.toml b/stdlib/Logging/Project.toml index ce69112733d5e..3fc288e25f0b7 100644 --- a/stdlib/Logging/Project.toml +++ b/stdlib/Logging/Project.toml @@ -2,6 +2,9 @@ name = "Logging" uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" version = "1.11.0" +[deps] +StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" + [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 1d45296c907d1..0922e9fcc66c9 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -12,10 +12,10 @@ Log levels less than `min_level` are filtered out. Message formatting can be controlled by setting keyword arguments: * `meta_formatter` is a function which takes the log event metadata - `(level, _module, group, id, file, line)` and returns a color (as would be - passed to printstyled), prefix and suffix for the log message. The - default is to prefix with the log level and a suffix containing the module, - file and line location. + `(level, _module, group, id, file, line)` and returns a face name (used in + the constructed [`AnnotatedString`](@ref Base.AnnotatedString)), prefix and + suffix for the log message. The default is to prefix with the log level and + a suffix containing the module, file and line location. * `show_limited` limits the printing of large data structures to something which can fit on the screen by setting the `:limit` `IOContext` key during formatting. @@ -59,10 +59,10 @@ showvalue(io, ex::Exception) = showerror(io, ex) function default_logcolor(level::LogLevel) level in keys(custom_log_levels) ? custom_log_levels[level][2] : - level < Info ? Base.debug_color() : - level < Warn ? Base.info_color() : - level < Error ? Base.warn_color() : - Base.error_color() + level < Info ? :log_debug : + level < Warn ? :log_info : + level < Error ? :log_warn : + :log_error end function default_metafmt(level::LogLevel, _module, group, id, file, line) @@ -104,6 +104,8 @@ function termlength(str) return N end +termlength(str::Base.AnnotatedString) = textwidth(str) + function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id, filepath, line; kwargs...) @nospecialize @@ -146,6 +148,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Format lines as text with appropriate indentation and with a box # decoration on the left. color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String} + color = StyledStrings.Face(foreground=StyledStrings.Legacy.legacy_color(color)) minsuffixpad = 2 buf = IOBuffer() iob = IOContext(buf, stream) @@ -159,19 +162,19 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module nonpadwidth = 2 + length(suffix) end for (i, (indent, msg)) in enumerate(msglines) - boxstr = length(msglines) == 1 ? "[ " : - i == 1 ? "┌ " : - i < length(msglines) ? "│ " : - "└ " - printstyled(iob, boxstr, bold=true, color=color) + boxstr = length(msglines) == 1 ? "[" : + i == 1 ? "┌" : + i < length(msglines) ? "│" : + "└" + print(iob, styled"{$color,bold:$boxstr} ") if i == 1 && !isempty(prefix) - printstyled(iob, prefix, " ", bold=true, color=color) + print(iob, styled"{$color,bold:$prefix} ") end print(iob, " "^indent, msg) if i == length(msglines) && !isempty(suffix) npad = max(0, justify_width - nonpadwidth) + minsuffixpad print(iob, " "^npad) - printstyled(iob, suffix, color=:light_black) + print(iob, styled"{shadow:$suffix}") end println(iob) end diff --git a/stdlib/Logging/src/Logging.jl b/stdlib/Logging/src/Logging.jl index 83e93ee396361..1cb1bca774c27 100644 --- a/stdlib/Logging/src/Logging.jl +++ b/stdlib/Logging/src/Logging.jl @@ -8,6 +8,8 @@ and available by default. """ module Logging +using StyledStrings + # Import the CoreLogging implementation into Logging as new const bindings. # Doing it this way (rather than with import) makes these symbols accessible to # tab completion. @@ -31,13 +33,11 @@ for sym in [ end """ - @create_log_macro(name::Symbol, level::Int, color::Union{Int,Symbol}) - -Creates a custom log macro like `@info`, `@warn` etc. with a given `name`, `level` and -`color`. The macro created is named with the lowercase form of `name` but the given form -is used for the printing. + @create_log_macro(name::Symbol, level::Int, face::Union{Symbol, StyledStrings.Face}) -The available color keys can be seen by typing `Base.text_colors` in the help mode of the REPL +Creates a custom log macro like `@info`, `@warn` etc. with a given `name`, +`level` to be displayed with `face`. The macro created is named with the +lowercase form of `name` but the given form is used for the printing. ```julia-repl julia> @create_log_macro(:MyLog, 200, :magenta) diff --git a/stdlib/Logging/test/runtests.jl b/stdlib/Logging/test/runtests.jl index e0fc6a0bc3770..15371ac5d442c 100644 --- a/stdlib/Logging/test/runtests.jl +++ b/stdlib/Logging/test/runtests.jl @@ -54,24 +54,24 @@ end @testset "Default metadata formatting" begin @test Logging.default_metafmt(Logging.Debug, Base, :g, :i, expanduser("~/somefile.jl"), 42) == - (:blue, "Debug:", "@ Base ~/somefile.jl:42") + (:log_debug, "Debug:", "@ Base ~/somefile.jl:42") @test Logging.default_metafmt(Logging.Info, Main, :g, :i, "a.jl", 1) == - (:cyan, "Info:", "") + (:log_info, "Info:", "") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", 2) == - (:yellow, "Warning:", "@ Main b.jl:2") + (:log_warn, "Warning:", "@ Main b.jl:2") @test Logging.default_metafmt(Logging.Error, Main, :g, :i, "", 0) == - (:light_red, "Error:", "@ Main :0") + (:log_error, "Error:", "@ Main :0") # formatting of nothing @test Logging.default_metafmt(Logging.Warn, nothing, :g, :i, "b.jl", 2) == - (:yellow, "Warning:", "@ b.jl:2") + (:log_warn, "Warning:", "@ b.jl:2") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, nothing, 2) == - (:yellow, "Warning:", "@ Main") + (:log_warn, "Warning:", "@ Main") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", nothing) == - (:yellow, "Warning:", "@ Main b.jl") + (:log_warn, "Warning:", "@ Main b.jl") @test Logging.default_metafmt(Logging.Warn, nothing, :g, :i, nothing, 2) == - (:yellow, "Warning:", "") + (:log_warn, "Warning:", "") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", 2:5) == - (:yellow, "Warning:", "@ Main b.jl:2-5") + (:log_warn, "Warning:", "@ Main b.jl:2-5") end function dummy_metafmt(level, _module, group, id, file, line) @@ -256,9 +256,9 @@ end # Basic colorization test @test genmsg("line1\nline2", color=true) == """ - \e[36m\e[1m┌ \e[22m\e[39m\e[36m\e[1mPREFIX \e[22m\e[39mline1 - \e[36m\e[1m│ \e[22m\e[39mline2 - \e[36m\e[1m└ \e[22m\e[39m\e[90mSUFFIX\e[39m + \e[36m\e[1m┌\e[39m\e[22m \e[36m\e[1mPREFIX\e[39m\e[22m line1 + \e[36m\e[1m│\e[39m\e[22m line2 + \e[36m\e[1m└\e[39m\e[22m \e[90mSUFFIX\e[39m """ end diff --git a/test/precompile.jl b/test/precompile.jl index 1eed9b1418a63..d1360d1a06357 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -469,6 +469,7 @@ precompile_test_harness(false) do dir # and their dependencies Dict(Base.PkgId(Base.root_module(Base, :SHA)) => Base.module_build_id(Base.root_module(Base, :SHA))), Dict(Base.PkgId(Base.root_module(Base, :Markdown)) => Base.module_build_id(Base.root_module(Base, :Markdown))), + Dict(Base.PkgId(Base.root_module(Base, :StyledStrings)) => Base.module_build_id(Base.root_module(Base, :StyledStrings))), # and their dependencies Dict(Base.PkgId(Base.root_module(Base, :Base64)) => Base.module_build_id(Base.root_module(Base, :Base64))), )