Hello, When exporting to LaTeX, is there a mechanism to make the figure captions as wide as the figure? In pure LaTeX, this can be easily accomplished by placing the figure inside a minipage environment. Using a special block, as in: \begin{minipage}{0.7\textwidth} #+CAPTION: looooooong caption. [[file_path]] \end{minipage} fails, as it seems impossible to pass arguments to the special block. Any tips welcome. -- Seb
Hi Seb Seb writes: > When exporting to LaTeX, is there a mechanism to make the figure > captions as wide as the figure? In pure LaTeX, this can be easily > accomplished by placing the figure inside a minipage environment. > Using a special block, as in: > > \begin{minipage}{0.7\textwidth} > > #+CAPTION: looooooong caption. > [[file_path]] > > \end{minipage} > > fails, as it seems impossible to pass arguments to the special block. > Any tips welcome. If you use the caption package (https://www.ctan.org/pkg/caption), you can indicate in each figure the width of the caption. In this case, you would have to introduce the code using raw latex via the `:caption' property: #+LaTeX_Header: \usepackage{caption} #+ATTR_LaTeX: :caption \captionsetup{width=.3\linewidth}\caption{Lorem ipsum dolor sit amet, consectetuer adipiscing elit} #+ATTR_LaTeX: :width .3\linewidth [[file_path]] Best regards, Juan Manuel
P.S.: I have come up with another possibility, more automatic, on the LaTeX side, if you compile with LuaTeX. This thread (https://tex.stackexchange.com/questions/202046/width-of-the-caption-of-a-figure), where someone proposes to use a \savebox for concrete images, gave me the idea. We can automate that through a simple function in Lua, and add it to the `process_input_buffer' callback, in order to the caption *always* has the width of each image: You can put this in your Org document: #+NAME: luacode #+begin_src latex :exports none \usepackage{luacode} \begin{luacode*} function caption_width ( text ) text = string.gsub ( text, "(\\includegraphics.+)", "\\sbox0{%1}") text = string.gsub ( text, "(\\caption{.+})", "\\begin{minipage}{\\wd0}\\usebox0%1\\end{minipage}") return text end \end{luacode*} \newcommand\CaptionAutoWidth{\directlua{luatexbase.add_to_callback ( "process_input_buffer" , caption_width , "caption_width" )}} \AtBeginDocument{\CaptionAutoWidth} #+end_src #+begin_src latex :noweb yes :results raw ,#+LaTeX_HEADER: <<luacode>> #+end_src And then: #+CAPTION: Lorem ipsum dolor sit amet, consectetuer adipiscing elit #+ATTR_LaTeX: :width .3\linewidth [[img]] Best regards, Juan Manuel Juan Manuel Macías writes: > If you use the caption package (https://www.ctan.org/pkg/caption), you > can indicate in each figure the width of the caption. In this case, you > would have to introduce the code using raw latex via the `:caption' > property: > > #+LaTeX_Header: \usepackage{caption} > > #+ATTR_LaTeX: :caption \captionsetup{width=.3\linewidth}\caption{Lorem ipsum dolor sit amet, consectetuer adipiscing elit} > #+ATTR_LaTeX: :width .3\linewidth > [[file_path]]
On Mon, 27 Dec 2021 07:41:59 +0000, Juan Manuel Macías <maciaschain@posteo.net> wrote: [...] > If you use the caption package (https://www.ctan.org/pkg/caption), you > can indicate in each figure the width of the caption. In this case, > you would have to introduce the code using raw latex via the > `:caption' property: > #+LaTeX_Header: \usepackage{caption} > #+ATTR_LaTeX: :caption \captionsetup{width=.3\linewidth}\caption{Lorem > ipsum dolor sit amet, consectetuer adipiscing elit} #+ATTR_LaTeX: > :width .3\linewidth [[file_path]] Thank you, Juan. Unfortunately, there is a price for this solution as it is now impossible to name and refer to this segment as usual: #+LATEX_HEADER: \usepackage{caption} See [[fig1]]. #+NAME: fig1 #+ATTR_LATEX: :caption \captionsetup{width=0.5\textwidth}\caption{Lorem ipsum dolor sit amet, consectetuer adipiscing elit} [[file_path]] leads to this (I compile with latexmk): Latexmk: Summary of warnings from last run of *latex: Latex failed to resolve 1 reference(s) -- Seb
Sebastian P. Luque writes:
> Thank you, Juan. Unfortunately, there is a price for this solution as
> it is now impossible to name and refer to this segment as usual:
I see. Have you tried the option with LuaTeX that I put in my other
message? You can compile with LuaTeX also using latexmk:
(setq org-latex-pdf-process
'("latexmk -lualatex -e '$lualatex=q/lualatex %%O -shell-escape %%S/' %f"))
In any case, since this is a simple substitution, you can use also a
function in Elisp as a final output filter[1]:
#+BIND: org-export-filter-final-output-functions (caption-auto-width)
#+begin_src emacs-lisp :exports results :results none
(defun caption-auto-width (text backend info)
(when (org-export-derived-backend-p backend 'latex)
(with-temp-buffer
(insert text)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "\\(\\\\includegraphics.+\\)" nil t)
(replace-match "\\\\sbox0{\\1}" t nil)))
(save-excursion
(goto-char (point-min))
(while (re-search-forward "\\(\\\\caption.+\\)" nil t)
(replace-match "\\\\begin{minipage}{\\\\wd0}\\\\usebox0\\1\\\\end{minipage}" t nil)))
(setq text (buffer-string)))))
#+end_src
Vid. [[fig:1]]
#+NAME: fig:1
#+CAPTION: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec hendrerit tempor tellus. Donec pretium posuere tellus
#+ATTR_LaTeX: :width .3\linewidth
[[my-image.jpg]]
[1] You need to set this variable as non-nil, in order to use bind
keywords: (setq org-export-allow-bind-keywords t)
Hope this works,
Best regards,
Juan Manuel
On Mon, 27 Dec 2021 13:28:08 +0000, Juan Manuel Macías <maciaschain@posteo.net> wrote: > Sebastian P. Luque writes: >> Thank you, Juan. Unfortunately, there is a price for this solution >> as it is now impossible to name and refer to this segment as usual: > I see. Have you tried the option with LuaTeX that I put in my other > message? You can compile with LuaTeX also using latexmk: > (setq org-latex-pdf-process '("latexmk -lualatex -e > '$lualatex=q/lualatex %%O -shell-escape %%S/' %f")) I haven't tried this yet, but it's great to know latexmk can use LuaTex. > In any case, since this is a simple substitution, you can use also a > function in Elisp as a final output filter[1]: > #+BIND: org-export-filter-final-output-functions (caption-auto-width) > #+begin_src emacs-lisp :exports results :results none > (defun caption-auto-width (text backend info) (when > (org-export-derived-backend-p backend 'latex) (with-temp-buffer > (insert text) (save-excursion (goto-char (point-min)) (while > (re-search-forward "\\(\\\\includegraphics.+\\)" nil t) (replace-match > "\\\\sbox0{\\1}" t nil))) (save-excursion (goto-char (point-min)) > (while (re-search-forward "\\(\\\\caption.+\\)" nil t) (replace-match > "\\\\begin{minipage}{\\\\wd0}\\\\usebox0\\1\\\\end{minipage}" t nil))) > (setq text (buffer-string))))) #+end_src > Vid. [[fig:1]] > #+NAME: fig:1 #+CAPTION: Lorem ipsum dolor sit amet, consectetuer > adipiscing elit. Donec hendrerit tempor tellus. Donec pretium posuere > tellus > #+ATTR_LaTeX: :width .3\linewidth [[my-image.jpg]] > [1] You need to set this variable as non-nil, in order to use bind > keywords: (setq org-export-allow-bind-keywords t) > Hope this works, This is great, and very interesting to learn about the BIND keyword. Thank you, -- Seb
Sebastian P. Luque writes:
> This is great, and very interesting to learn about the BIND keyword.
>
> Thank you,
You're welcome. Of course, if you use the filter very often, it is not
necessary to include it in a document or use the bind keyword. It
would be enough to add the function to your init and the line:
(add-to-list 'org-export-filter-final-output-functions #'caption-auto-width)
In a case like this, however, I would prefer to use the other function
in Lua within LuaTeX, since two commands could be defined: one to enable
the automatic caption width and one to disable it, throughout the
document. E.g.:
#+begin_src latex
\usepackage{luacode}
\begin{luacode*}
function caption_width ( text )
text = string.gsub ( text, "(\\includegraphics.+)", "\\sbox0{%1}")
text = string.gsub ( text, "(\\caption.+)", "\\begin{minipage}{\\wd0}\\usebox0%1\\end{minipage}")
return text
end
\end{luacode*}
\newcommand\CaptionAutoWidthOn{\directlua{luatexbase.add_to_callback
( "process_input_buffer" , caption_width , "caption_width" )}}
\newcommand\CaptionAutoWidthOff{\directlua{luatexbase.remove_from_callback
( "process_input_buffer" , "caption_width" )}}
#+end_src
\CaptionAutoWidthOn
#+CAPTION: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec hendrerit tempor tellus
#+ATTR_LaTeX: :width .3\linewidth
[[img.jpg]]
\CaptionAutoWidthOff
#+CAPTION: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec hendrerit tempor tellus
#+ATTR_LaTeX: :width .1\linewidth
[[img.jpg]]
On Sunday, 26 Dec 2021 at 19:22, Seb wrote: > Using a special block, as in: [...] > fails, as it seems impossible to pass arguments to the special block. Not true. The following seems to create the LaTeX code you wanted: --8<---------------cut here---------------start------------->8--- #+attr_latex: :options {0.7\textwidth} #+begin_minipage #+CAPTION: looooooong caption. [[file_path]] #+end_minipage --8<---------------cut here---------------end--------------->8--- HTH, eric -- : Eric S Fraga, with org release_9.5.1-279-g8908fb in Emacs 29.0.50 : Latest paper written in org: https://arxiv.org/abs/2106.05096
On Tue, 28 Dec 2021 14:58:35 +0000, Eric S Fraga <e.fraga@ucl.ac.uk> wrote: > On Sunday, 26 Dec 2021 at 19:22, Seb wrote: >> Using a special block, as in: > [...] >> fails, as it seems impossible to pass arguments to the special block. > Not true. The following seems to create the LaTeX code you wanted: > #+attr_latex: :options {0.7\textwidth} #+begin_minipage > #+CAPTION: looooooong caption. [[file_path]] > #+end_minipage That is strange, as it actually should not work (it still doesn't for me with your code). However, I had made a mistake in my original post as I meant to have the minipage environment inside the floating figure environment in the output, as in: ---<--------------------cut here---------------start------------------->--- \begin{figure}[htbp] \centering \begin{minipage}{0.5\textwidth} \includegraphics[width=\textwidth]{FILE_PATH} \caption{\label{ORG_LABEL}Lorem ipsum dolor sit amet, consectetuer adipiscing elit.} \end{minipage} \end{figure} ---<--------------------cut here---------------end--------------------->--- which does compile fine. Apologies for the confusion this may have caused. The previous post by Juan Manuel did provide a neat solution, which I'll be tweaking to implement this as I never need captions running across the whole page for figures using much less. -- Seb
On Tuesday, 28 Dec 2021 at 09:59, Seb wrote: > That is strange, as it actually should not work (it still doesn't for me > with your code). Well, it won't work if the figure is to float but will if you ask org to not float the figure. > However, I had made a mistake in my original post as I meant to have > the minipage environment inside the floating figure environment in the > output, as in: That makes more sense and, for this case, special blocks cannot work unfortunately. I'm glad you did find a working solution but I simply wanted to clarify that you can indeed pass options to special blocks which your original post seemed to state was not possible. I use special blocks all the time, including minipages but others as well for custom LaTeX environments. -- : Eric S Fraga, with org release_9.5.1-279-g8908fb in Emacs 29.0.50 : Latest paper written in org: https://arxiv.org/abs/2106.05096