Hello R-devel,
The idea to use Unicode when rendering equations in plain text was
mentioned a few times in the past, most recently by Sebastian Meyer in
a Bugzilla comment. I would like to share the patch to use Unicode
characters for approximately the same symbols that used to be
substituted in the old HTML equation renderer.
Why do it? Familiar Greek letters would be more consistent with HTML
and PDF documentation.
What are the downsides?
- Some symbols don't look as good on a terminal as they do in a
document when typeset with a mathematical font. Depending on the
font used in the terminal, \pi ? ? may look very similar to n. (For
example, the popular Terminus font uses exactly the same glyph for
'?', U+03C0 GREEK SMALL LETTER PI, and '?', U+043F CYRILLIC
SMALL
LETTER PE.) \infty ? '?' and \dots ? '?' are too small and
narrow
when rendered at the same width as normal monospace letters. '?',
'?'/'?', and '?'/'?' may look too unexpected
compared to 'sqrt',
'sum', and 'prod'.
- There may be accessibility implications. Would a screen reader
struggle upon seeing a '?' instead of 'prod'? Hopefully the
screen
reader users can enjoy the more accessible HTML documentation now,
and there is an option to disable the Unicode symbols.
- The patch is only mildly tested by reading ?stats::TDist and
?pracma::expint and making sure that for (pkg in
rownames(installed.packages())) for (Rd in tools::Rd_db(pkg))
tools::Rd2txt(Rd) doesn't fail, with or without a UTF-8-capable
locale.
Thanks to Sebastian Meyer for the initial comments!
Index: src/library/tools/R/Rd2HTML.R
==================================================================---
src/library/tools/R/Rd2HTML.R (revision 90047)
+++ src/library/tools/R/Rd2HTML.R (working copy)
@@ -109,14 +109,13 @@
x <- fsub('"\\{"', '"{"', x)
## http://htmlhelp.com/reference/html40/entities/symbols.html
if(inEqn) {
- x <-
psub("\\\\(Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|sum|prod)",
"&\\1;", x)
- x <- psub("\\\\(dots|ldots)", "…", x)
- x <- psub("\\\\(left|right)", "", x)
- x <- psub("\\\\leq?", "≤", x)
- x <- psub("\\\\geq?", "≥", x)
- x <- psub("\\\\neq?", "≠", x)
- x <- fsub("\\infty", "∞", x)
- x <- fsub("\\sqrt", "√", x)
+ rx <- paste0("\\\\(",
+ paste(math_replacements[,"name"], collapse =
"|"),
+ ")(?![a-zA-Z])")
+ m <- gregexec(rx, x, perl = TRUE)
+ ii <- lapply(regmatches(x, m),
+ function(mm) if (length(mm)) match(mm[2,],
math_replacements[,"name"]))
+ regmatches(x, gregexpr(rx, x, perl = TRUE)) <- lapply(ii,
function(i) math_replacements[i, "html"])
}
x
}
Index: src/library/tools/R/Rd2txt.R
==================================================================---
src/library/tools/R/Rd2txt.R (revision 90047)
+++ src/library/tools/R/Rd2txt.R (working copy)
@@ -55,6 +55,71 @@
}
})
+math_replacements <- matrix(c(
+ "Alpha", "\u391", "Alpha",
"Α",
+ "Beta", "\u392", "Beta",
"Β",
+ "Gamma", "\u393", "Gamma",
"Γ",
+ "Delta", "\u394", "Delta",
"Δ",
+ "Epsilon", "\u395", "Epsilon",
"Ε",
+ "Zeta", "\u396", "Zeta",
"Ζ",
+ "Eta", "\u397", "Eta",
"Η",
+ "Theta", "\u398", "Theta",
"Θ",
+ "Iota", "\u399", "Iota",
"Ι",
+ "Kappa", "\u39a", "Kappa",
"Κ",
+ "Lambda", "\u39b", "Lambda",
"Λ",
+ "Mu", "\u39c", "Mu",
"Μ",
+ "Nu", "\u39d", "Nu",
"Ν",
+ "Xi", "\u39e", "Xi",
"Ξ",
+ "Omicron", "\u39f", "Omicron",
"Ο",
+ "Pi", "\u3a0", "Pi",
"Π",
+ "Rho", "\u3a1", "Rho",
"Ρ",
+ "Sigma", "\u3a3", "Sigma",
"Σ",
+ "Tau", "\u3a4", "Tau",
"Τ",
+ "Upsilon", "\u3a5", "Upsilon",
"Υ",
+ "Phi", "\u3a6", "Phi",
"Φ",
+ "Chi", "\u3a7", "Chi",
"Χ",
+ "Psi", "\u3a8", "Psi",
"Ψ",
+ "Omega", "\u3a9", "Omega",
"Ω",
+ "alpha", "\u3b1", "alpha",
"α",
+ "beta", "\u3b2", "beta",
"β",
+ "gamma", "\u3b3", "gamma",
"γ",
+ "delta", "\u3b4", "delta",
"δ",
+ "epsilon", "\u3b5", "epsilon",
"ε",
+ "zeta", "\u3b6", "zeta",
"ζ",
+ "eta", "\u3b7", "eta",
"η",
+ "theta", "\u3b8", "theta",
"θ",
+ "iota", "\u3b9", "iota",
"ι",
+ "kappa", "\u3ba", "kappa",
"κ",
+ "lambda", "\u3bb", "lambda",
"λ",
+ "mu", "\u3bc", "mu",
"μ",
+ "nu", "\u3bd", "nu",
"ν",
+ "xi", "\u3be", "xi",
"ξ",
+ "omicron", "\u3bf", "omicron",
"ο",
+ "pi", "\u3c0", "pi",
"π",
+ "rho", "\u3c1", "rho",
"ρ",
+ "sigma", "\u3c3", "sigma",
"σ",
+ "tau", "\u3c4", "tau",
"τ",
+ "upsilon", "\u3c5", "upsilon",
"υ",
+ "phi", "\u3c6", "phi",
"φ",
+ "chi", "\u3c7", "chi",
"χ",
+ "psi", "\u3c8", "psi",
"ψ",
+ "omega", "\u3c9", "omega",
"ω",
+ "sum", "\u2211", "sum",
"∑",
+ "prod", "\u220f", "prod",
"∏",
+ "sqrt", "\u221a", "sqrt",
"√",
+ "dots", "\u2026", "...",
"…",
+ "ldots", "\u2026", "...",
"…",
+ "le", "\u2264", "<=",
"≤",
+ "leq", "\u2264", "<=",
"≤",
+ "ge", "\u2265", ">=",
"≥",
+ "geq", "\u2265", ">=",
"≥",
+ "ne", "\u2260", "!=",
"≠",
+ "neq", "\u2260", "!=",
"≠",
+ "infty", "\u221e", "Inf",
"∞",
+ "left", "", "", "",
+ "right", "", "", ""
+), ncol = 4, byrow = TRUE, dimnames = list(NULL, c("name",
"fancy", "ascii", "html")))
+
transformMethod <- function(i, blocks, Rdfile) {
editblock <- function(block, newtext)
list(tagged(newtext,
@@ -529,13 +594,14 @@
}
txt_eqn <- function(x) {
- x <-
psub("\\\\(Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|sum|prod|sqrt)",
"\\1", x)
- x <- psub("\\\\(dots|ldots)", "...", x)
- x <- psub("\\\\(left|right)", "", x)
- x <- psub("\\\\leq?", "<=", x)
- x <- psub("\\\\geq?", ">=", x)
- x <- psub("\\\\neq?", "!=", x)
- x <- fsub("\\infty", "Inf", x)
+ replacement <- if (unicode_symbols) "fancy" else
"ascii"
+ rx <- paste0("\\\\(",
+ paste(math_replacements[,"name"], collapse =
"|"),
+ ")(?![a-zA-Z])")
+ m <- gregexec(rx, x, perl = TRUE)
+ ii <- lapply(regmatches(x, m),
+ function(mm) if (length(mm)) match(mm[2,],
math_replacements[,"name"]))
+ regmatches(x, gregexpr(rx, x, perl = TRUE)) <- lapply(ii,
function(i) math_replacements[i, replacement])
## FIXME: are these needed?
x <- psub("\\\\(bold|strong|emph|var)\\{([^}]*)\\}",
"\\2", x)
x <- psub("\\\\(code|samp)\\{([^}]*)\\}",
"'\\2'", x)
--
Best regards,
Ivan
>>>>> Ivan Krylov via R-devel writes:I like your patch :-) Perhaps do this conditionally on Rd2txt_options()$unicode_symbols set to TRUE? Best -k> Hello R-devel, > The idea to use Unicode when rendering equations in plain text was > mentioned a few times in the past, most recently by Sebastian Meyer in > a Bugzilla comment. I would like to share the patch to use Unicode > characters for approximately the same symbols that used to be > substituted in the old HTML equation renderer.> Why do it? Familiar Greek letters would be more consistent with HTML > and PDF documentation.> What are the downsides?> - Some symbols don't look as good on a terminal as they do in a > document when typeset with a mathematical font. Depending on the > font used in the terminal, \pi ? ? may look very similar to n. (For > example, the popular Terminus font uses exactly the same glyph for > '?', U+03C0 GREEK SMALL LETTER PI, and '?', U+043F CYRILLIC SMALL > LETTER PE.) \infty ? '?' and \dots ? '?' are too small and narrow > when rendered at the same width as normal monospace letters. '?', > '?'/'?', and '?'/'?' may look too unexpected compared to 'sqrt', > 'sum', and 'prod'.> - There may be accessibility implications. Would a screen reader > struggle upon seeing a '?' instead of 'prod'? Hopefully the screen > reader users can enjoy the more accessible HTML documentation now, > and there is an option to disable the Unicode symbols.> - The patch is only mildly tested by reading ?stats::TDist and > ?pracma::expint and making sure that for (pkg in > rownames(installed.packages())) for (Rd in tools::Rd_db(pkg)) > tools::Rd2txt(Rd) doesn't fail, with or without a UTF-8-capable > locale.> Thanks to Sebastian Meyer for the initial comments!> Index: src/library/tools/R/Rd2HTML.R > ==================================================================> --- src/library/tools/R/Rd2HTML.R (revision 90047) > +++ src/library/tools/R/Rd2HTML.R (working copy) > @@ -109,14 +109,13 @@ > x <- fsub('"\\{"', '"{"', x) > ## http://htmlhelp.com/reference/html40/entities/symbols.html > if(inEqn) { > - x <- psub("\\\\(Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|sum|prod)", "&\\1;", x) > - x <- psub("\\\\(dots|ldots)", "…", x) > - x <- psub("\\\\(left|right)", "", x) > - x <- psub("\\\\leq?", "≤", x) > - x <- psub("\\\\geq?", "≥", x) > - x <- psub("\\\\neq?", "≠", x) > - x <- fsub("\\infty", "∞", x) > - x <- fsub("\\sqrt", "√", x) > + rx <- paste0("\\\\(", > + paste(math_replacements[,"name"], collapse = "|"), > + ")(?![a-zA-Z])") > + m <- gregexec(rx, x, perl = TRUE) > + ii <- lapply(regmatches(x, m), > + function(mm) if (length(mm)) match(mm[2,], math_replacements[,"name"])) > + regmatches(x, gregexpr(rx, x, perl = TRUE)) <- lapply(ii, function(i) math_replacements[i, "html"]) > } > x > } > Index: src/library/tools/R/Rd2txt.R > ==================================================================> --- src/library/tools/R/Rd2txt.R (revision 90047) > +++ src/library/tools/R/Rd2txt.R (working copy) > @@ -55,6 +55,71 @@ > } > })> +math_replacements <- matrix(c( > + "Alpha", "\u391", "Alpha", "Α", > + "Beta", "\u392", "Beta", "Β", > + "Gamma", "\u393", "Gamma", "Γ", > + "Delta", "\u394", "Delta", "Δ", > + "Epsilon", "\u395", "Epsilon", "Ε", > + "Zeta", "\u396", "Zeta", "Ζ", > + "Eta", "\u397", "Eta", "Η", > + "Theta", "\u398", "Theta", "Θ", > + "Iota", "\u399", "Iota", "Ι", > + "Kappa", "\u39a", "Kappa", "Κ", > + "Lambda", "\u39b", "Lambda", "Λ", > + "Mu", "\u39c", "Mu", "Μ", > + "Nu", "\u39d", "Nu", "Ν", > + "Xi", "\u39e", "Xi", "Ξ", > + "Omicron", "\u39f", "Omicron", "Ο", > + "Pi", "\u3a0", "Pi", "Π", > + "Rho", "\u3a1", "Rho", "Ρ", > + "Sigma", "\u3a3", "Sigma", "Σ", > + "Tau", "\u3a4", "Tau", "Τ", > + "Upsilon", "\u3a5", "Upsilon", "Υ", > + "Phi", "\u3a6", "Phi", "Φ", > + "Chi", "\u3a7", "Chi", "Χ", > + "Psi", "\u3a8", "Psi", "Ψ", > + "Omega", "\u3a9", "Omega", "Ω", > + "alpha", "\u3b1", "alpha", "α", > + "beta", "\u3b2", "beta", "β", > + "gamma", "\u3b3", "gamma", "γ", > + "delta", "\u3b4", "delta", "δ", > + "epsilon", "\u3b5", "epsilon", "ε", > + "zeta", "\u3b6", "zeta", "ζ", > + "eta", "\u3b7", "eta", "η", > + "theta", "\u3b8", "theta", "θ", > + "iota", "\u3b9", "iota", "ι", > + "kappa", "\u3ba", "kappa", "κ", > + "lambda", "\u3bb", "lambda", "λ", > + "mu", "\u3bc", "mu", "μ", > + "nu", "\u3bd", "nu", "ν", > + "xi", "\u3be", "xi", "ξ", > + "omicron", "\u3bf", "omicron", "ο", > + "pi", "\u3c0", "pi", "π", > + "rho", "\u3c1", "rho", "ρ", > + "sigma", "\u3c3", "sigma", "σ", > + "tau", "\u3c4", "tau", "τ", > + "upsilon", "\u3c5", "upsilon", "υ", > + "phi", "\u3c6", "phi", "φ", > + "chi", "\u3c7", "chi", "χ", > + "psi", "\u3c8", "psi", "ψ", > + "omega", "\u3c9", "omega", "ω", > + "sum", "\u2211", "sum", "∑", > + "prod", "\u220f", "prod", "∏", > + "sqrt", "\u221a", "sqrt", "√", > + "dots", "\u2026", "...", "…", > + "ldots", "\u2026", "...", "…", > + "le", "\u2264", "<=", "≤", > + "leq", "\u2264", "<=", "≤", > + "ge", "\u2265", ">=", "≥", > + "geq", "\u2265", ">=", "≥", > + "ne", "\u2260", "!=", "≠", > + "neq", "\u2260", "!=", "≠", > + "infty", "\u221e", "Inf", "∞", > + "left", "", "", "", > + "right", "", "", "" > +), ncol = 4, byrow = TRUE, dimnames = list(NULL, c("name", "fancy", "ascii", "html"))) > + > transformMethod <- function(i, blocks, Rdfile) { > editblock <- function(block, newtext) > list(tagged(newtext, > @@ -529,13 +594,14 @@ > }> txt_eqn <- function(x) { > - x <- psub("\\\\(Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|sum|prod|sqrt)", "\\1", x) > - x <- psub("\\\\(dots|ldots)", "...", x) > - x <- psub("\\\\(left|right)", "", x) > - x <- psub("\\\\leq?", "<=", x) > - x <- psub("\\\\geq?", ">=", x) > - x <- psub("\\\\neq?", "!=", x) > - x <- fsub("\\infty", "Inf", x) > + replacement <- if (unicode_symbols) "fancy" else "ascii" > + rx <- paste0("\\\\(", > + paste(math_replacements[,"name"], collapse = "|"), > + ")(?![a-zA-Z])") > + m <- gregexec(rx, x, perl = TRUE) > + ii <- lapply(regmatches(x, m), > + function(mm) if (length(mm)) match(mm[2,], math_replacements[,"name"])) > + regmatches(x, gregexpr(rx, x, perl = TRUE)) <- lapply(ii, function(i) math_replacements[i, replacement]) > ## FIXME: are these needed? > x <- psub("\\\\(bold|strong|emph|var)\\{([^}]*)\\}", "\\2", x) > x <- psub("\\\\(code|samp)\\{([^}]*)\\}", "'\\2'", x)> -- > Best regards, > Ivan> ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel