# Automating quoting across LaTeX documents

I occasionally face the following situation when writing LaTeX documents. (This question is probably not LaTeX specific, though). Suppose I have a document, say orig.tex. Then I quote from that document in another document, say new.tex. So, for example... orig.tex is

\documentclass{article}

%% orig.tex
\begin{document}

Here is some text. {This is some text I want to quote.} Here is yet
more text. The quick brown fox ran over the lazy dog.

{I want to quote all the text in this para. Some more text to get this
line to wrap.

And this para as well, in one quotation.}

\end{document}


and new.tex is

%% new.tex
\documentclass{article}
\usepackage{quoting}
\begin{document}

Quotation one from orig.tex is
\begin{quoting}
This is some text I want to quote.
\end{quoting}

Quotation two from orig.tex is

\begin{quoting}
I want to quote all the text in this para. Some more text to get
this line to wrap.

And this para as well, in one quotation.
\end{quoting}

\end{document}


However, the problem is that after I have copied in these quotations to new.tex, I may change the text in orig.tex. I want LaTeX to automatically copy the text across from orig.tex to new.tex. Each quotation could be associated with some kind of label.

The curly braces in orig.tex mark the quotation start and end points. This is a stand-in for proper macro or function usage. This will cause some clutter in the original document, but I can remove these markers after the new.tex has been sent off. Till then, I want these two documents to stay in sync.

For simplicity, let's assume these quotations are non-overlapping, as this would add extra complexity to the problem. However, as shown in the example, they may cross line and paragraph breaks.

The closest thing in terms of functionality that I am aware of is the xr package by our very own David Carlisle :-), but I don't know if it can be adapted for use here.

UPDATE: Apparently this question wasn't as clear as it should have been. I just used {}'s in orig.tex because I wasn't sure what kind of syntax to use, but I was thinking of something along the lines of some macro like \c (for cut) in orig.tex, thus,

...\c[label]{some text to quote}


and then another macro \p for paste, which inserts that text in new.tex, thus.

...\p[label]...


UPDATE2: Thanks to Peter Grill, David Carlisle, and Aditya for their answers.

I have tested both Peter's macro solution and David's solution. A choice between the two of them would have been difficult. However, Peter's approach uses the standalone package, which seems to have some bad interactions with the custom class I'm using, Springer's svmult.cls. I was on a deadline and didn't want to take the time to figure this out, so I went with David's solution, which has no package dependencies, and worked for me.

I think this code is worth packaging - I'm surprised it does not exist as a package already. Handling multiple input files would be a desirable feature, though.

I haven't tested Aditya's solution, but plan to do so.

-
Interesting timing... This is pretty much exactly what I am doing with Expansion issue: How Check if options passed to an environment were used. This question was used to be able to provide an error message in case an attempt was made to quote something that did not exist. –  Peter Grill May 24 '12 at 18:53

I don't think picking up just on brace groups is viable, there are too many braces in a TeX document. I used \q{...} here.

After clarification in chat and comments, a version with named references.

orig.tex

\documentclass{article}

\usepackage{qting}

%% orig.tex
\begin{document}

Here is some text. \q{aa}{This is some text I want to quote.} Here is yet
more text. The quick brown fox ran over the lazy dog.

\q{bb}{I want to quote all the text in this para. Some more text to get this
line to wrap.

And this para as well, in one quotation.}

\end{document}


new.tex

\documentclass{article}
\usepackage{qting}
\quotefrom{orig}

\begin{document}

Quotation one from orig.tex is
\quoting{aa}

Quotation two from orig.tex is

\quoting{bb}

And once again, for luck: \quoting{aa}.

\end{document}


qting.sty

% \q is just a marker to place in the original file, it just discards the label
\def\q#1{}

% \quotefrom goes in the new file and specifies which file to read.
% The file is read line by line using \read and plain TeX's \loop
% reading each line until end of file (\ifeof).
%
% So the second argument of \q with the quotation will always be read in one "go".
\def\quotefrom#1{%
\openin\q@in#1\relax
\loop
% This puts the next line/brace group of old.tex into \temp
% This puts tests if \temp includes \q, if not it does nothing.
% And we loop to the next line, if it does save the second argument of \q in a macro.
% with name based on the first argument.
\expandafter\testq\temp\testq\q\@nil\relax\testq\quotefrom
% keep going till the end of the file
\ifeof\q@in
\else
\repeat
}

% use a delimited argument to find the next two things after \q.
% If they are \@nil and {}, then this is the "fake" instance inserted in
% the call. In that case do nothing. Otherwise this is a \q in the document, so
% save the second argument of \q (#3) in a macro with name \q-firstArgOfq.
\long\def\testq#1\q#2#3#4\testq#5\quotefrom{%
\def\@tempa{#2}%
\ifx\@tempa\@nnil
\else
\@namedef{q-#2}{#3}%
\fi}

% if the macro for the referenced quotation is defined, use it, otherwise
% warn on the log and in the document.
\def\quoting#1{%
\expandafter\ifx\csname q-#1\endcsname\relax
[Missing quote \texttt{#1}]%
\typeout{what quote [#1] ?}%
\else
\csname q-#1\expandafter\endcsname
\fi}


The main restrictions are that:

• You can't have two \q on the same line in the original document. Or more exactly, everything on the line after the } of a \q is ignored.

• Any \q inside brace groups will not be seen by the scanner (as it uses TeX delimited arguments to look for \q tokens). This may be used to hide \q that may have locally different meaning, but does mean that you have to arrange that any text that you do want to quote is at the top level of the original file.

Extended version of this code placed at

-
As I've already published a quoting package, please consider to rename your example .sty file. –  lockstep May 24 '12 at 19:24
@lockstep, yes I just copied the OP, I'll give it an obviously temp name, to save it being copied out of context. –  David Carlisle May 24 '12 at 19:25
Hi David. Thanks for the answer, but for this to work in general I think some label system is needed. perhaps a first argument to your \q macro, which can be used to reference that particular quotation. Also, why the restriction? –  Faheem Mitha May 24 '12 at 19:41
Hey I was following the question:-) I thought I was changing too much by introducing \q you asked for anonymous brace groups as the marker. the restriction is there because \read reads a line at a tine so the whole line has been read so you gran the q bit and throw the rest of the line away, and if there is another q in there too bad. (that could be fixed, but at some cost in complexity and you can almost always just put a linebreak before the \q in the original file. A label system would really want a different implementation as this just picks them up one at time. –  David Carlisle May 24 '12 at 19:54

In ConTeXt, the standard way to do this is to use buffers. For example, you can define a file called quotes.tex that contains:

\startenvironment quotes

\startbuffer[quote-1]
A random quote with {\em emphasis} and other commands\footnote{e.g., footntoes}.
\stopbuffer

\startbuffer[quote-2]
A quote with different catcodes, for example, in-line verbatim
\type{\undefined#} or display verbatim
\starttyping
/* Some C code */
#include<stdio.h>

void main() {
printf("Hello World\n");
}
\stoptyping
\stopbuffer

\stopenvironment


Then in orig.tex you can use

\environment quotes

\starttext
\getbuffer[quote-1]
\input ward
\getbuffer[quote-2]
\stoptext


and similarly in new.tex. I know that this is not exactly what the OP asked, but in some sense, it achieves the same functionality.

Buffers are stored in memory, and at the same time are more robust that the macro based solutions presented above, as they do not touch the catcode of the contents. So you can have code listings, etc. inside the buffers, or use the buffer inside a different catcode regime (if you are processing XML etc).

-
Interesting. Does LaTeX have similar functionality? If you post a complete example, I'll give it a try. I don't know anything about ConTeXt though. –  Faheem Mitha May 24 '12 at 22:15
I added a complete working example. ConTeXt is a macro package similar to LaTeX. See the context wiki for an introduction. –  Aditya May 25 '12 at 19:29
I'm aware of the existence of ConTeXt, but little more. I'm basically out of bandwidth for this month, and don't have ConTeXt installed, so I can't test this right now. However, I'm unclear about what your files are. What is the original file, and what is the files that quotes that file? It looks like these are quotes.tex and orig.tex, but you are refer to a new.tex, which is confusing. What files corresponds to orig.tex and new.tex in my question? –  Faheem Mitha May 28 '12 at 16:13
I have split the orig.tex file in your example to two files, quotes.tex and orig.tex. The new.tex is the same as the new.tex in your question. So, basically, I am using a separate file to define quotes. –  Aditya May 28 '12 at 16:56
I see. Since I don't know ConTeXt, what would the new.tex look like exactly? I assume it has to be a ConTeXt file. –  Faheem Mitha May 28 '12 at 17:08

Here is something I think that is more flexible. This is adapted from something similar that I have been working on in the past few days.

## Environment Version (Old Solution):

The main difference is that what I needed was to unquote portions of the text, so to adapt it for your case I needed to wrap all the text in the QuotableText environment. There is likely a way to work around this, but in the current form of this solution you need to wrap all the text within a QuotableText environment (See Further Enhancements section).

\begin{QuotableText}
Here is some text.
\end{QuotableText}


In the orig.tex, this environment is defined as

\newenvironment{QuotableText}[1][Unnamed Quote]{\ignorespaces}{}%


so all the text is typeset as normal. But, for the portions that you may want to quote you give those a name. Here I have named this quote "First Quote":

\begin{QuotableText}[First Quote]
This is some text I want to quote.
\end{QuotableText}


Then, when you want to quote this in another file, you use:

\QuoteMyText{orig.tex}{First Quote}


where you provide the file name, and the name of the quote environment that you want.

This MWE below yields (where the blue is the quotes produced by your original MWE, and the red is the one produced via the \QuoteMyText macro by extracting the content from the original file):

## Further Enhancements:

All these are fixed in the macro version answer:

• Eliminate the need to wrap a QuotableText environment around text that never needs to be quoted.
• Tweaks so that the spacing produced is identical.
• Error message if a request to obtain a named quote provided a name which does not exist. For my case, I have adapted the solution from Expansion issue: How Check if options passed to an environment were used to solve this case. This is highly recommended as it took me a quite a few minutes to figure out that the reason why \QuoteMyText{orig.tex}{Second Quote} was not yielding any text was that I had the incorrect quote name.

## Code:

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{orig.tex}
\documentclass{article}

\newenvironment{QuotableText}[1][Unnamed Quote]{%
\ignorespaces%
}{%
}%

\begin{document}
\begin{QuotableText}
Here is some text.
\end{QuotableText}
\begin{QuotableText}[First Quote]
This is some text I want to quote.
\end{QuotableText}
\begin{QuotableText}
Here is yet more text. The quick brown fox ran over the lazy dog.
\end{QuotableText}

\begin{QuotableText}[Another Quote]
I want to quote all the text in this para. Some more text to get
this line to wrap.

And this para as well, in one quotation.
\end{QuotableText}
\end{document}
\end{filecontents*}
%---------------------------

\usepackage{standalone}
\usepackage{etoolbox}
\usepackage{xcolor}
\usepackage{quoting}
\usepackage{xstring}
\usepackage{environ}

\NewEnviron{QuotableText}[1][Unnamed Quote]{\BODY}%

\newcommand{\QuoteMyText}[2]{%
% #1 = file name
% #2 = name of quotable section
\RenewEnviron{QuotableText}[1][Unnamed Quote]{%
\IfEq{##1}{#2}{% This is the quote we want
\ignorespaces%
\begin{quoting}\color{red}%
\BODY%
\end{quoting}%
}{% This is not the one we are looking for
% so we ignore the \BODY here
}%
}%
\input{#1}%
}%

\begin{document}

Quotation one from orig.tex is
\QuoteMyText{orig.tex}{First Quote}

\begin{quoting}\color{blue}
This is some text I want to quote.
\end{quoting}

Quotation two from orig.tex is

\QuoteMyText{orig.tex}{Another Quote}

\begin{quoting}\color{blue}
I want to quote all the text in this para. Some more text to get
this line to wrap.

And this para as well, in one quotation.
\end{quoting}
\end{document}

-

You may use the clipboard package:

\Copy{<key>}{text}

\Paste{<key>}

For example:

## source.tex:

\documentclass{book}
\usepackage{clipboard}
\newclipboard{myclipboard}
\begin{document}
\Copy{dolorem ipsum}{Nor again is there anyone who
loves or pursues or desires to obtain pain of itself},
because it is pain, but occasionally circumstances occur
in which toil and pain can procure him some great pleasure.
\end{document}


## target.tex:

\documentclass{article}
\usepackage{clipboard}
\openclipboard{myclipboard}
\begin{document}
According to Cicero,
\begin{quote}
\Paste{dolorem ipsum}
\end{quote}
\end{document}


Now run:

$latex source.tex$ latex target.tex

-
\yank in this context does the opposite of what "yank" means in emacs. That might be confusing. –  Seamus Jan 13 '13 at 18:58
@Seamus: Really? But yank seems to mean copy in vim! What could I use instead of \yank and \copy? –  eduardo.tex Jan 18 '13 at 2:35
Yank means "paste" in emacs. Perhaps \copy or \remember or something? –  Seamus Jan 19 '13 at 11:09
\copy is already defined in TeX but \remember is a good idea. Thanks! –  eduardo.tex Jan 19 '13 at 11:48

A possibly simpler solution:

## xqting.sty

\ProvidesPackage{xqting}

\newif\ifxqt@option
\newif\ifxqt@primary
\DeclareOption{primary}{\xqt@primarytrue\xqt@optiontrue}
\DeclareOption{secondary}{\xqt@primaryfalse\xqt@optiontrue}

\ProcessOptions\relax

\RequirePackage{environ}

\ifxqt@option\else
\PackageError{xqting}{Missing Option}
{You must provide either primary' or secondary'.\MessageBreak
Fix the call and rerun LaTeX}
\@@end
\fi

\ifxqt@primary
\newwrite\xqt@notes
\immediate\openout\xqt@notes=\jobname.nts
\else
\AtBeginDocument{
\ifdefined\xqt@original\else
\PackageError{xqting}
{Missing original file}
{You have to state \string\original{...}' in the preamble}
\fi
}
\fi

%%% Commands for the primary source
\newcommand{\Store}[2]{%
\immediate\write\xqt@notes{\noexpand\Note{#1}{\unexpanded{#2}}}%
#2}

\NewEnviron{LongStore}[1]{%
\immediate\write\xqt@notes{\noexpand\Note{#1}{\unexpanded\expandafter{\BODY}}}%
\BODY}

%%% Commands for the secondary source
\newcommand{\originalfile}[1]{%
\InputIfFileExists{#1.nts}
{\let\xqt@original=T}
{\PackageWarning{xqting}{Missing file #1.nts}}%
}
\@onlypreamble\originalfile

\newcommand{\Note}[2]{\@namedef{Note@#1}{#2}}
\newcommand{\Print}[1]{\@ifundefined{Note@#1}{MISSING (\texttt{#1})}{\@nameuse{Note@#1}}}

\endinput


## Master file (file1.tex)

\documentclass{article}
\usepackage[primary]{xqting}

\begin{document}

First sentence. \Store{qt1}{Second sentence}. Third sentence.

Fourth sentence. \Store{qt2}{Third sentence with \emph{emphasis}}.

Something longer that would be difficult to put in braces so
\begin{LongStore}{qt3}
here's a passage that doesn't need braces
but is more conveniently in an environment.

It even has two paragraphs.
\end{LongStore}

\end{document}


## Secondary file (file2.tex)

\documentclass{article}

\usepackage[secondary]{xqting}
\originalfile{file1}

\begin{document}

The author says:
\begin{quote}
\Print{qt1}
\end{quote}
but also \Print{qt2}''.

And the long quotation is
\begin{quote}
\Print{qt3}
\end{quote}

But something can go wrong: \Print{qt4}

\end{document}


One can even use two or more \originalfile commands, as long as the keys are distinct.

-
This works very well. The one problem is that it doesn't resolve references. That is, Figure \ref{fig:firstfigure} appears in the .nts file verbatim, and since the secondary file can't find the fig:firstfigure label, it also appears verbatim when you compile the secondary file. Any suggestions? –  user21155 Mar 7 at 15:07
@user21155 I think you can do this with the help of the xr package. –  egreg Mar 7 at 16:54
xr helps with cros-references, thanks. What about citations, e.g. with bibtex? I would like to reproduce the citation as it appears in the primary document, rather than attempt to process the bib file, etc. Also, for numbered bibliographies processing the bibliography won't work well, since it will return an incorrect number. –  user21155 Mar 21 at 15:53
@user21155 There is xcite that works in a very similar way to xr. I know about this package for obvious reasons. ;-) –  egreg Mar 21 at 15:55

This is an improved version of the environment version:

## Macro Version:

You could wrap the text you want to quote in a macro such as:

\newcommand{\QuotableText}[2][Unnamed Quote]{#2}%


where #1 is the optional name for this quote, and #2 is the actual quote. Note that with this definition the content is typeset as normal in the original document. Then when you want to reference this quote in some other file, you use the macro:

\QuoteMyText{<File Name>}{<Quote Name>}


Within the \QuoteMyText macro, you redefine \QuotableText as such:

\newcommand{\QuoteMyText}[2]{%
% #1 = file name
% #2 = name of quotable section
\renewcommand{\QuotableText}[2][Unnamed Quote]{%
\IfEq{##1}{#2}{% This is the quote we want
\global\def\QuotedText{##2}%
}{% This is not the one we are looking for
% so we ignore the ##2 here
}%
}%
\savebox{\mybox}{\vbox{\input{#1}}}%
\par\begin{quoting}\color{red}%
\QuotedText%
\end{quoting}%
\global\def\QuotedText{\DefaultQuotedText}
}%


## Notes:

• Since this solution needs the ability to incorporate complete LaTeX files, the standalone package needs to be used.
• In this version the requirement that the unquoted text be wrapped in an environment has been eliminated.
• Quotes can be accessed in any order (not necessarily in the order the appear in the source text).
• The slight spacing discrepancy in the first quote that was in the earlier version is now fixed (added \par prior to begin{quoting}.
• If an attempt to access a quote that has not been defined (ie, such as would be the case for a simple typo), this is displayed prominently in the output. So, an attempt to quote as \QuoteMyText{orig.tex}{Second Quote} yields:

You can change the definition of \DefaultQuotedText to change how this error condition is handled.

## Further Enhancements:

• If the source text redefines a named quote using the same name, only the last named quote will show up. A check could be added to alert the user if this is encountered.

## Output:

The code below (blue is the quotes produced by the original MWE, and the red is the quote extracted from the original file) yields:

## Code:

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{orig.tex}
\documentclass{article}

\newcommand{\QuotableText}[2][Unnamed Quote]{#2}%

\begin{document}
Here is some text that is not part of the quoted text.
\QuotableText[First Quote]{%
This is some text I want to quote.%
}%
Here is yet more text that is not quoted. The quick brown fox ran over the lazy dog.

\QuotableText[Another Quote]{
I want to quote all the text in this para. Some more text to get
this line to wrap.

And this para as well, in one quotation.
}

\section{foo}\label{foo}
abc
\end{document}
\end{filecontents*}
%---------------------------

\usepackage{standalone}
\usepackage{xcolor}
\usepackage{quoting}
\usepackage{xstring}

\newcommand{\QuotableText}[2][Unnamed Quote]{#2}%
\newcommand{\QuotedText}{\DefaultQuotedText}%
\newsavebox{\mybox}

\newcommand{\QuoteMyText}[2]{%
% #1 = file name
% #2 = name of quotable section
\renewcommand{\QuotableText}[2][Unnamed Quote]{%
\IfEq{##1}{#2}{% This is the quote we want
\global\def\QuotedText{##2}%
}{% This is not the one we are looking for
% so we ignore the ##2 here
}%
}%
\savebox{\mybox}{\vbox{\input{#1}}}%
\par\begin{quoting}\color{red}%
\QuotedText%
\end{quoting}%
\global\def\QuotedText{\DefaultQuotedText}%
}%

\begin{document}
Quotation one from orig.tex is
\QuoteMyText{orig.tex}{First Quote}

\begin{quoting}\color{blue}
This is some text I want to quote.
\end{quoting}

Quotation two from orig.tex is

\QuoteMyText{orig.tex}{Another Quote}

\begin{quoting}\color{blue}
I want to quote all the text in this para. Some more text to get
this line to wrap.

And this para as well, in one quotation.
\end{quoting}
\end{document}
`
-