From 7b6aa7d47279a3dbe4cbd781f9e0d2b564efffd3 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Thu, 26 Feb 2026 21:22:03 +0000 Subject: [PATCH] Do not let _opt_ in a sub-methods use Char. This reduces multiple-recompilations. --- src/common_options.jl | 22 +++++++++++----------- src/geodesy/psvelo.jl | 4 ++-- src/grdvector.jl | 2 +- src/pscoast.jl | 4 ++-- src/pshistogram.jl | 2 +- src/psmask.jl | 2 +- src/psrose.jl | 2 +- src/pssolar.jl | 2 +- src/pstext.jl | 2 +- src/pswiggle.jl | 2 +- src/psxy.jl | 4 ++-- src/seis/psmeca.jl | 4 ++-- src/windbarbs/windbarbs.jl | 2 +- test/test_common_opts.jl | 6 +++--- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/common_options.jl b/src/common_options.jl index a4de9f1fe..7973ab5e5 100644 --- a/src/common_options.jl +++ b/src/common_options.jl @@ -1838,7 +1838,7 @@ function parse_params(d::Dict, cmd::String; del::Bool=true)::String end # --------------------------------------------------------------------------------------------------- -function add_opt_pen(d::Dict, symbs::Union{Nothing, VMs}; opt::String="", del::Bool=true)::String +function add_opt_pen(d::Dict, @nospecialize(symbs::Union{Nothing, VMs}); opt::String="", del::Bool=true)::String # Build a pen option. Input can be either a full hard core string or spread in lw (or lt), lc, ls, etc or a tuple (SHOW_KWARGS[]) && return print_kwarg_opts(symbs, "NamedTuple | Tuple | String | Number") # Just print the options @@ -2308,9 +2308,9 @@ end # --------------------------------------------------------------------------------------------------- function add_opt(d::Dict, cmd::String, opt::String, mapa::NamedTuple)::String # Thin wrapper: convert NT to Dict to compile _add_opt only once - _add_opt_1(d, cmd, opt, nt2dict(mapa)) + _add_opt_1(d, cmd, opt, Dict{Symbol,Any}(nt2dict(mapa))) end -function _add_opt_1(d::Dict, cmd::String, opt::String, mapa::Dict)::String +function _add_opt_1(d::Dict, cmd::String, opt::String, mapa::Dict{Symbol,Any})::String cmd_::String = "" for k in keys(mapa) ((val_ = find_in_dict(d, [k], false)[1]) === nothing) && continue # This mapa key was not used @@ -2339,11 +2339,11 @@ end function add_opt(d::Dict, cmd::String, opt::String, symbs::VMs, mapa; grow_mat=nothing, del::Bool=true, expand::Bool=false, expand_str::Bool=false)::String # Thin wrapper: convert NamedTuple mapa to Dict to avoid recompilation for each distinct NT type mapa_is_nt = isa(mapa, NamedTuple) - _mapa = mapa_is_nt ? nt2dict(mapa) : mapa - _add_opt_2(d, cmd, opt, symbs, _mapa; grow_mat=grow_mat, del=del, expand=expand, expand_str=expand_str, mapa_is_nt=mapa_is_nt) + _mapa = mapa_is_nt ? Dict{Symbol,Any}(nt2dict(mapa)) : (mapa === nothing ? Dict{Symbol,Any}() : mapa) + _add_opt_2(d, cmd, opt, vec(symbs), _mapa, grow_mat, del, expand, expand_str, mapa_is_nt) end -function _add_opt_2(d::Dict, cmd::String, opt::String, symbs::VMs, mapa; grow_mat=nothing, del::Bool=true, expand::Bool=false, expand_str::Bool=false, mapa_is_nt::Bool=false)::String +function _add_opt_2(d::Dict, cmd::String, opt::String, symbs::Vector{Symbol}, @nospecialize(mapa), @nospecialize(grow_mat), del::Bool, expand::Bool, expand_str::Bool, mapa_is_nt::Bool)::String # Scan the D Dict for SYMBS keys and if found create the new option OPT and append it to CMD # If DEL == false we do not remove the found key. # 'grow_mat=mat', is a special case to append to a matrix (can't realy be done in Julia) @@ -2598,7 +2598,7 @@ function _add_opt_3(d::Dict, cmd::String, opt::String, symbs::VMs, need_symb::Sy opt = string(opt,val) to_slot = false end - cmd = _add_opt_2(d, cmd, opt, symbs, nt_opts_d; mapa_is_nt=true) + cmd = _add_opt_2(d, cmd, opt, vec(symbs), nt_opts_d, nothing, true, false, false, true) elseif (isa(val, Array{<:Real}) || isa(val, GDtype) || isa(val, GMTcpt) || typeof(val) <: AbstractRange) if (typeof(val) <: AbstractRange) val = collect(val) end cmd = string(cmd, " -", opt) @@ -2717,18 +2717,18 @@ function add_opt_fill(d::Dict, opt::String="") add_opt_fill(d, [collect(keys(d))[1]], opt) # Use ONLY when len(d) == 1 end add_opt_fill(d::Dict, symbs::VMs, opt="") = add_opt_fill("", d, symbs, opt) -function add_opt_fill(cmd::String, d::Dict, symbs::VMs, opt="", del::Bool=true)::String +function add_opt_fill(cmd::String, d::Dict, @nospecialize(symbs::VMs), opt::String="", del::Bool=true)::String # Deal with the area fill attributes option. Normally, -G (SHOW_KWARGS[]) && return print_kwarg_opts(symbs, "NamedTuple | Tuple | Array | String | Number") ((val = find_in_dict(d, symbs, del)[1]) === nothing) && return cmd isa(val, AbstractDict) && (val = Base.invokelatest(dict2nt, val)) (val == true && symbs == [:G :fill]) && (val="#0072BD") # Let fill=true mean a default color (val == "" && symbs == [:G :fill]) && return cmd # Let fill="" mean no fill (handy for proggy reasons) - (opt != "") && (opt = string(" -", opt)) + (opt !== "") && (opt = string(" -", opt)) return add_opt_fill(val, cmd, opt) end -function add_opt_fill(@nospecialize(val), cmd::String="", opt="")::String +function add_opt_fill(@nospecialize(val), cmd::String="", opt::String="")::String # This method can be called directy with VAL as a NT or a string if (isa(val, Tuple) && length(val) == 2 && (isa(val[1], Tuple) || isa(val[1], NamedTuple))) # wiggle, for example, may want to repeat the call to fill (-G). Then we expect a Tuple of -G's @@ -2737,7 +2737,7 @@ function add_opt_fill(@nospecialize(val), cmd::String="", opt="")::String elseif (isvector(val) && length(val) == 2 && isa(val[1], String)) # The above case works but may be uggly sometimes; e.g. fill=(("red+p",), ("blue+n",)) # So accept also a vector of strings and do not try to interpret its contents. Ex: fill(["red+p", "blue+n"] - (opt != "" && !startswith(opt, " -")) && (opt = string(" -", opt)) + (opt !== "" && !startswith(opt, " -")) && (opt = string(" -", opt)) cmd = cmd * opt * val[1]::String * opt * val[2]::String elseif (isa(val, NamedTuple)) d2::Dict = nt2dict(val) diff --git a/src/geodesy/psvelo.jl b/src/geodesy/psvelo.jl index 4a6c2133d..044760157 100644 --- a/src/geodesy/psvelo.jl +++ b/src/geodesy/psvelo.jl @@ -27,8 +27,8 @@ function velo(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol, Any}) cmd = (isa(val, String)) ? cmd * " -A" * val : cmd * " -A" * vector_attrib(val) end - cmd = add_opt_fill(cmd, d, [:E :fill_wedges :uncertaintyfill], 'E') - cmd = add_opt_fill(cmd, d, [:G :fill :fill_symbols], 'G') + cmd = add_opt_fill(cmd, d, [:E :fill_wedges :uncertaintyfill], "E") + cmd = add_opt_fill(cmd, d, [:G :fill :fill_symbols], "G") cmd = parse_these_opts(cmd, d, [[:D :sigma_scale], [:L :outlines], [:N :no_clip :noclip]]) if (haskey(d, :Se) || haskey(d, :velo_NE)) symbs = [:Se :vel_NE] diff --git a/src/grdvector.jl b/src/grdvector.jl index 94c0129fa..8538f6abd 100644 --- a/src/grdvector.jl +++ b/src/grdvector.jl @@ -147,7 +147,7 @@ function grdvector_helper(arg1, arg2, K::Bool, O::Bool, d::Dict{Symbol, Any}) defNorm, defHead = @sprintf("%.6g%s", as/2+1e-7, km_u), "yes" opt_Q = !isbarbs ? parse_Q_grdvec(d, [:Q :vec :vector :arrow], defLen, defHead, defNorm) : "" - !occursin(" -G", opt_Q) && (cmd = add_opt_fill(cmd, d, [:G :fill], 'G')) # If fill not passed in arrow, try from regular option + !occursin(" -G", opt_Q) && (cmd = add_opt_fill(cmd, d, [:G :fill], "G")) # If fill not passed in arrow, try from regular option cmd *= add_opt_pen(d, [:W :pen], opt="W") (!occursin(" -C", cmd) && !occursin(" -W", cmd) && !occursin(" -G", opt_Q)) && (cmd *= " -W0.5") # If still nothing, set -W. (opt_Q != "") && (cmd *= opt_Q) diff --git a/src/pscoast.jl b/src/pscoast.jl index 45b544f90..35f2f3f54 100644 --- a/src/pscoast.jl +++ b/src/pscoast.jl @@ -152,8 +152,8 @@ function coast_parser(first::Bool, clip::String, O::Bool, d::Dict{Symbol, Any}) cmd = parse_Td(d, cmd) cmd = parse_Tm(d, cmd) cmd = parse_L(d, cmd) - cmd = add_opt_fill(cmd, d, [:G :land], 'G') - cmd = add_opt_fill(cmd, d, [:S :water :ocean], 'S') + cmd = add_opt_fill(cmd, d, [:G :land], "G") + cmd = add_opt_fill(cmd, d, [:S :water :ocean], "S") if (clip !== "") if (clip == "land") cmd *= " -Gc" diff --git a/src/pshistogram.jl b/src/pshistogram.jl index d8ee2618a..49aaf698b 100644 --- a/src/pshistogram.jl +++ b/src/pshistogram.jl @@ -120,7 +120,7 @@ function histogram_helper(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol,A cmd = parse_common_opts(d, cmd, [:UVXY :JZ :c :e :f :p :t :w :params :margin]; first=!O)[1] cmd = parse_these_opts(cmd, d, [[:A :horizontal], [:F :center], [:Q :cumulative], [:S :stairs]]) nofill = ((symb = is_in_dict(d, [:G :fill])) !== nothing && d[symb] == "") ? true : false # To know if no fill was asked - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") cmd = add_opt(d, cmd, "D", [:D :annot :annotate :counts], (beneath = "_+b", font = "+f", offset = "+o", vertical = "_+r")) cmd = parse_INW_coast(d, [[:N :distribution :normal]], cmd, "N") (SHOW_KWARGS[]) && print_kwarg_opts(symbs, "NamedTuple | Tuple | Dict | String") diff --git a/src/psmask.jl b/src/psmask.jl index 0f15bb113..6477223dd 100644 --- a/src/psmask.jl +++ b/src/psmask.jl @@ -89,7 +89,7 @@ function mask(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol, Any}) return isinv ? mat2img(collect(arg1.z .<= thres), arg1) : mat2img(collect(arg1.z .>= thres), arg1) end - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") cmd = gmt_proggy * cmd ((r = check_dbg_print_cmd(d, cmd)) !== nothing) && return r prep_and_call_finish_PS_module(d, cmd, "", K, O, true, arg1) diff --git a/src/psrose.jl b/src/psrose.jl index 20de0f8d6..882fe59b8 100644 --- a/src/psrose.jl +++ b/src/psrose.jl @@ -109,7 +109,7 @@ function rose_helper(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol, Any}) cmd = add_opt(d, cmd, "E", [:E :vectors]) cmd, arg1, arg2, = add_opt_cpt(d, cmd, CPTaliases, 'C', N_args, arg1, arg2) - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") cmd *= opt_pen(d, 'W', [:W :pen]) _cmd = [gmt_proggy * cmd] diff --git a/src/pssolar.jl b/src/pssolar.jl index 05ce92394..3a5d00d4c 100644 --- a/src/pssolar.jl +++ b/src/pssolar.jl @@ -54,7 +54,7 @@ function solar(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol, Any}) cmd, = parse_common_opts(d, cmd, [:bo :c :h :o :p :t :UVXY :params]; first=!O) cmd = parse_these_opts(cmd, d, [[:C :format], [:M :dump], [:N :invert]]) - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") cmd = add_opt(d, cmd, "I", [:I :sun], (pos="",date="+d",TZ="+z")) cmd = add_opt(d, cmd, "T", [:T :terminators], (term="",date="+d",TZ="+z")) cmd *= opt_pen(d, 'W', [:W :pen]) diff --git a/src/pstext.jl b/src/pstext.jl index a72689ade..88362c7e4 100644 --- a/src/pstext.jl +++ b/src/pstext.jl @@ -119,7 +119,7 @@ function _text(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol,Any}) cmd = add_opt(d, cmd, "D", [:D :offset], (away=("j", nothing, 1), corners=("J", nothing, 1), shift="", line=("+v",add_opt_pen))) opt_F = add_opt(d, "", "F", [:F :attrib], (angle="+a", Angle="+A", font=("+f", font), justify="+j", region_justify="+c", header="_+h", label="_+l", rec_number="_+r", text="+t", zvalues="_+z"); expand=true) - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") contains(cmd, " -G") && (CTRL.pocket_B[3] = ".") # Signal gmt() that it needs to restart because the fill f the API cmd *= add_opt_pen(d, [:W :pen], opt="W") diff --git a/src/pswiggle.jl b/src/pswiggle.jl index ae50728ef..b1e7937eb 100644 --- a/src/pswiggle.jl +++ b/src/pswiggle.jl @@ -82,7 +82,7 @@ function wiggle_helper(cmd0::String, arg1, O::Bool, K::Bool, d::Dict{Symbol, Any (map=("g", arg2str, 1), outside=("J", arg2str, 1), inside=("j", arg2str, 1), norm=("n", arg2str, 1), paper=("x", arg2str, 1), anchor=("", arg2str, 2), width=("+w", arg2str), justify="+j", label_left="_+al", labels="+l", label="+l", offset=("+o", arg2str)), 'j') cmd *= opt_pen(d, 'T', [:T :track]) cmd *= opt_pen(d, 'W', [:W :pen]) - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") _cmd = [gmt_proggy * cmd] _cmd = frame_opaque(_cmd, gmt_proggy, opt_B, opt_R, opt_J) # No -t in frame diff --git a/src/psxy.jl b/src/psxy.jl index 9eaa64faf..be24f1ea0 100644 --- a/src/psxy.jl +++ b/src/psxy.jl @@ -358,9 +358,9 @@ end function parse_plot_G_L(d::Dict{Symbol, Any}, cmd::String, g_bar_fill::Vector{String}, is_ternary::Bool) opt_G::String = "" if (isempty(g_bar_fill)) # Otherwise bar fill colors are dealt with somewhere else - ((opt_G = add_opt_fill("", d, [:G :fill], 'G')) != "") && (cmd *= opt_G) # Also keep track if -G was set + ((opt_G = add_opt_fill("", d, [:G :fill], "G")) != "") && (cmd *= opt_G) # Also keep track if -G was set end - opt_Gsymb::String = add_opt_fill("", d, [:G :mc :markercolor :markerfacecolor :MarkerFaceColor], 'G') # Filling of symbols + opt_Gsymb::String = add_opt_fill("", d, [:G :mc :markercolor :markerfacecolor :MarkerFaceColor], "G") # Filling of symbols (opt_Gsymb == " -G") && (opt_Gsymb *= "black") # Means something like 'mc=true' was used, but we need a color opt_L::String = "" diff --git a/src/seis/psmeca.jl b/src/seis/psmeca.jl index 31897a81f..d1a06b732 100644 --- a/src/seis/psmeca.jl +++ b/src/seis/psmeca.jl @@ -146,7 +146,7 @@ function common_mecas(cmd0, arg1, d, proggy, first, K, O) cmd = add_opt(d, cmd, "D", [:D :offset], (dist_is_geog="+c", fill=("+g", add_opt_fill), offset="+o", pen=("+p", add_opt_pen), size="+s")) end - cmd = add_opt_fill(cmd, d, [:E :fill_extensive :extensionfill], 'E') + cmd = add_opt_fill(cmd, d, [:E :fill_extensive :extensionfill], "E") cmd = parse_these_opts(cmd, d, [[:H :scale], [:I :intens :intensity], [:L :pen_outline], [:M :same_size :samesize], [:N :no_clip :noclip], [:T :nodal]]) cmd = parse_these_opts(cmd, d, [[:Fa :PT_axes], [:Fo :psvelo]]) @@ -156,7 +156,7 @@ function common_mecas(cmd0, arg1, d, proggy, first, K, O) cmd *= add_opt_pen(d, [:Fp :P_axis_pen], opt="Fp") cmd *= add_opt_pen(d, [:Ft :T_axis_pen], opt="Ft") cmd *= add_opt_pen(d, [:Fz :zero_trace], opt="Fz") - cmd = add_opt_fill(cmd, d, [:G :fill :compressionfill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill :compressionfill], "G") #(occursin("coupe", proggy)) && (cmd = add_opt(d, cmd, "Q", [:Q])) # If file name sent in, read it and compute a tight -R if it was not provided diff --git a/src/windbarbs/windbarbs.jl b/src/windbarbs/windbarbs.jl index da6dcd707..a3c2dd835 100644 --- a/src/windbarbs/windbarbs.jl +++ b/src/windbarbs/windbarbs.jl @@ -36,7 +36,7 @@ function windbarbs(arg1, O::Bool, K::Bool, d::Dict{Symbol, Any}) cmd = parse_these_opts(cmd, d, [[:D :offset], [:I :intens], [:N :no_clip :noclip]]) cmd = add_opt(d, cmd, "Q", [:Q :barbs], (len=("", arg2str, 1), length=("", arg2str, 1), angle="+a", fill=("+g", add_opt_fill), pen=("+p", add_opt_pen), just="+j", speed="+s", width="+w", uv="+z", cartesian="+z")) cmd *= opt_pen(d, 'W', [:W :pen]) - cmd = add_opt_fill(cmd, d, [:G :fill], 'G') + cmd = add_opt_fill(cmd, d, [:G :fill], "G") cmd, arg1, arg2, = add_opt_cpt(d, cmd, CPTaliases, 'C', 1, arg1) (!isa(arg1, GDtype) && !isa(arg1, Matrix{<:Real})) && (arg1 = tabletypes2ds(arg1)) diff --git a/test/test_common_opts.jl b/test/test_common_opts.jl index e8afb1c56..9523906f3 100644 --- a/test/test_common_opts.jl +++ b/test/test_common_opts.jl @@ -109,12 +109,12 @@ @test GMT.add_opt(Dict{Symbol,Any}(:L => "pen"), "", "L", [:L], (pen="_+p",)) == " -L+p" @test GMT.add_opt_1char("", Dict{Symbol,Any}(:N=>"abc"), [[:N :geod2aux]]) == " -Na" @test GMT.add_opt_1char("", Dict{Symbol,Any}(:N => ("abc", "sw", "x"), :Q=>"datum"), [[:N :geod2aux], [:Q :list]]) == " -Nasx -Qd" - r = GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>(inv_pattern=12,fg="white",bg=[1,2,3], dpi=10) ), [:G :fill], 'G'); + r = GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>(inv_pattern=12,fg="white",bg=[1,2,3], dpi=10) ), [:G :fill], "G"); @test r == " -GP12+b1/2/3+fwhite+r10" - @test GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>:red), [:G :fill], 'G') == " -Gred" + @test GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>:red), [:G :fill], "G") == " -Gred" @test GMT.add_opt_fill(["red+p", "blue+n"], "", "G") == " -Gred+p -Gblue+n" @test GMT.add_opt_fill((("red+p",), ("blue+n",)), "", " -G") == " -Gred+p -Gblue+n" - @test_throws ErrorException("For 'fill' option as a NamedTuple, you MUST provide a 'patern' member") GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>(inv_pat=12,fg="white")), [:G], 'G') + @test_throws ErrorException("For 'fill' option as a NamedTuple, you MUST provide a 'patern' member") GMT.add_opt_fill("", Dict{Symbol,Any}(:G=>(inv_pat=12,fg="white")), [:G], "G") d = Dict{Symbol,Any}(:offset=>5, :bezier=>true, :cline=>"", :ctext=>true, :pen=>("10p",:red,:dashed)); @test GMT.add_opt_pen(d, [:W :pen], opt="W") == " -W10p,red,-+cl+cf+s+o5" d = Dict{Symbol,Any}(:W=>(offset=5, bezier=true, cline="", ctext=true, pen=("10p",:red,:dashed), arrow=(length=0.1,)));