org-special-block-extras
org-special-block-extras copied to clipboard
Unwanted newlines in LaTeX export
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.
- Unfortunately, I can't look into this closer at the moment, but perhaps this tutorial will help: https://alhassy.github.io/org-special-block-extras/#practice_problems
Thanks for your answer. After digging in the code for hours, I have found out two things:
- The reason why there were extra
#+end_export
and#+begin_export
lines is due to a line which explicitly adds them; see #28. - 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
- Nonetheless, if you export this to LaTeX, you will get
\blockcquote[]{}{*This* is a /try/
}
- 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}.}
"