# Storing captions in a file

I would like to have LaTeX read figure captions from a list stored in some file rather than writing their text directly in the \caption{} command. However I've not been able to figure out if this can be done nor how to do it.

The best situation would be like this one: the captions are stored in a plain text files together with some way to identify them (a label or a tag possibly separated from the caption itself in some way, like a tab or a semicolon or whatever). From the tex file one should be able to call something like \caption{\ReadFromFile[file]{tag}}. In this way one should still be able to rely on Latex for automatic float numbering etc, but the external file structure might get a bit complicated.

Another possibility is just to store the captions as consecutive lines in a file, read them and invoke something like \caption{\Nextcaption}. Of course in this case one would have to know a priori float numbering but the external file structure will be simple and thus reusable (the scenario I have in mind for this case is scientific publishing, where some journals ask for a separate figure caption file in plain text).

Suggestions are very welcome!

-
Welcome to TeX.sx! A tip: You can use backticks  to mark your inline code as I did in my edit. –  doncherry Nov 23 '11 at 10:58
Can you tell a little more about the external file. Is the format of that file part of the question or should a already existing file be used as it is? If so, a MWE showing at least that file would be nice. –  Schweinebacke Nov 23 '11 at 11:05
How do you intend to identify the actual caption. Should be there some automatic counter (e.g., \caption{\NextCaptionFromFile} reads line 1 for first \caption{} command, then line 2 for the next) or do you want to pass this info explictely (e.g., \caption{\FromFile{1}}). Elaborating a bit more on this (directly edit your question, please) might improve the quality of answers you get. Be precise :-) –  Daniel Nov 23 '11 at 11:08
@Daniel The question was vague on purpose, as both the option look interesting. Anyway now I stated both of them explicitly –  4gamma Nov 23 '11 at 12:00
add comment

## 2 Answers

You can call captions by a name that you assign and that can be used also for the \label. You'll write the caption file, say captions.tex, as

% #1 is the caption name, #2 is the caption text
\newcommand{\definecaption}[2]{%
\expandafter\newcommand\csname 4gamma@caption@#1\endcsname{#2}}
\newcommand{\usecaption}[1]{%
\caption{\csname 4gamma@caption@#1\endcsname\label{#1}}

% Now the captions

\definecaption{cat}{This is my cat}
\definecaption{dog}{This is my dog}


You'll say \input{captions} before \begin{document}. Then you can write

\begin{figure}
\centering
\includegraphics{cat}
\usecaption{cat}
\end{figure}


I'm not so sure that this is more practical than writing the caption text where it belongs, though.

-
As you will notice I heavily edited the original post.Anyway this would be perfect for the first proposed case! Thank you –  4gamma Nov 23 '11 at 11:57
@4gamma: If you find a answer useful, you should write this not only at a comment but up vote the answer (click onto the up pen). This is not only for reputation (egreg has a lot of this) but to show other users, which answers where really useful. –  Schweinebacke Nov 23 '11 at 14:44
add comment

You may parse a file with lines of format

label: caption text


using package xstring:

\begin{filecontents*}{captions.txt}
first: This is the first caption
third: This is the third caption (but second at file)
second: This is the second caption (but third at file)
\end{filecontents*}

\documentclass{article}
\usepackage{xstring}

\makeatletter
\newread\labelfile
\newcommand*{\ReadFromFile}[2][captions.txt]{%
\@ifundefined{text@#1@2}{%
\def\@labelfilename{#1}%
\openin\labelfile #1
\@process@line@from@captionfile
\closein\labelfile
}{}%
\@nameuse{text@#1@#2}%
}
\newcommand*{\string@from@captionfile}{}
\newcommand*{\@process@line@from@captionfile}{%
\ifeof\labelfile\else
\readline\labelfile to\@string@from@captionfile
\StrLen{\@string@from@captionfile}[\@string@length]%
\ifnum \number\@string@length>1 % ignore empty lines
\StrBefore{\@string@from@captionfile}{: }[\@firstpart]%
\StrBehind{\@string@from@captionfile}{: }[\@secondpart]%
\IfStrEq{\@firstpart}{}{%
\typeout{Syntax error: \@string@from@captionfile'}%
}{%
\expandafter\edef\csname text@\@labelfilename @\@firstpart\endcsname{%
\noexpand\scantokens{\@secondpart}%
}%
%        \expandafter\show\csname text@\@labelfilename @\@firstpart\endcsname% for debugging only
\expandafter\expandafter\expandafter\@process@line@from@captionfile
}%
\fi
\fi
}
\makeatother

\begin{document}
\listoffigures

\section{The Figures}
\begin{figure}[ht]
\caption{\ReadFromFile{first}}
\end{figure}

\begin{figure}[ht]
\caption{\ReadFromFile{second}}
\end{figure}

\begin{figure}[hb]
\caption{\ReadFromFile{third}}
\end{figure}

\end{document}


empty lines (even not space!) are allowed at the file with the caption texts. They will be ignored. Lines which does not fit the syntax given above (e.g. missing space after :) will show a syntax error message and be ignored. A \ReadFromFile{notfound} with notfound may not be found at the caption texts will result in an empty caption text. You may add a test for this, using package xstring again. See package manual for more information about.

-
add comment