diff --git a/README.md b/README.md index 4d792d5a..aadbf4bc 100644 --- a/README.md +++ b/README.md @@ -314,7 +314,7 @@ The method `label!` is responsible for the setting all the textual decorations o ![Decorate](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/doc/imgs/2.x/decorate.png) - * `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kwargs...)` + * `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kw...)` * `text` arbitrary annotation at position (x, y) diff --git a/docs/generate_docs.jl b/docs/generate_docs.jl index 08c73f8f..65db46f3 100644 --- a/docs/generate_docs.jl +++ b/docs/generate_docs.jl @@ -293,7 +293,7 @@ The method `label!` is responsible for the setting all the textual decorations o - `row` can be between 1 and the number of character rows of the canvas $(MD(Paragraph(indent(examples.decorate, 2)))) - - `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kwargs...)` + - `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kw...)` - `text` arbitrary annotation at position (x, y) ## Know Issues diff --git a/src/canvas/asciicanvas.jl b/src/canvas/asciicanvas.jl index 13ca5d50..5620f330 100644 --- a/src/canvas/asciicanvas.jl +++ b/src/canvas/asciicanvas.jl @@ -129,8 +129,8 @@ end @inline lookup_encode(::AsciiCanvas) = ascii_signs @inline lookup_decode(::AsciiCanvas) = ascii_decode -AsciiCanvas(args...; kwargs...) = - CreateLookupCanvas(AsciiCanvas, (0b000_000_000, 0b111_111_111), args...; kwargs...) +AsciiCanvas(args...; kw...) = + CreateLookupCanvas(AsciiCanvas, (0b000_000_000, 0b111_111_111), args...; kw...) function char_point!( c::AsciiCanvas, diff --git a/src/canvas/blockcanvas.jl b/src/canvas/blockcanvas.jl index 7bc82980..ffaf326f 100644 --- a/src/canvas/blockcanvas.jl +++ b/src/canvas/blockcanvas.jl @@ -54,8 +54,8 @@ end @inline lookup_encode(::BlockCanvas) = block_signs @inline lookup_decode(::BlockCanvas) = block_decode -BlockCanvas(args...; kwargs...) = - CreateLookupCanvas(BlockCanvas, (0b0000, 0b1111), args...; kwargs...) +BlockCanvas(args...; kw...) = + CreateLookupCanvas(BlockCanvas, (0b0000, 0b1111), args...; kw...) function char_point!( c::BlockCanvas, diff --git a/src/canvas/dotcanvas.jl b/src/canvas/dotcanvas.jl index c1b4f2f6..35abaa8e 100644 --- a/src/canvas/dotcanvas.jl +++ b/src/canvas/dotcanvas.jl @@ -43,8 +43,7 @@ end @inline lookup_encode(::DotCanvas) = dot_signs @inline lookup_decode(::DotCanvas) = dot_decode -DotCanvas(args...; kwargs...) = - CreateLookupCanvas(DotCanvas, (0b00, 0b11), args...; kwargs...) +DotCanvas(args...; kw...) = CreateLookupCanvas(DotCanvas, (0b00, 0b11), args...; kw...) function char_point!( c::DotCanvas, diff --git a/src/canvas/heatmapcanvas.jl b/src/canvas/heatmapcanvas.jl index 30376ce7..c190aae3 100644 --- a/src/canvas/heatmapcanvas.jl +++ b/src/canvas/heatmapcanvas.jl @@ -29,13 +29,13 @@ const HALF_BLOCK = '▄' @inline nrows(c::HeatmapCanvas) = div(size(grid(c), 2) + 1, 2) -HeatmapCanvas(args...; kwargs...) = CreateLookupCanvas( +HeatmapCanvas(args...; kw...) = CreateLookupCanvas( HeatmapCanvas, (0, 1), args...; min_char_width = 1, min_char_height = 1, - kwargs..., + kw..., ) _toCrayon(c) = c === nothing ? 0 : (c isa Unsigned ? Int(c) : c) diff --git a/src/common.jl b/src/common.jl index 05e37c62..27b3022e 100644 --- a/src/common.jl +++ b/src/common.jl @@ -154,7 +154,7 @@ const ASPECT_RATIO = 4 / 3 # default display size for the default BrailleCanvas (which has aspect ratio = 2) ==> (40, 15) const DEFAULT_HEIGHT = Ref(15) -const DEFAULT_WIDTH = Ref(2round(Int, ASPECT_RATIO * DEFAULT_HEIGHT[])) +const DEFAULT_WIDTH = Ref(round(Int, DEFAULT_HEIGHT[] * 2ASPECT_RATIO)) const MarkerType = Union{Symbol,Char,AbstractString} const UserColorType = Union{Integer,Symbol,NTuple{3,Integer},Nothing} # allowed color type @@ -167,6 +167,21 @@ const BASES = (identity = nothing, ln = "ℯ", log2 = "2", log10 = "10") #! format: on +function default_size!(; + width::Union{Integer,Nothing} = nothing, + height::Union{Integer,Nothing} = nothing, +) + @assert (width === nothing) ⊻ (height === nothing) + if width !== nothing + DEFAULT_WIDTH[] = width + DEFAULT_HEIGHT[] = round(Int, width / 2ASPECT_RATIO) + elseif height !== nothing + DEFAULT_HEIGHT[] = height + DEFAULT_WIDTH[] = round(Int, height * 2ASPECT_RATIO) + end + return +end + function char_marker(marker::MarkerType)::Char if marker isa Symbol get(MARKERS, marker, MARKERS[:circle]) diff --git a/src/description.jl b/src/description.jl index a430e749..670c726c 100644 --- a/src/description.jl +++ b/src/description.jl @@ -69,7 +69,7 @@ const DESCRIPTION = ( const Z_DESCRIPTION = (:zlabel, :zlim, :colorbar, :colormap, :colorbar_lim, :colorbar_border) -const DEFAULT_KWARGS = ( +const DEFAULT_KW = ( # does not have to stay ordered :name, :title, @@ -110,7 +110,7 @@ default_with_type(s::Symbol) = ( ) """ - keywords([extra]; default = DEFAULT_KWARGS, add = (), exclude = DEFAULT_EXCLUDED, remove = ()) + keywords([extra]; default = DEFAULT_KW, add = (), exclude = DEFAULT_EXCLUDED, remove = ()) Adds default keywords to a function signature, in a docstring. @@ -123,20 +123,20 @@ Adds default keywords to a function signature, in a docstring. """ function keywords( extra::NamedTuple = NamedTuple(); - default::Tuple = DEFAULT_KWARGS, + default::Tuple = DEFAULT_KW, add::Tuple = (), exclude::Tuple = DEFAULT_EXCLUDED, remove::Tuple = (), ) all_kw = (; KEYWORDS..., extra...) - candidates = keys(extra) ∪ filter(x -> x ∈ add ∪ default, DEFAULT_KWARGS) + candidates = keys(extra) ∪ filter(x -> x ∈ add ∪ default, DEFAULT_KW) kw = filter(x -> x ∉ setdiff(exclude ∪ remove, add), candidates) @assert allunique(kw) # extra check join((k isa Symbol ? "$k = $(all_kw[k] |> repr)" : k for k in kw), ", ") end """ - arguments([desc]; default = DEFAULT_KWARGS, add = (), exclude = DEFAULT_EXCLUDED, remove = ()) + arguments([desc]; default = DEFAULT_KW, add = (), exclude = DEFAULT_EXCLUDED, remove = ()) Defines arguments for docstring genreration. @@ -149,7 +149,7 @@ Defines arguments for docstring genreration. """ function arguments( desc::NamedTuple = NamedTuple(); - default::Tuple = DEFAULT_KWARGS, + default::Tuple = DEFAULT_KW, add::Tuple = (), exclude::Tuple = DEFAULT_EXCLUDED, remove::Tuple = (), diff --git a/src/interface/barplot.jl b/src/interface/barplot.jl index 096cd504..c433edca 100644 --- a/src/interface/barplot.jl +++ b/src/interface/barplot.jl @@ -1,5 +1,5 @@ """ - barplot(text, heights; kwargs...) + barplot(text, heights; kw...) # Description @@ -15,7 +15,7 @@ as the heights of the bars. barplot(text, heights; $(keywords((border = :barplot, color = :green,), remove = (:xlim, :ylim, :xscale, :yscale, :height, :grid), add = (:symbols,)))) - barplot(dict; kwargs...) + barplot(dict; kw...) # Arguments diff --git a/src/interface/boxplot.jl b/src/interface/boxplot.jl index 4a838063..a3cd8185 100644 --- a/src/interface/boxplot.jl +++ b/src/interface/boxplot.jl @@ -1,5 +1,5 @@ """ - boxplot(data; kwargs...) + boxplot(data; kw...) # Description @@ -20,7 +20,7 @@ used as the labels. boxplot([text], data; $(keywords((border = :corners, color = :green,), remove = (:ylim, :height, :grid))) - boxplot(dict; kwargs...) + boxplot(dict; kw...) # Arguments @@ -102,7 +102,7 @@ function boxplot( end """ - boxplot!(plot, data; kwargs...) + boxplot!(plot, data; kw...) Mutating variant of `boxplot`, in which the first parameter (`plot`) specifies the existing plot to draw on. diff --git a/src/interface/contourplot.jl b/src/interface/contourplot.jl index 6bb55ae8..e2b3506c 100644 --- a/src/interface/contourplot.jl +++ b/src/interface/contourplot.jl @@ -1,5 +1,5 @@ """ - contourplot(x, y, A; kwargs...) + contourplot(x, y, A; kw...) Draws a contour plot on a new canvas. @@ -102,7 +102,7 @@ function contourplot!( end """ - contourplot(A; kwargs...) + contourplot(A; kw...) Draws a contour plot of matrix `A` along axis `x` and `y` on a new canvas. @@ -120,5 +120,5 @@ axes(A, 1) │ │ y │ │ x ``` """ -contourplot(A::AbstractMatrix; kwargs...) = - contourplot(axes(A, 2) |> collect, axes(A, 1) |> reverse |> collect, A; kwargs...) +contourplot(A::AbstractMatrix; kw...) = + contourplot(axes(A, 2) |> collect, axes(A, 1) |> reverse |> collect, A; kw...) diff --git a/src/interface/densityplot.jl b/src/interface/densityplot.jl index 72c719fd..59180bf2 100644 --- a/src/interface/densityplot.jl +++ b/src/interface/densityplot.jl @@ -1,5 +1,5 @@ """ - densityplot(x, y; kwargs...) + densityplot(x, y; kw...) # Description diff --git a/src/interface/heatmap.jl b/src/interface/heatmap.jl index 1a16d554..2e9b473e 100644 --- a/src/interface/heatmap.jl +++ b/src/interface/heatmap.jl @@ -1,5 +1,5 @@ """ - heatmap(A; kwargs...) + heatmap(A; kw...) # Description diff --git a/src/interface/histogram.jl b/src/interface/histogram.jl index 84a232d3..2f7cabd8 100644 --- a/src/interface/histogram.jl +++ b/src/interface/histogram.jl @@ -1,5 +1,5 @@ """ - histogram(data; kwargs...) + histogram(data; kw...) # Description @@ -12,7 +12,7 @@ Note internally that `histogram` is a simply wrapper for # Usage - histogram(x; nbins, closed = :left, kwargs...) + histogram(x; nbins, closed = :left, kw...) histogram(hist; $(keywords((border = :barplot, color = :green,), remove = (:ylim, :yscale, :height, :grid), add = (:symbols,))) diff --git a/src/interface/lineplot.jl b/src/interface/lineplot.jl index 6b1d3611..1fdb0364 100644 --- a/src/interface/lineplot.jl +++ b/src/interface/lineplot.jl @@ -1,5 +1,5 @@ """ - lineplot(x, y; kwargs...) + lineplot(x, y; kw...) # Description @@ -13,7 +13,7 @@ This means that the two vectors must be of the same length and ordering. lineplot([x], y; $(keywords(; add = (:canvas,))) - lineplot(fun, [start], [stop]; kwargs...) + lineplot(fun, [start], [stop]; kw...) # Arguments diff --git a/src/interface/scatterplot.jl b/src/interface/scatterplot.jl index a623f345..683c2864 100644 --- a/src/interface/scatterplot.jl +++ b/src/interface/scatterplot.jl @@ -1,5 +1,5 @@ """ - scatterplot(x, y; kwargs...) + scatterplot(x, y; kw...) # Description diff --git a/src/interface/spy.jl b/src/interface/spy.jl index 49bea724..8c6c599c 100644 --- a/src/interface/spy.jl +++ b/src/interface/spy.jl @@ -1,5 +1,5 @@ """ - spy(A; kwargs...) + spy(A; kw...) # Description @@ -69,9 +69,9 @@ julia> spy(sprandn(50, 120, .05)) [`BrailleCanvas`](@ref), [`BlockCanvas`](@ref), [`AsciiCanvas`](@ref), [`DotCanvas`](@ref) """ -function spy(A::AbstractMatrix; kwargs...) +function spy(A::AbstractMatrix; kw...) rows, cols, vals = _strict_non_zeros(_findnz(A)...) - if get(kwargs, :show_zeros, false) + if get(kw, :show_zeros, false) I = CartesianIndex.(zip(rows, cols)) # non zeros mask = trues(size(A)) mask[I] .= false @@ -79,7 +79,7 @@ function spy(A::AbstractMatrix; kwargs...) rows, cols = getindex.(Z, 1), getindex.(Z, 2) vals = zeros(eltype(vals), length(rows)) end - spy(size(A)..., rows, cols, vals; kwargs...) + spy(size(A)..., rows, cols, vals; kw...) end function _strict_non_zeros(rows, cols, vals) diff --git a/src/interface/stairs.jl b/src/interface/stairs.jl index 8edc5775..7638e1f7 100644 --- a/src/interface/stairs.jl +++ b/src/interface/stairs.jl @@ -1,5 +1,5 @@ """ - stairs(x, y; kwargs...) + stairs(x, y; kw...) # Description diff --git a/src/plot.jl b/src/plot.jl index 5425b443..54853c08 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -1,5 +1,5 @@ """ - Plot(graphics; kwargs...) + Plot(graphics; kw...) # Description @@ -60,9 +60,9 @@ mutable struct Plot{T<:GraphicsArea} colors_right::Dict{Int,JuliaColorType} decorations::Dict{Symbol,String} colors_deco::Dict{Symbol,JuliaColorType} - show_labels::Bool + labels::Bool colormap::Any - show_colorbar::Bool + colorbar::Bool colorbar_border::Symbol colorbar_lim::Tuple{Number,Number} autocolor::Int @@ -134,8 +134,8 @@ function Plot( zlabel::AbstractString = KEYWORDS.zlabel, xscale::Union{Symbol,Function} = KEYWORDS.xscale, yscale::Union{Symbol,Function} = KEYWORDS.yscale, - width::Int = KEYWORDS.width, - height::Int = KEYWORDS.height, + width::Union{Int,Nothing} = nothing, + height::Union{Int,Nothing} = nothing, border::Symbol = KEYWORDS.border, compact::Bool = KEYWORDS.compact, blend::Bool = KEYWORDS.blend, @@ -156,6 +156,10 @@ function Plot( length(xlim) == length(ylim) == 2 || throw(ArgumentError("xlim and ylim must be tuples or vectors of length 2")) length(X) == length(Y) || throw(DimensionMismatch("X and Y must have same length")) + + width === nothing && (width = DEFAULT_WIDTH[]) + height === nothing && (height = DEFAULT_HEIGHT[]) + (visible = width > 0) && (width = max(width, min_width)) height = max(height, min_height) @@ -427,7 +431,7 @@ function annotate!( end """ - annotate!(plot, x, y, text; kwargs...) + annotate!(plot, x, y, text; kw...) # Description @@ -476,25 +480,25 @@ function annotate!( y::Number, text::Union{Char,AbstractString}; color = :normal, - kwargs..., + kw..., ) color = color == :auto ? next_color!(plot) : color - annotate!(plot.graphics, x, y, text, color; kwargs...) + annotate!(plot.graphics, x, y, text, color; kw...) plot end -function lines!(plot::Plot{<:Canvas}, args...; kwargs...) - lines!(plot.graphics, args...; kwargs...) +function lines!(plot::Plot{<:Canvas}, args...; kw...) + lines!(plot.graphics, args...; kw...) plot end -function pixel!(plot::Plot{<:Canvas}, args...; kwargs...) - pixel!(plot.graphics, args...; kwargs...) +function pixel!(plot::Plot{<:Canvas}, args...; kw...) + pixel!(plot.graphics, args...; kw...) plot end -function points!(plot::Plot{<:Canvas}, args...; kwargs...) - points!(plot.graphics, args...; kwargs...) +function points!(plot::Plot{<:Canvas}, args...; kw...) + points!(plot.graphics, args...; kw...) plot end @@ -549,7 +553,7 @@ function print_labels( right_pad::AbstractString, blank::Char, ) - p.show_labels || return + p.labels || return lloc = Symbol(mloc, :l) rloc = Symbol(mloc, :r) left_str = get(p.decorations, lloc, "") @@ -591,17 +595,17 @@ function Base.show(io::IO, p::Plot) bmap = BORDERMAP[p.border === :none && c isa BrailleCanvas ? :bnone : p.border] # get length of largest strings to the left and right - max_len_l = if p.show_labels && !isempty(p.labels_left) + max_len_l = if p.labels && !isempty(p.labels_left) maximum([length(_nocolor_string(l)) for l in values(p.labels_left)]) else 0 end - max_len_r = if p.show_labels && !isempty(p.labels_right) + max_len_r = if p.labels && !isempty(p.labels_right) maximum([length(_nocolor_string(l)) for l in values(p.labels_right)]) else 0 end - if !p.compact && p.show_labels && p.ylabel != "" + if !p.compact && p.labels && p.ylabel != "" max_len_l += length(p.ylabel) + 1 end @@ -611,7 +615,7 @@ function Base.show(io::IO, p::Plot) # padding-string from left to border plot_padding = repeat(🗷, p.padding) - if p.show_colorbar + if p.colorbar min_z, max_z = p.colorbar_lim min_z_str = string(isinteger(min_z) ? min_z : float_round_log10(min_z)) max_z_str = string(isinteger(max_z) ? max_z : float_round_log10(max_z)) @@ -659,7 +663,7 @@ function Base.show(io::IO, p::Plot) for row in 1:nrows(c) # print left annotations print(io, repeat(🗷, p.margin)) - if p.show_labels + if p.labels # Current labels to left and right of the row and their length left_str = get(p.labels_left, row, "") left_col = get(p.colors_left, row, :light_black) @@ -691,13 +695,13 @@ function Base.show(io::IO, p::Plot) # print right label and padding print_color(:light_black, io, bmap[:r]) end - if p.show_labels + if p.labels print(io, plot_padding) print_color(right_col, io, right_str) print(io, repeat(🗷, max_len_r - right_len)) end # print colorbar - if p.show_colorbar + if p.colorbar print(io, plot_padding) printcolorbarrow( io, @@ -719,7 +723,7 @@ function Base.show(io::IO, p::Plot) # draw bottom border and bottom labels c.visible && print_border(io, :b, border_length, '\n' * border_left_pad, border_right_pad, bmap) - if p.show_labels + if p.labels print_labels( io, :b, diff --git a/test/tst_common.jl b/test/tst_common.jl index 4a59356a..f4fbf5c1 100644 --- a/test/tst_common.jl +++ b/test/tst_common.jl @@ -63,6 +63,26 @@ end end end +@testset "colors" begin + @test UnicodePlots.julia_color(100) == 100 + @test UnicodePlots.julia_color(:red) == :red + @test UnicodePlots.julia_color(nothing) == :normal + @test UnicodePlots.julia_color((0, 135, 95)) == 29 + + @test UnicodePlots.colormap_callback(UnicodePlots.COLOR_MAP_DATA |> keys |> first) isa + Function + @test UnicodePlots.colormap_callback(() -> nothing) isa Function + @test UnicodePlots.colormap_callback([1, 2, 3]) isa Function + @test UnicodePlots.colormap_callback(nothing) === nothing + + # en.wikipedia.org/wiki/ANSI_escape_code#8-bit + @test UnicodePlots.rgb2ansi((0, 0, 0)) == 016 # black + @test UnicodePlots.rgb2ansi((1, 0, 0)) == 196 # red + @test UnicodePlots.rgb2ansi((0, 1, 0)) == 046 # green + @test UnicodePlots.rgb2ansi((0, 0, 1)) == 021 # blue + @test UnicodePlots.rgb2ansi((1, 1, 1)) == 231 # white +end + @testset "miscellaneous" begin @test UnicodePlots.char_marker('a') === 'a' @test UnicodePlots.char_marker("a") === 'a' @@ -89,26 +109,16 @@ end @test UnicodePlots.out_stream_width(nothing) == 40 @test UnicodePlots.out_stream_height(nothing) == 15 - @test UnicodePlots.julia_color(100) == 100 - @test UnicodePlots.julia_color(:red) == :red - @test UnicodePlots.julia_color(nothing) == :normal - @test UnicodePlots.julia_color((0, 135, 95)) == 29 - @test UnicodePlots.superscript("-10") == "⁻¹⁰" @test UnicodePlots.superscript("+2") == "⁺²" - @test UnicodePlots.colormap_callback(UnicodePlots.COLOR_MAP_DATA |> keys |> first) isa - Function - @test UnicodePlots.colormap_callback(() -> nothing) isa Function - @test UnicodePlots.colormap_callback([1, 2, 3]) isa Function - @test UnicodePlots.colormap_callback(nothing) === nothing - - # en.wikipedia.org/wiki/ANSI_escape_code#8-bit - @test UnicodePlots.rgb2ansi((0, 0, 0)) == 016 # black - @test UnicodePlots.rgb2ansi((1, 0, 0)) == 196 # red - @test UnicodePlots.rgb2ansi((0, 1, 0)) == 046 # green - @test UnicodePlots.rgb2ansi((0, 0, 1)) == 021 # blue - @test UnicodePlots.rgb2ansi((1, 1, 1)) == 231 # white + @test_throws AssertionError UnicodePlots.default_size!(width = 8, height = 8) + UnicodePlots.default_size!(width = 64) + @test UnicodePlots.DEFAULT_WIDTH[] == 64 + @test UnicodePlots.DEFAULT_HEIGHT[] == 24 + UnicodePlots.default_size!(height = 15) + @test UnicodePlots.DEFAULT_WIDTH[] == 40 + @test UnicodePlots.DEFAULT_HEIGHT[] == 15 end @testset "docs" begin