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'm using ConTeXt, but I suspect the answer will lie in plain TeX.)

I've created an environment that takes one argument myBufferName, and stores its contents in a buffer of that name. Unfortunately, all spaces after the argument are gobbled, and I don't know how to stop this properly. The usual gobble-stoppers, {} and \, end up in the buffer verbatim if I put them after \dostartbuffer.

\startluacode
    -- Print contents of buffer b to stdout and tmp.txt for inspection
    function printbuffer(b)
        -- Once to stdout ...
        print('====') 
        print(buffers.getcontent(b))
        print('====')

        -- ... and once to tmp.txt.
        jan = io.open('tmp.txt', 'w')
        jan:write(buffers.getcontent(b))
        jan:close()
    end
\stopluacode

% This environment stores its contents in a custom-named buffer.
% (The #1 merely allows whitespace, like this: `\startMyBuffer [name]`)
\def\startMyBuffer#1[#2]
    {% Store the name --- we'll need it when defining stopMyBuffer
     \def\myBufferName{#2}
     % ConTeXt macro that defines the \start... and \stop... commands.
     \dostartbuffer[#2][startMyBuffer][stopMyBuffer]}

%% % Hack I currently use: a dot at the end of the definition.
%% \def\startMyBuffer#1[#2]
%%     {\def\myBufferName{#2}
%%      \dostartbuffer[#2][startMyBuffer][stopMyBuffer].}
%% %                                                   ^
%% %                                                   |
%% % I later remove the dot using Lua.

% On closing the buffer, print its contents.
\def\stopMyBuffer
    {\ctxlua
        {printbuffer('\myBufferName')}}

% Test it. You'll see the first line loses its leading whitespace :-(
\starttext
\startMyBuffer[myNameIsNobody]
    Andra moi ennepe,
        mousa, 
    polutropon.
\stopMyBuffer
\stoptext

When you try running it, this gives

Andra moi ennepe,
        mousa,
    polutropon.

as the buffer's contents.

share|improve this question
add comment

3 Answers

up vote 10 down vote accepted

You define the macro as

\def\startMyBuffer#1[#2]
     {....}

To avoid the macro eating spaces, use

\def\startMyBuffer#1[#2]%
    {...}

(Note the % at the end. You also have a trailing whitespace at the end of the next line. Thus, a proper definition of the macro is

\def\startMyBuffer#1[#2]%
    {% Store the name --- we'll need it when defining stopMyBuffer
     \def\myBufferName{#2}% <<<<---- ADDED THS
     % ConTeXt macro that defines the \start... and \stop... commands.
     \dostartbuffer[#2][startMyBuffer][stopMyBuffer]}

If you don't want to worry about all this, use \starttexdefinition ... \stoptexdefinition instead.

\starttexdefinition startMyBuffer #1[#2]
   % Store the name --- we'll need it when defining stopMyBuffer
   \def\myBufferName{#2}
   % ConTeXt macro that defines the \start... and \stop... commands.
   \dostartbuffer[#2][startMyBuffer][stopMyBuffer]
\stoptexdefinition
share|improve this answer
    
Tried them both, they both work a treat. Thank you! –  Esteis Feb 19 '12 at 22:04
add comment

The general syntax of \def is

\def<name><parameter text>{<replacement text>}

, where <parameter text> is matched against input. The parameter text can contain parameter tokens (#1, #2, …) and other tokens, for example, #1[#2]abc. Other tokens are matched exactly against input — in this example, if TeX fails to find a sequence <something>[<something>]abc, it will stop with an error. After a match has been found, the <something> parts will be taken as macro parameters per parameter text definition, but the other matched tokens will be simply eaten. In your case the parameter text of \startMyBuffer contains space after [#2], thus it will be also matched and eaten.

Look at the output of this Plain TeX document to see the difference:

\def\readsome#1\relax{`#1'}    
\def\a[]
    {\readsome}    
\def\b[]{\readsome}

\a[]
    test\relax
\b[]
    test\relax

\bye

Conclusion: don't put extraneous symbols in macro parameter text. For Plain TeX/LaTeX, let { follow immediately after all parameters have been specified; for ConTeXt, put a % after the parameter text to ignore the newline and the following space.

share|improve this answer
1  
In ConTeXt, the standard style is to add a % on the \def line and put { on the next line. –  Aditya Feb 15 '12 at 17:21
    
@Aditya: Thanks, good to know. –  Andrey Vihrov Feb 15 '12 at 18:13
add comment

I'm not sure if I understand your question correctly, but you seem to indicate that you don't want TeX to gobble whitespace. If that's what you're after, check out the commands \obeyspaces (Plain TeX) and \obeywhitespace (eTeX).

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.