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.

Intro

I'm working on a lightweight package that allows you to put any content (typically LaTeX code) in an environment, then use that content multiple times, each time scanned separately, so you can use it both as verbatim output and interpreted as LaTeX.

Its main purpose is to typeset LaTeX code and its 'result' side-by-side; useful for documenting TeX packages without having to copy/paste code. But it has other purposes as well.

After experimenting with \scantokens until I gave up in tears, I arrived at the filecontents environment, which almost solved my problem singlehandedly!

The Problem

The problem is, when reintroducing filecontented code through \input, LaTeX adds an implicit newline at the end, which translates to whitespace that I can't seem to get rid of.

I've seen many semi-related questions floating around, with answers employing techniques like:

  • reading a file line-by-line,
  • using \everyeof in some clever way,
  • playing with \endlinechar or
  • using packages such as catchfile

but none of them provides a clear answer to the following question:

The Question

How can I \input a file without getting the implicit newline?

Minimal Working Example

\documentclass[margin=1mm]{standalone}

\usepackage{filecontents}

\begin{filecontents*}{tmp.tex}
    \LaTeX{}\end{filecontents*}

\begin{document}
    \fbox{\input{tmp.tex}}
\end{document}

enter image description here

Note the extra whitespace to the right of the box.

Note also that I'm definitely not adding any explicit whitespace. Even a manually produced file (so, not using filecontents) with no newlines at all exhibits the same problem.

share|improve this question
    
Could you show us and example you've put together that illustrates the basic idea of what you're aiming for? And then point out how the example isn't fully realizing you ideal result. –  A.Ellett Dec 9 '12 at 16:12
    
@A.Ellett Done. –  mhelvens Dec 9 '12 at 16:36
    
In this context the final empty line is not responsible for that space: \par does nothing in restricted horizontal mode. –  egreg Dec 9 '12 at 16:51
    
@egreg This is not about \par, but about the single newline (\n if you will) that TeX adds to my input. It gets converted to a space, just like TeX always does with single newlines. No? –  mhelvens Dec 9 '12 at 16:56
    
@mhelvens No: it's an empty line, so it gets converted to \par –  egreg Dec 9 '12 at 16:57
show 7 more comments

6 Answers 6

up vote 6 down vote accepted

The following requires a different command, say \minput:

\documentclass[margin=1mm,varwidth]{standalone}

\usepackage{filecontents}

\newcommand\minput[1]{%
  \input{#1}%
  \ifhmode\ifnum\lastnodetype=11 \unskip\fi\fi}

\begin{filecontents*}{tmp.tex}
\LaTeX{}
\end{filecontents*}
\begin{filecontents*}{tmp2.tex}
\LaTeX
\end{filecontents*}
\begin{filecontents*}{tmp3.tex}
\LaTeX\hspace{2em}
\end{filecontents*}

\begin{document}
\fbox{\input{tmp.tex}} \fbox{\minput{tmp.tex}}

\minput{tmp}Nospace \minput{tmp} Space

\minput{tmp2} Space

\minput{tmp3}Nospace

\LaTeX\hspace{2em}Nospace
\end{document}

This will fail if the input file ends with something like \hskip 2pt, but I believe one can ignore such cases.

enter image description here

share|improve this answer
    
Looking good! I guess this is the closest we are likely to come to a correct answer. :-) –  mhelvens Dec 16 '12 at 12:19
    
Ah, in naming the command for my package, can you tell me what the 'm' stands for? I'll use it if it makes sense. ;-) –  mhelvens Dec 16 '12 at 12:28
    
Also, if you have some time, could you write a paragraph about the limitations of this solution to include in the docs? I'll quote you by name. –  mhelvens Dec 16 '12 at 12:35
    
@mhelvens The limitation is that an explicit horizontal glue specification at the end of the input file will be lost. Not if the specification uses \hspace, but only with \hskip. It will not work if one fiddles with \endlinechar, but I guess it won't be the case with your setting. –  egreg Dec 16 '12 at 13:46
    
Thanks for your input! –  mhelvens Dec 16 '12 at 13:50
add comment

Using \everyeof is too late to gobble the space. One can set \endlinechar=\m@one, but this will ignore all end-of-lines, not just the trailing space-causing one.

One might consider reading the file into a macro where the trailing space can be controlled more easily. However, any solution involving storing the file contents in a macro will suffer from the problem that the file itself cannot initiate catcode changes.

Possible solutions (with the above caveats) are presented with, and without, the catchfile package:

  • Without the catchfile package, it is easier to gobble that space early. This is adapted from code on a comp.text.tex thread; I have added a space to the parameter text of \@inputfiledef to gobble it. Note the restrictions of this approach as discussed there. In particular, the file should not contain \ENDMARKER.

    \documentclass{article}
    
    \usepackage{filecontents}
    
    \begin{filecontents*}{tmp.tex}
        \LaTeX{}
    
        and some more text \LaTeX{}\end{filecontents*}
    
    \makeatletter
    \long\def\@inputfiledef#1#2 \ENDMARKER{%<-- added a space here
      \endgroup
      \def#1{#2}%
      \noexpand
    }%
    \long\def\inputfiledef#1#2{%
      \begingroup
      \everyeof{\ENDMARKER}%
      \expandafter\@inputfiledef\expandafter#1#2%
    }%
    \newcommand*{\myinputnospace}[1]{\inputfiledef\myfile{\@@input #1\space}\relax\myfile}
    \makeatother
    
    \begin{document}
        % hopefully doesn't end with a space
        \fbox{\myinputnospace{tmp.tex}}
    
        % illustrate that the line endings are being read (not the case if \endlinechar=\m@one)
        \myinputnospace{tmp.tex}
        %\show\myfile
    \end{document}
    
  • The catchfile package does some magic to use a less likely \ENDMARKER, but this makes it harder for me to see how to extend it to gobble the space, but one can always strip the space from the macro afterwards, as I have done here:

    \documentclass{article}
    
    \usepackage{filecontents}
    
    \begin{filecontents*}{tmp.tex}
        \LaTeX{}
    
        and some more text \LaTeX{}\end{filecontents*}
    
    \usepackage{catchfile}
    \usepackage{trimspaces}
    \makeatletter
    \newcommand*{\myinputnospace}[1]{%
        \CatchFileDef{\myfile}{#1}{}%
        \trim@post@space@in\myfile
        % could also consider trimming a \par from the end if necessary
        \myfile
    }
    \makeatother
    
    \begin{document}
        % hopefully doesn't end with a space
        \fbox{\myinputnospace{tmp.tex}}
    
        % illustrate that the line endings are being read (not the case if \endlinechar=\m@one)
        \myinputnospace{tmp.tex}
        %\show\myfile
    \end{document}
    
share|improve this answer
    
I've taken a look at catchfile before. But I'm still not sure what they add over a simple \def\cmd{\input{file.tex}}. I believe they perform some catcode preparations, but I should note that I want the file content to be scanned within the current catcode regime. –  mhelvens Dec 16 '12 at 12:42
1  
With your command, the contents of the file are not saved in the macro, only the \input command. It is difficult to use \edef, \expandafter and \@@input to do it without issues. As far as I understand, it's up to the user to specify any desired catcode changes in the third argument 'setup' to \CatchFileDef. I left this argument blank to mean use the current regime. But any solution involving storing the file contents in a macro will suffer from the problem that the file itself cannot initiate catcode changes. –  cyberSingularity Dec 16 '12 at 12:57
    
Some very good points! Especially that last point, which kind of prevents me from using the catchfile solution by default. Nonetheless, I could perhaps offer it as an option. –  mhelvens Dec 16 '12 at 13:00
    
@cyberSingularity You could wrap up this in the definition of a command. –  egreg Dec 16 '12 at 13:30
    
@mhelvens: If I understand it correctly, another upshot of that thread I've linked to appears to be that, unless capturing the file in a command, it is not possible to remove the EOF 'token' before it is too late (where by 'too late', I mean resorting to something like \unskip), unless perhaps you are able to introduce a new engine primitive... –  cyberSingularity Dec 16 '12 at 14:43
add comment

Your problem is not the implicit newline at the end, but the explicit newline. For example:

\documentclass{article}
\usepackage{filecontents}
  \begin{filecontents*}{file.tex}
    xyz%
  \end{filecontents*}
  \begin{filecontents*}{file2.tex}
    xyz
  \end{filecontents*}
\begin{document}
  \fbox{\input{file.tex}}
  \fbox{\input{file2.tex}}
\end{document}

The first one has no space, the second one does.

Also, note the filecontents package, which makes using and reusing a document with this environment more convenient.

share|improve this answer
    
Hm... I do still believe that it's the implicit newline you're escaping there with the % char. Just create a file manually with no newlines at all and try to input that one. <>---<> Anyway, your solution would be similar to the one suggested by barbara beeton, which requires me to change the file. For the purpose of this question, I cannot change the file. –  mhelvens Dec 9 '12 at 16:25
    
@mhelvens Ryan is right. The implicit empty line has no effect in this context, because you're building an \hbox and \par does nothing in restricted horizontal mode. –  egreg Dec 9 '12 at 16:49
    
@RyanReich Did you actually test your code there, with xyz\end{filecontents*}? Because for me it still generates a space. –  mhelvens Dec 9 '12 at 17:55
    
@RyanReich Strange. Then we may be using a different version of... something? "pdfTeX 3.1415926-2.4-1.40.13 (TeX Live 2012)" and "filecontents 2011/10/08 v1.3" here. –  mhelvens Dec 9 '12 at 19:21
    
@mhelvens: never mind, it does produce a space. I had made a change elsewhere that canceled it. –  Ryan Reich Dec 9 '12 at 19:25
add comment

I've been able to get a satisfactory behavior by directly following the \input directive with \unskip.

A minimal working example:

\documentclass[margin=1mm]{standalone}

\usepackage{filecontents}

\begin{filecontents}{tmp.tex}
    \LaTeX{}
\end{filecontents}

\begin{document}
    \fbox{\input{tmp.tex}}
    \fbox{\input{tmp.tex}\unskip}
\end{document}

enter image description here

This is not a valid answer to the question, since I now no longer have the option of putting whitespace at the end if I want to. But it's better than nothing.

share|improve this answer
    
You can protect desired whitespace by putting some item after it that, although invisible, is not a skip and therefore makes the "last skip" null. Both \special{} and \penalty0 work, as would \hbox{}. –  Ryan Reich Dec 9 '12 at 16:20
    
@RyanReich Unfortunately, any such addition solution would require me to pollute the input file (which is not under my control). –  mhelvens Dec 9 '12 at 16:29
    
Do you want whitespace at the end, sometimes? –  Ryan Reich Dec 9 '12 at 16:43
    
@RyanReich Ideally, I would faithfully return whatever the user types in my environment (the one I'm developing). What if I wanted to use my environment to demonstrate this exact problem? –  mhelvens Dec 9 '12 at 16:49
    
I always hate to accept my own answer over the answers of others, but in this case using \unskip has been the only solution that gave me an acceptable result. However, if anyone can show me a way that faithfully preserves the exact content of the environment (including whitespace, or lack thereof), I'd happily give them the points. –  mhelvens Dec 16 '12 at 11:12
add comment

Have you looked at using \lstinputlisting (from the listings package) or \VerbatimInput from the fancyvrb package? They both give you powerful ways of reading in files and formatting them as desired.

share|improve this answer
    
That is indeed a good way to typeset LaTeX code from a file. But in this case I'm looking for a way to actually interpret the LaTeX code (without the annoying endline there). –  mhelvens Dec 9 '12 at 16:01
add comment

try adding \endinput as the last line of the file to be \input. this will cause anything that follows to be ignored. in fact, you can add anything you want following \endinput, which makes it useful for including notes to yourself.

it's also probably a good idea to end the last "real" line of your file with a % to avoid even that newline.

\endinput is a tex primitive, and often isn't mentioned in latex manuals.

share|improve this answer
    
Very useful! But not exactly what I'm looking for. Why? Because I want to be able to 'retrieve' the content of that file in multiple ways, not just a simple \input. While your suggestion solves my immediate problem, it would cause unwanted output when the user of my package tries to typeset the content of the file with listings, for example. So for the purpose of this question, I cannot change the content of the file. –  mhelvens Dec 9 '12 at 16:05
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.