From 3d768575ac906036f0fcf68186865379be2e0f57 Mon Sep 17 00:00:00 2001 From: Jakob Peters Date: Wed, 16 Oct 2024 10:32:48 -0700 Subject: [PATCH] Preserve non-printing characters in `show(::IO, ::TypstString)` --- NEWS.md | 2 ++ docs/source/references/internals.md | 1 + src/Strings.jl | 50 ++++++++++++++++++++++++++--- test/interface/TestStrings.jl | 4 ++- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index f7b78c6..d3bc33a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,5 +5,7 @@ ### Bug Fixes +- If a `TypstString` contains any characters that satisfy `!isprint`, +`show(::IO, ::TypstString)` now prints a format that preserves those characters. - Delete redundant `show_typst` documentation for `String` - Account for a [Typst bug with single-letter strings in `math` mode](https://github.com/typst/typst/issues/274#issue-1639854848) diff --git a/docs/source/references/internals.md b/docs/source/references/internals.md index 6444a6c..d712e3f 100644 --- a/docs/source/references/internals.md +++ b/docs/source/references/internals.md @@ -29,6 +29,7 @@ Typstry.Strings.show_array Typstry.Strings.show_parameters Typstry.Strings.show_raw Typstry.Strings.show_vector +Typstry.Strings.escape ``` ### Dates.jl diff --git a/src/Strings.jl b/src/Strings.jl index 46406fa..299f860 100644 --- a/src/Strings.jl +++ b/src/Strings.jl @@ -16,7 +16,6 @@ Typstry.Strings module Strings import Base: IOBuffer, ==, codeunit, isvalid, iterate, ncodeunits, pointer, repr, show -using Base: escape_raw_string using .Docs: HTML, Text using .Iterators: Stateful using .Meta: isexpr, parse @@ -183,7 +182,7 @@ macro typst_str(s::String) end end - current ≤ final && push!(args, s[current:final]) + current > final || push!(args, s[current:final]) :(TypstString(TypstText($_s))) end @@ -475,6 +474,23 @@ show_vector(io, x) = math_mode(io, x) do io, x print(io, "\n", _indent ^ _depth, ")") end +""" + escape(io, n) + +Print `\\` to `io` `n` times. + +# Examples + +```jldoctest +julia> julia> Typstry.Strings.escape(stdout, 2) +\\ +``` +""" +escape(io, n) = + for _ in 1:n + print(io, '\\') + end + ## Dates.jl """ @@ -919,9 +935,33 @@ typst"a" ``` """ function show(io::IO, ts::TypstString) - print(io, "typst") - enclose((io, text) -> escape_raw_string(io, replace(text, - r"(\\+)\(" => s"\1\1(")), io, ts.text, "\"") + text = ts.text + + if all(isprint, text) + escapes = 0 + + print(io, "typst\"") + + for c in text + if c == '\\' escapes += 1 + else + if c == '\"' escape(io, escapes + 1) + elseif c == '(' escape(io, escapes) + end + + escapes = 0 + end + + print(io, c) + end + + escape(io, escapes) + print(io, "\"") + else + print(io, TypstString, "(", TypstText, "(") + show(io, text) + print(io, "))") + end end """ diff --git a/test/interface/TestStrings.jl b/test/interface/TestStrings.jl index 4f3c19a..57ded77 100644 --- a/test/interface/TestStrings.jl +++ b/test/interface/TestStrings.jl @@ -29,7 +29,9 @@ show_typst(io, ::X) = print(io, io[:x]::Int) const pairs = [ typst"" => "" - typst"x" => "x" + typst"\\" => "\\" # \ + typst"\ " => "\\ " + typst"\\ " => "\\\\ " typst"(x)" => "(x)" typst"𝒂(x)𝒃" => "𝒂(x)𝒃" typst"𝒂𝒃(x)𝒄𝒅" => "𝒂𝒃(x)𝒄𝒅"