From 3351502b8bd2a4061f447975361729f73f03d5fc Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Fri, 13 Dec 2024 15:19:02 +0100 Subject: [PATCH 1/3] Override default variable latexification with custom [latex = ...] field --- src/latexify_recipes.jl | 29 +++++++++++++++++++++-------- src/variable.jl | 6 +++--- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/latexify_recipes.jl b/src/latexify_recipes.jl index 58dcdd3b4..a557c1ea9 100644 --- a/src/latexify_recipes.jl +++ b/src/latexify_recipes.jl @@ -52,8 +52,12 @@ recipe(n) = latexify_derivatives(cleanup_exprs(_toexpr(n))) cdot --> false fmt --> FancyNumberFormatter(5) index --> :subscript - snakecase --> true - safescripts --> true + + # Prevent Latexify.jl from interfering if variable has custom [latex = ...] field (it should escape its own underscores etc.) + custom = unwrap(n) isa Symbolic && hasmetadata(unwrap(n), VariableLatex) + snakecase --> !custom + safescripts --> !custom + function_name --> false return recipe(n) end @@ -191,13 +195,22 @@ function _toexpr(O) return frac_expr end end - if issym(O) - sym = string(nameof(O)) - sym = replace(sym, NAMESPACE_SEPARATOR => ".") - if length(sym) > 1 - sym = string("\\mathtt{", sym, "}") + if issym(O) + name = string(nameof(O)) + + # If given, use custom [latex = ...] option for the variable name (does not affect subsystem names) + # Otherwise fall back to a sane default, where multi-letter variables are rendered with a fixed width font + name = replace(name, NAMESPACE_SEPARATOR => '.') + if hasmetadata(O, VariableLatex) + seppos = findlast('.', name) + sysname = isnothing(seppos) ? "" : "\\mathtt{$(name[begin:seppos])}" # always \mathtt system names (consistent with multi-letter vars) + varname = getmetadata(O, VariableLatex) # override + name = string(sysname, varname) + elseif length(name) > 1 + name = "\\mathtt{$name}" end - return Symbol(sym) + + return Symbol(name) end !iscall(O) && return O diff --git a/src/variable.jl b/src/variable.jl index 489a072de..c4b60f82c 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -17,6 +17,7 @@ const IndexMap = Dict{Char,Char}( abstract type AbstractVariableMetadata end struct VariableDefaultValue <: AbstractVariableMetadata end struct VariableSource <: AbstractVariableMetadata end +struct VariableLatex <: AbstractVariableMetadata end function recurse_and_apply(f, x) if symtype(x) <: AbstractArray @@ -252,9 +253,8 @@ function construct_vars(macroname, v, type, call_args, val, prop, transform, isr lhs, :($lhs = $rhs) end -function option_to_metadata_type(::Val{opt}) where {opt} - throw(Base.Meta.ParseError("unknown property type $opt")) -end +option_to_metadata_type(::Val{:latex}) = VariableLatex +option_to_metadata_type(::Val{opt}) where {opt} = throw(Base.Meta.ParseError("unknown property type $opt")) function setprops_expr(expr, props, macroname, varname) expr = :($setmetadata($expr, $VariableSource, ($(Meta.quot(macroname)), $varname,))) From 4e3f23325380295de7e85afce3e39254e0d20bda Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Fri, 13 Dec 2024 15:19:24 +0100 Subject: [PATCH 2/3] Preserve latex variable metadata for callable variables --- src/latexify_recipes.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/latexify_recipes.jl b/src/latexify_recipes.jl index a557c1ea9..c76b5eec0 100644 --- a/src/latexify_recipes.jl +++ b/src/latexify_recipes.jl @@ -244,6 +244,10 @@ function _toexpr(O) end return Expr(:call, :_integral, _toexpr(lower), _toexpr(upper), vars, _toexpr(integrand)) elseif symtype(op) <: FnType + # Preserve latex metadata field when `x(t)` becomes `x` + if hasmetadata(O, VariableLatex) + op = setmetadata(op, VariableLatex, getmetadata(O, VariableLatex)) + end isempty(args) && return nameof(op) return Expr(:call, _toexpr(op), _toexpr(args)...) elseif op === getindex && symtype(args[1]) <: AbstractArray From 82d9eacba3ce2e9126682a33595994c392eee3ee Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Fri, 13 Dec 2024 15:19:37 +0100 Subject: [PATCH 3/3] Add tests --- test/latexify.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/latexify.jl b/test/latexify.jl index 5d80cab52..17a47afe9 100644 --- a/test/latexify.jl +++ b/test/latexify.jl @@ -62,3 +62,7 @@ Dy = Differential(y) @test_reference "latexify_refs/indices2.txt" latexify(h[10,10], index=:bracket) @test !occursin("identity", latexify(Num(π))) # issue #1254 + +@variables t +@test String(latexify(only(@variables sys₊x123(t)[1:3])[1]; env=:raw)) == raw"\mathtt{sys.x123}\left( t \right)_{1}" # x without subscript +@test String(latexify(only(@variables sys₊x123(t)[1:3] [latex = raw"x_{123}"])[1]; env=:raw)) == raw"\mathtt{sys.}x_{{123}}\left( t \right)_{1}" # x with subscript