8

If I have a macro that works like this, inside the braces:

{\SomeMacro applies to this text}

I can easily do this:

\newcommand\MySomeMacro[1]{{\SomeMacro #1}}

Then the new command goes outside the braces:

\MySomeMacro{applies to this text}

I can also use \let to re-define the original macro, via an intermediary.

My question: Can it be done the other way around? That is, if I already have a macro that is used outside the braces, can I re-define it (or create a new macro) that does the same thing, but inside the braces?

I am using LuaTeX on TeXlive 2016, but surely this is a rather basic question, applicable to anything. Also, in my particular case, the argument of the macro is very simple, usually plain text.

Why I would like to do this: I am working with a document, in which most of the user commands go inside the braces. For consistency in writing, I would like to define my own commands so that they work the same way. Re-defining the original commands, so that they go outside the braces, might confuse someone who is editing my document.

  • while this is possible it seems very weird thing to do, commands like \bfseries do not pick up an argument from a surrounding group they are a state change just acting at the point of the command. To take a command that has an argument like \section{abc} and change its syntax so {zzzz \newsection abc} works (but \begin{figure} zzzz \newsection abc\end{figure} gives a parse error) obscures the underlying operation of the command. – David Carlisle Dec 06 '16 at 17:27

2 Answers2

7

If you want to input, for instance

{\macro argument or whatever}

and want TeX to convert that to

\command{argument or whatever}

to get all the flexibility of an easily defined command with one argument, you can do

\def\macro{\aftergroup\command\aftergroup{}}
\def\command#1{Whatever you whant to do with the argument [#1].}

What does this do?

Your code {\macro argument} will open a group { and then expand \macro, which expands to \aftergroup\command\aftergroup{}. In turn, \aftergroup makes sure the next token is inserted exactly after closing the group, so \aftergroup\command ensures that when you close the group \command is there, and \aftergroup{ ensures that \command{ is there when you close a group. Then, you close the group with the following } leaving your code with \command{argument}.

Manuel
  • 27,118
  • This is weird, since one would think the argument is processed and forgotten (since TeX found \macro and not \command), yet somehow it ends up as the argument to \command. – Werner Dec 06 '16 at 17:03
  • 1
    @Werner the trick is that the group started by { is finished by \macro not by the } at the end of the "argument" so the switch to \command happens before the argument is scanned. – David Carlisle Dec 06 '16 at 18:41
  • 1
    @Werner Roughly, \macro “expands” to }\command{. So {\macro arg} is converted to {}\command{arg}. – Manuel Dec 06 '16 at 19:06
  • I accepted this one, because it works and is simple. The situation at hand is also simple (I hope). Did not test it with exotic argument, because it is not necessary in my case. –  Dec 06 '16 at 19:33
  • 1
    @RobtA It's not the argument that needs to be exotic but the context, not the fault of Manuel but \parbox{6cm}{abc \macro xyz} will fail as will \begin{center} abc\macro xyz\end{center} the number of places where you can use \macro and not result in an error or in lost text is strictly limited. – David Carlisle Dec 06 '16 at 19:44
  • @DavidCarlisle OK, I'll keep that in mind, and also have a deeper look at egreg's solution. TeX being TeX, I always have to think about whether things are better left alone. –  Dec 06 '16 at 21:17
  • How to create \SomeCommand{and \SomeOtherCommand{apply to this text}} from {\SomeMacro and \SomeOtherMacro apply to this text}? (I think teaching people to distinguish scope delimiting braces from macro argument braces might be a better approach.) – Ulrich Diez Dec 06 '16 at 21:24
  • @egreg's solution is same as this one from this point of view. You should accept Manuel's solution as it's a nice code and answers your question but you shouldn't do this in a real docuemnt. – David Carlisle Dec 06 '16 at 21:36
  • @UlrichDiez As David said, you can't leave braces out. {\one and {\two apply to this text}} will usually work and give \ONE{and \TWO{apply to this text}}. You just can't leave braces out, they are part of the syntax in this case. E.g., you can't do \foo{\macro argument} and expect it to work, it's much more probable that \foo{{\macro argument}} works. Remember that { } are part of the syntax here. Of course, this is not entirely secure (I didn't even made the macros \protected). – Manuel Dec 06 '16 at 21:54
  • 1
    @UlrichDiez In any case you can (probably) make your suggestion work by just adding braces around the #1 inside each command of this type (for instance \def\command#1{Do something with [{#1}].}). Of course, as this whole idea, it's not ensured that it will work everytime. – Manuel Dec 06 '16 at 22:00
  • @Manuel I did not suggest anything. I was nagging. If I got it right, the efforts aim at providing a syntax to users that is easy. One the one hand I like your \aftergroup-trick. On the other hand I fear that in the end a syntax where each single command plus the things which it shall be applied to must go inside another pair of braces might turn out rather confusing to many people. – Ulrich Diez Dec 06 '16 at 22:16
  • @UlrichDiez By suggestion I meant the example you wrote. In any case, here it is unformatted a “general” macro to define this kind of commands:\protected\def\weirddef#1{\protected\def#1{\expandafter\aftergroup\csname inn1\string#1\endcsname\aftergroup{}}\protected\expandafter\def\csname inn1\string#1\endcsname##1{\csname inn2\string#1\endcsname{{##1}}}\protected\expandafter\def\csname inn2\string#1\endcsname} and then use \weirddef\foo#1{[#1]} \weirddef\baz#1{(#1)} and use like {\foo this \baz that}. – Manuel Dec 06 '16 at 22:52
4

The real solution depends on how \commandwitharg is defined. A general solution allowing

 <open group>\noarg text<close group>

is really very difficult to find, if at all possible.

Here's an alternative solution to Manuel's, which is slicker:

\documentclass{article}

\newcommand\commandwitharg[1]{---#1---}

\newcommand{\noarg}{%
  % close the group
  \egroup                  
  % the first \expandafter removes \iftrue
  % the second \expandafter removes \else
  \expandafter\expandafter\expandafter
  \commandwitharg\iftrue\expandafter{\else}\fi 
}

\begin{document}

\commandwitharg{ABC}

{\noarg ABC}

\end{document}

Don't hope to be able to have \begingroup\noarg text\endgroup: only {\noarg text} will work.

It is much better to use a text editor and simply do the change

{\noarg<space>

to

\commandwitharg{

Finally, knowing the real definition of \commandwitharg and its use cases, can lead to a better solution.

egreg
  • 1,121,712
  • 2
    but I want to do \begin{center} \noarg ABC \end{center} ..... – David Carlisle Dec 06 '16 at 17:29
  • 1
    @DavidCarlisle Go away! – egreg Dec 06 '16 at 17:39
  • I will test all of the above, and report back. Perhaps my question is trickier than I thought it would be. Rather like asking, "If taking derivatives is so easy, then why are integrals so hard? Aren't they just the reverse of each other?" –  Dec 06 '16 at 18:29
  • 3
    @RobtA a better analogy might be like saying if making scrambled eggs is easy why can't I make an egg out of scrambled egg, aren't they just reverse of each other. – David Carlisle Dec 06 '16 at 18:43
  • @DavidCarlisle Oh, I thought mathematicians were the main users here. Thought they'd understand math, but not eggs. –  Dec 06 '16 at 19:35
  • The solution by egreg may indeed be more general, but my own situation is fairly simple. Anyway, anything involving \expandafter gives me the shivers. –  Dec 06 '16 at 19:36
  • @DavidCarlisle I want to do this too. Besides this I want to do {\noargA ABC \noargB DEF \noargC GHI } – Ulrich Diez Dec 06 '16 at 21:29