Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
    
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
add comment

6 Answers 6

up vote 12 down vote accepted

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.

enter image description here

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).
%
% Crucially, \read reads _at least_ a line, but always reads entire brace groups
% So the second argument of \q with the quotation will always be read in one "go".
\def\quotefrom#1{%
\newread\q@in
\openin\q@in#1\relax
\loop
% This puts the next line/brace group of old.tex into \temp
\read\q@in to \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

http://code.google.com/p/dpctex/source/browse/#svn%2Ftrunk%2Fqting

share|improve this answer
    
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
add comment

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).

share|improve this answer
1  
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
show 2 more comments

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):

enter image description here

Notes:

  • Since this solution needs the ability to incorporate complete LaTeX files, the standalone package needs to be used.

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}
share|improve this answer
add comment

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
share|improve this answer
1  
\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
add comment

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.

share|improve this answer
add comment

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:

    enter image description here

    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:

enter image description here

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{\DefaultQuotedText}{\fbox{\color{green}Quoted text not found!!!!}}%
\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}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.