alhassy / org-special-block-extras

A number of new custom blocks and link types for Emacs' Org-mode ^_^

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unwanted newlines in LaTeX export

Perangelot opened this issue · comments

Consider the following custom block:

#+begin_blockquote :citekey key :pages pages
*This* is a /try/.
#+end_blockquote

which was defined like this

(org-defblock blockquote nil (citekey "" pages "") "This is just an attempt."
(format (if (equal backend 'latex)
"\\blockcquote[%s]{%s}{%s}" nil)
pages citekey contents))

What it should print:

\blockcquote[pages]{key}{\textbf{This} is a \emph{try}.}

What it does print:

\blockcquote[pages]{key}{
\textbf{This} is a \emph{try}.

}

The problem is that, due to the added whitespace, the custom block just shown produces the latter output. If this is exported to LaTeX, instead of "**This** is a _try_", you get " **This** is a _try_ ". regexp-replacement does not work here, adding % only for the first line. Any ideas what to do?

Note that org-defblock XXX gives you a function org--XXX that you can play with ---see https://github.com/alhassy/org-special-block-extras/blob/master/org-special-block-extras.el#L647. So in this case, you can press C-h o RET blockquote and see the exact name, and docstring, of the resulting function.

Then you can experiment with this function to see what it is generating; e.g.,

(org--blockquote 'latex  "*This* is a /try/.")

;; Press   C-u C-x C-e   at the end of the closing parens above to get the following:

"#+begin_export latex 
\\blockcquote[]{}{
#+end_export
*This* is a /try/.
#+begin_export latex
}
#+end_export"

This ugly mess is what Org "sees" before producing LaTeX 😨

  • I suspect the extra newlines you're seeing come from the superflous #+begin_export latex ...at the end.
  • I don't recall where, but somewhere in these notes, this issue of newlines is mentioned.
  • This seems related to issues #8 and #24.

Hope this helps.

Thanks for your answer. After digging in the code for hours, I have found out two things:

  1. The reason why there were extra #+end_export and #+begin_export lines is due to a line which explicitly adds them; see #28.
  2. After changing this piece of code, with the same example as above, you will now get the raw string if you call it via org--blockcquote:
#+begin_export latex 
\blockcquote[]{}{*This* is a /try/}
#+end_export
  1. Nonetheless, if you export this to LaTeX, you will get
\blockcquote[]{}{*This* is a /try/
}
  1. The last newline is produced because of this line:
(setq blk-contents (buffer-substring-no-properties body-start (line-beginning-position)))

An easy fix is to just go one character back: (1- (line-beginning-position))

(setq blk-contents (buffer-substring-no-properties body-start (1- (line-beginning-position))))

Unfortunately, if you remove (2), you won't get the the org-export-machinery you need. "This" stays "This" and won't export to "\emph{This}".

This is everything I could find out. It's really important for me to get this feature going, so if there's any chance you can utilize this information, I would be more than happy if you could do so!

After hours of searching, I have finally found the culprit. Your export machinery makes an unncessary move. Let us take

#+begin_blockquote :citekey key :pages pages
*This* is a /try/.
#+end_blockquote

as an example again. The function org-defblock---support-block-type takes the name, the documentation string, content of the code-block as well as the main-argument's name and value and other keywords as an input (leaving out that html feature for a second). In our case, it would look like this:

name: blockcquote
doc-string: "This is just an attempt."
main-arg name: "key"
main-arg: key
kwd: (:pages "pages")
body:  "*This* is a /try/."

It then uses two-functions: : org-export and org-parse. org-parse wraps the body in an export block depending on the backend:

(format "#+begin_export %s \n%s\n#+end_export" backend x)

In our case it produces:

"#+begin_export latex
*This* is a /try/.
#+end_export latex"

org-export now also wraps its argument, but the other way around: end_export first, begin_export last:

(format "\n#+end_export\n%s\n#+begin_export %s\n" x backend)

Also note the newline after #+begin_export latex. I have no idea why it is done like this, it does not make sense to me. It does not actually export the body. This is done by the usual org-export machinery; the function is hooked at org-export-before-processing-hook. it only adds export_ lines. This is why we end up with the undesired result:

blockcquote[key]{page}{
\textbf{This} is a \emph{try}.

}

The empty lines immediately above and below result form the _export lines. The second empty line is produced by the misplaced \n in the org-export function.

The easiest way to go about this is to just not use this weird syntax at all but actually parsing the body to org immediately. That is, we modify org-parse. If we replace

(format "\n#+end_export\n%s\n#+begin_export %s\n" x backend)

by

(s-replace-regexp "\n\\'" "" (org-export-string-as x backend t))))))))

we export the body to the preferred backend and delete any newlines before the string ends. This way, we get what we want:

#+begin_export latex 
\blockcquote[key]{pages}{\textbf{This} is a \emph{try}.}
#+end_export

I have added a merge request, see #30. It would be great if you could check whether this solution works and merge it. It's important for me that this is working.

@Perangelot Thanks for the investigations! 🔥

I haven't been able to get #30 incorporated, it's out of date and seems to break things on my end. I'm still investigating.

However, it seems the most up to date version of org-defblock solves your initial issue:

With this definition

(org-defblock blockquote (nil nil citekey "" pages "" :backend latex)
 "This is just an attempt."
 (format "\\blockcquote[%s]{%s}{%s}" pages citekey contents))

The LaTeX export does not produce too many unwanted newlines...

(org-export-string-as
 "#+begin_blockquote :citekey key :pages pages
 *This* is a /try/.
 #+end_blockquote" 'latex :body-only)
;;
;; ⇒ ⇒ ⇒
;;
"\\blockcquote[pages]{key}{\\textbf{This} is a \\emph{try}.}
"