~jonsterling/forester-devel

[Breaking] Don't add spurious whitespace in TeX-like rendering v2 APPLIED

Jon Sterling: 1
 [Breaking] Don't add spurious whitespace in TeX-like rendering

 3 files changed, 32 insertions(+), 35 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~jonsterling/forester-devel/patches/53295/mbox | git am -3
Learn more about email & git

[PATCH v2] [Breaking] Don't add spurious whitespace in TeX-like rendering Export this patch

We rename the badly named Render_verbatim to Render_TeX_like. More
importantly, the whitespace behaviour of Render_TeX_like.render is
changed as follows.

Previously, spaces would be inserted between every Forester node. This
results in incorrect rendering in some cases, including when we want to
emit \tag{...} to LaTeX. Now we do not add whitespace automatically between
nodes; however, when we encounter an uninterpeted control sequence
(which should be emitted as a TeX control sequence), we add spacing
depending on whether it is a *control word* or a *control symbol* ---
following the discussion in Chapter 3 of the TeXBook. According to
op.cit., spaces are ignored after control words and not ignored after
control symbols.

> When a space comes after a control word (an all-letter control
sequence), it is ignored by TeX. [...] But when a space comes after a
control symbol, it is truly a space.

I believe this behaviour is now as close to desirable as we can get.

This patch pertains to the discussion here:
https://lists.sr.ht/~jonsterling/forester-discuss/%3CB051B670-D3A9-4317-AFA1-675405EB171F@jonmsterling.com%3E

Signed-off-by: Jon Sterling <jon@jonmsterling.com>
---
 ...{Render_verbatim.ml => Render_TeX_like.ml} | 57 +++++++++----------
 ...ender_verbatim.mli => Render_TeX_like.mli} |  2 +-
 lib/render/Render_dream.ml                    |  8 +--
 3 files changed, 32 insertions(+), 35 deletions(-)
 rename lib/render/{Render_verbatim.ml => Render_TeX_like.ml} (52%)
 rename lib/render/{Render_verbatim.mli => Render_TeX_like.mli} (75%)

diff --git a/lib/render/Render_verbatim.ml b/lib/render/Render_TeX_like.ml
similarity index 52%
rename from lib/render/Render_verbatim.ml
rename to lib/render/Render_TeX_like.ml
index e47b9b1..a922a62 100644
--- a/lib/render/Render_verbatim.ml
+++ b/lib/render/Render_TeX_like.ml
@@ -1,7 +1,6 @@
open Prelude
open Core


module Printer =
struct
  module P0 =
@@ -19,43 +18,41 @@ end

type cfg = {tex : bool}

(* TeXBook Ch. 3 *)
type cs_type = Word | Symbol

let cs_symbol_rx = Str.regexp {|^[^A-Za-z]$|}

let cs_type name =
  if Str.string_match cs_symbol_rx name 0 then
    Symbol
  else
    Word

let cs_separator =
  function
  | Word -> Printer.space
  | Symbol -> Printer.nil

let rec render_node ~cfg : Sem.node Range.located -> Printer.t =
  fun located ->
  match located.value with
  | Sem.Text txt | Sem.Verbatim txt ->
    Printer.text txt
  | Sem.Math (_, xs) ->
    render ~cfg xs
  | Sem.Math (mode, xs) ->
    render ~cfg xs;
  | Sem.Xml_tag (_, _, body) ->
    render ~cfg body
  | Sem.If_tex (x , y) ->
    if cfg.tex then render ~cfg x else render ~cfg y
  | Sem.Unresolved name ->
    render_unresolved ~cfg name []
  | node ->
    Reporter.fatalf ?loc:located.loc Type_error "Render_verbatim: cannot render this kind of object"


and render_unresolved ~cfg name body =
  Printer.seq
    [Printer.text "\\";
     Printer.text name;
     render_arg ~cfg Braces body]

and render ~cfg ?(sep = Printer.space) xs =
  Printer.iter ~sep (render_node ~cfg) xs

and render_arg ~cfg delim (arg : Sem.t) : Printer.t =
  match arg with
  | [] -> Printer.nil
  | _ ->
    let l, r =
      match delim with
      | Braces -> "{", "}"
      | Squares -> "[", "]"
      | Parens -> "(", ")"
    in
    let sep = cs_separator @@ cs_type name in
    Printer.seq
      [Printer.text l;
       render ~cfg arg;
       Printer.text r]
      [Printer.text "\\";
       Printer.text name;
       sep]
  | node ->
    Reporter.fatalf ?loc:located.loc Type_error "Render_TeX_like: cannot render this kind of object"

and render ~cfg =
  Printer.iter (render_node ~cfg)
diff --git a/lib/render/Render_verbatim.mli b/lib/render/Render_TeX_like.mli
similarity index 75%
rename from lib/render/Render_verbatim.mli
rename to lib/render/Render_TeX_like.mli
index 44e713e..fd6f3ba 100644
--- a/lib/render/Render_verbatim.mli
+++ b/lib/render/Render_TeX_like.mli
@@ -10,4 +10,4 @@ end

type cfg = {tex : bool}

val render : cfg:cfg -> ?sep:Printer.t -> Sem.t -> Printer.t
val render : cfg:cfg -> Sem.t -> Printer.t
diff --git a/lib/render/Render_dream.ml b/lib/render/Render_dream.ml
index cbd57e7..85490c3 100644
--- a/lib/render/Render_dream.ml
+++ b/lib/render/Render_dream.ml
@@ -101,9 +101,9 @@ let rec render_located (located : Sem.node Range.located) =

  | Sem.Math (mode, body) ->
    let rendered =
      let module TP = Render_verbatim.Printer in
      let module TP = Render_TeX_like.Printer in
      Str.global_replace (Str.regexp "\n") " " @@
      TP.contents @@ Render_verbatim.render ~cfg:{tex = false} body
      TP.contents @@ Render_TeX_like.render ~cfg:{tex = false} body
    in
    F.tex [
      match mode with
@@ -189,8 +189,8 @@ let rec render_located (located : Sem.node Range.located) =

  | Sem.Embed_tex {preamble; source} ->
    let as_tex x =
      Render_verbatim.Printer.contents @@
      Render_verbatim.render ~cfg:{tex = true} x
      Render_TeX_like.Printer.contents @@
      Render_TeX_like.render ~cfg:{tex = true} x
    in
    let preamble = as_tex preamble in
    let source = as_tex source in
--
2.45.0