Ihor Radchenko writes:

> Looks reasonable in general. Of course, we will also need to document
> the new attribute.

Here is the modified patch (with your suggestions, including the `rx' code)
and the documentation of the new attribute.

-- 
Juan Manuel Macías

https://juanmanuelmacias.com

https://lunotipia.juanmanuelmacias.com

https://gnutas.juanmanuelmacias.com

>From 463e4a984b0ccc9bc1fdde699cb5cfed1ac59613 Mon Sep 17 00:00:00 2001
From: Juan Manuel Macias <maciasch...@posteo.net>
Date: Mon, 14 Aug 2023 21:48:58 +0200
Subject: [PATCH] lisp/ox-latex.el: add the `:literal' attribute to verse
 block.

* (org-latex-verse-block): now the treatment of blank lines is
consistent with the syntax of the LaTeX `verse' environment, and the
one provided by the `verse' package. If the `:literal' attribute is
used, the content is not exported within a `verse' environment, but
as-is, preserving horizontal spaces, line breaks, and blank lines.
The rx code has been suggested by Ihor Radchenko, to improve
readability.

* doc/org-manual.org (Verse blocks in LaTeX export): the new feature
is documented.
---
 doc/org-manual.org | 12 ++++++++++--
 lisp/ox-latex.el   | 43 ++++++++++++++++++++++++++++++-------------
 2 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index e59efc417..b640bbc7c 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -14425,8 +14425,8 @@ The LaTeX export backend converts horizontal rules by the specified
 #+cindex: verse blocks, in @LaTeX{} export
 #+cindex: @samp{ATTR_LATEX}, keyword
 
-The LaTeX export backend accepts four attributes for verse blocks:
-=:lines=, =:center=, =:versewidth= and =:latexcode=.  The three first
+The LaTeX export backend accepts five attributes for verse blocks:
+=:lines=, =:center=, =:versewidth=, =:latexcode= and =:literal=.  The three first
 require the external LaTeX package =verse.sty=, which is an extension
 of the standard LaTeX environment.
 
@@ -14440,6 +14440,14 @@ of the standard LaTeX environment.
   verse.
 - =:latexcode= :: It accepts any arbitrary LaTeX code that can be
   included within a LaTeX =verse= environment.
+- =:literal= :: With value t, the block is not exported to a =verse=
+  environment; instead, the content is exported as-is, preserving all
+  white lines as =\vspace{\baselineskip}=.  Note that in the =verse=
+  environment, one or more blank lines between stanzas are exported as
+  a single blank line, and any blank lines before or after the content
+  are removed.  If the =verse= package is loaded, the vertical spacing
+  between stanzas can be controlled by the length =\stanzaskip= (see
+  https://www.ctan.org/pkg/verse).
 
 A complete example with Shakespeare's first sonnet:
 
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 31cad1dc4..fcf22f87d 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -4116,32 +4116,49 @@ contextual information."
   (let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
          (latcode (org-export-read-attribute :attr_latex verse-block :latexcode))
          (cent (org-export-read-attribute :attr_latex verse-block :center))
-         (attr (concat
-	        (if cent "[\\versewidth]" "")
-	        (if lin (format "\n\\poemlines{%s}" lin) "")
-	        (if latcode (format "\n%s" latcode) "")))
+         (lit (org-export-read-attribute :attr_latex verse-block :literal))
+         (attr (if (not lit)
+		   (concat
+		    (if cent "[\\versewidth]" "")
+		    (if lin (format "\n\\poemlines{%s}" lin) "")
+		    (if latcode (format "\n%s" latcode) ""))
+		 ""))
          (versewidth (org-export-read-attribute :attr_latex verse-block :versewidth))
-         (vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" versewidth) ""))
-         (linreset (if lin "\n\\poemlines{0}" "")))
+         (vwidth (if (and versewidth (not lit)) (format "\\settowidth{\\versewidth}{%s}\n" versewidth) ""))
+         (linreset (if (and lin (not lit)) "\n\\poemlines{0}" "")))
     (concat
      (org-latex--wrap-label
       verse-block
       ;; In a verse environment, add a line break to each newline
       ;; character and change each white space at beginning of a line
-      ;; into a space of 1 em.  Also change each blank line with
-      ;; a vertical space of 1 em.
-      (format "%s\\begin{verse}%s\n%s\\end{verse}%s"
+      ;; into a normal space, calculated with `\fontdimen2\font'.
+      ;; One or more blank lines between lines are exported as a
+      ;; single blank line.  If the `:literal' attribute is used,
+      ;; CONTENTS is exported as is, with no environment, preserving
+      ;; line breaks and vertical and horizontal spaces.
+      (format (if (not lit)
+		  "%s\\begin{verse}%s\n%s\\end{verse}%s"
+		"%s%s\n%s%s")
 	      vwidth
 	      attr
 	      (replace-regexp-in-string
-	       "^[ \t]+" (lambda (m) (format "\\hspace*{%dem}" (length m)))
+	       "^[ \t]+" (lambda (m) (format "\\hspace*{%d\\fontdimen2\\font}" (length m)))
 	       (replace-regexp-in-string
-                (concat "^[ \t]*" (regexp-quote org-latex-line-break-safe) "$")
-	        "\\vspace*{1em}"
+                (if (not lit)
+		    (rx-to-string
+                     `(seq (group ,org-latex-line-break-safe "\n")
+		           (1+ (group line-start (0+ space) ,org-latex-line-break-safe "\n"))))
+		  (concat "^[ \t]*" (regexp-quote org-latex-line-break-safe) "$"))
+	        (if (not lit)
+		    (if lin "\\\\!\n\n" "\n\n")
+		  "\\vspace*{\\baselineskip}")
 	        (replace-regexp-in-string
 	         "\\([ \t]*\\\\\\\\\\)?[ \t]*\n"
                  (concat org-latex-line-break-safe "\n")
-	         contents nil t)
+	         (if (not lit)
+		     (concat (org-trim contents t) "\n")
+		   contents)
+                 nil t)
                 nil t)
                nil t)
               linreset)
-- 
2.41.0

Reply via email to