10

I'm generating LaTeX code and, as such, am faced with the difficulty to preserve spaces between inserted LaTeX commands and ensuing text. They way I'm doing it now is as suggested by the answer to a similar question, i.e. by always placing a pair of empty braces {} after the command.

For example, assuming that there is a definition \newcommand{\arnold}{Arnold Schwarzenegger}, a source text xxx $foo is a xxx, and $foo stands in for \arnold, I'm translating the source to xxx \arnold{} is a xxx.

I'm aware of the fact that I could use xxx {\arnold} is a xxx which should be much safer (syntactically speaking)—but that would make it impossible to insert a begin-group here and an end-group there, which is an essential must-have for me.

Also, the xspace package is not a solution since I do not control what commands users would want to insert into their scripts, and I'm not even going to think about re-defining/wrapping existing commands—given the mad complexity of TeX's inner workings (which is often compared to digestion or the outcome of it), such an approach is best left for parallel worlds with unlimited resources to attempt. (What's more, Dave Carlisle himself recommends not to use xspace, so thanks, but no, thanks.)

This works to preserve the space (or lack thereof) in this particular case; however, I'm worried that some funky (La)TeX command might happen to be defined so that \foo x and \foo{} x (or \bar{argument} x and \bar{argument}{} x) turn out to produce different things.

In case that should turn out to be impossible or not so by chance, I'm fine to leave it at that; but if there are such critical commands, what alternative device could I use?

Edit Thanks to the info provided by One Well-Known TeXpert, below, I now know that the first option is no more: I want users to be able to insert arbitrary TeX fragments into their scripts, and those should always work as expected provided the entirety of the generated TeX makes sense. You can define macros so that absence vs. presence of ensuing {} does make a difference, so someone will have done that already; therefore, transparently inserting {} might cause unexpected things to happen.

IOW, I'm in need of an alternative solution—preferrably one that works in math mode as well, but I could live with treating math mode specially, because, well, because math mode has always been like a whole other thing in TeX anyways, and I can put suitable restrictions and content-checks in place to take care of that situation.

  • Not sure if relevant here, but perhaps package xspace can be useful. – JLDiaz Oct 13 '15 at 20:53
  • @JLDiaz see my edit; not a solution because it must work with existing commands. – flow Oct 13 '15 at 21:02
  • I'm sure this is a duplicate (i'll see if I can find) but {} is safe enough in text mode most of the time, don't use it in math mode though. This assumes that you know \foo doesn't take arguments, or doesn't end with \ignorespaces or have other special handling/ – David Carlisle Oct 13 '15 at 21:04
  • just as i edited your name into my question! I might not know whether I'm in math mode, so that could bring problems, and i definitely do not know whether a given command takes arguments :-(. If \ignorespaces means that the command should never render following spaces, that'd be OK, because it's the expected outcome to swallow spaces. But that thing about whether a command takes arguments, that's a huge stumble block. I need something foolproof that will always work. – flow Oct 13 '15 at 21:15
  • If you do not know if the command takes arguments you are doomed. if the command is \fbox and you change \fbox {abc} to \fbox{} {abc} then you will box the wrong thing, You have to know something about the argument structure, or it is a non-starter. – David Carlisle Oct 13 '15 at 21:24
13

If you know \foo does not take arguments and is not in math mode then

\foo{}

is safe enough.

You also mentioned the case where the command does have arguments

\bar{argument}{}

But there the {} can not possibly do anything useful as spaces would not be dropped after {argument} anyway, so best not to add them in that case.

It is easy to define \foo in a way that this does affect things

\def\foo{\@ifnextchar\bgroup{yes}{no}}

for example will make \foo a say no and \foo{} a say yes. But if you are doing that, you presumably intend that to happen.

An empty brace group {} in math mode can affect spacing, compare ${}-1$ and $-1$ so it is best not to add {} in math mode, but as spaces are ignored in math mode, the issue of spaces after command names does not apply anyway.


one possibly safer alternative is to use

\IeC{\foo}

which is the commad inputenc uses for this purpose.

aaaa    \IeC{\foo}  bbbb

will work as will

aaa \IeC{\bar}{argument} aaa

\IeC is more or less \def\IeC#1{#1} apart from some checing about \protect (which you could also use)

If you haven't loaded inputenc it is:

\def\IeC{%
  \ifx\protect\@typeset@protect
    \expandafter\@firstofone
  \else
    \noexpand\IeC
  \fi
}
  • @flow see update – David Carlisle Oct 13 '15 at 21:32
  • I really hope another way is suggested because with this solution I'd have to parse TeX source myself OMG... But thanks a ton for the suggestion I might give it a try. – flow Oct 13 '15 at 21:41
  • @flow ???? why? Just write \IeC{\foo} instead of \foo what extra parsing do you see? – David Carlisle Oct 13 '15 at 21:44
  • Well, if users are allowed to put any kind of LaTeX fragment into the <<...>> fences, then the last command in that fragment may be arbitrarily difficult to find either from the left or the right edge of that span, given that an arbitrary number of commands with arbitrary and possibly nested arguments might be used. But I'm already thinking of another, much simpler solution if there's no very good answer to this problem. – flow Oct 13 '15 at 22:49
2

Because reactions to this question have subsided, and the only candidate answer—helpful as it is indeed—does not show a solution that I'm ready or able to adopt, I'll answer my own question here.

Slightly rewording my original post, the issue at hand is: given a string of TeX source XYZ, where X and Z are parts that you do control and Y is an inserted stretch of arbitrary (but presumably valid) TeX code that you don't control, how can you make it so that (should Z start with whitespace) whitespace will be preserved after Y no matter what Y ends with?

Through the present discussion and web search convinced me that there's no fool-proof, fail-safe way to do this in the general case short of parsing the intermediate stretch Y and reverse-engineer its workings. Needless to say, this is way too hard, too error-prone, and—as programmers will tell you—also limited to what you can possibly do with static code analysis (of course, there are solutions for specific cases and solutions for macro authors).

The solution I have adopted is to do nothing, meaning that the responsibility to deal with whitespace at the Y/Z boundary has been, so to speak shifted from Z to Y, i.e. whoever writes macros for inclusion in my TeX-generating software and whoever writes texts using it is responsible to look out for proper whitespace handling, the software will not do anything here (which may be a good thing after all because it follows the principle of least surprise).

  • despite being devastated at not getting the green tick, I agree with this. See tex.stackexchange.com/a/86620 for some thoughts on macros that try to be clever about white space, that apply here probably. – David Carlisle Oct 21 '15 at 14:58
  • I'm sorry as for the green tick but your answer was not a suitable solution for me, rather, it showed me that not doing anything instead of trying to be clever is the way to go. I upvoted your answer as a little thank you for the really helpful things you pointed out. – flow Nov 13 '15 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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