27

Using \@ifnextchar one can detect if e.g. the next Character is a [, e.g.:

\@ifnextchar[%
{
    %% code to execute if [ scanned.
}{
    %% code to execute if [ scanned.
}

However, I can’t seem to use \@ifnextchar{ to test if the next Character is {.

Is there any way to use \@ifnextchar to detect a {?

Is there any way at all to detect a {?

If so, please let me know.


Update 1: Okay, I think that \bgroup is a successful Answer. I think I know now (sort of) why it didn’t work when I first used it.

The Purpose I needed it for was to be able to have a Macro that can take an indefinite Number of Arguments. (E.g. listing out Authors.) These seems to run into issues once we want to place the resulting String in an Header.


Update 2: Regarding my secondary Problem (which was my original Application for all of this), is there a way to delay Commands in TeX. In particular, I want to first run a Macro which waits for an arbitrary Amount of Arguments, then run a second Command on this.

Here is the kind of thing I’m trying to do:

\def\headerauth#1{\rhead{#1\ifnextchar\bgroup{\@headerauth}{.}}}

\def\@headerauth#1{\& #1\ifnextchar\bgroup{\@headerauth}{.}}}

Without the \rhead, Things work fine. But once I use \rhead, it will only read the first Argument. The others are ignored. E.g.

\headerauth{S. Mishkin}{L. Polotov}

results in »S. Mishkin.« being placed in the Header, and »L. Polotov« placed in the main Text.

Whereas if I define \headerauth omitting the \rhead, and then use:

\rhead{\headerauth{S. Mishkin}{L. Polotov}}

I obtain »S. Mishkin & L. Polotov.« in the Header as desired.

Why doesn’t the first Thing work? (I realise that this Question probably belongs to a new Topic…)

P.s. *@doncherry* & @Yossi Farjoun: I’ve figured it out — turns out I was using the wrong Key Combination to access the ` Symbol on my Keyboard. (The same Key produces `'˚´ depending on Key Combinations.) (Took me a short while to figure out how to quote-not-use the Symbol ` (as well as \) via \` and \\ — ah, the Standard coding Tricks. Glad to see it’s very logical.)

R47
  • 273
  • Welcome to TeX.sx! A tip: You can use backticks ``` to mark your inline code as I did in my edit. – doncherry Nov 02 '11 at 14:08
  • This question should probably be tagged with [tag:tex-core] or [tag:latex-kernel], I don't know which one is appropriate. – doncherry Nov 02 '11 at 14:09
  • @doncherry I'd agree: the question is about the LaTeX kernel, I guess, but the reasoning is a TeX core concept. – Joseph Wright Nov 02 '11 at 14:20
  • @R47: Sorry if I wasn't clear: Your block code had already been properly marked as code; if you look at revision 2, I inserted backticks \`` (not apostrophes') where you referred to code within a line of normal text; so the source code of your first few words is ``Using@ifnextchar` one``. For more information, check out http://tex.stackexchange.com/editing-help#code, http://meta.tex.stackexchange.com/questions/863/how-do-i-mark-inline-code, and http://meta.tex.stackexchange.com/questions/1192/how-do-i-mark-code-blocks. – doncherry Nov 02 '11 at 14:39
  • Yes I knew you meant that Symbol. It’s just that on my Keyboard the Button which looks like the Backtick seems to produce '. I have ‘'´ but no Backtick, sorry. – R47 Nov 02 '11 at 14:46
  • @JosephWright IMHO better to use both tags for these with latex-kernel first. – yannisl Nov 02 '11 at 14:50
  • @YiannisLazarides: You can't influence the order of the tags, [tag:tex-core] will likely stay the first tag for a while: http://meta.stackexchange.com/questions/87508/are-the-tags-shown-in-a-particular-order – doncherry Nov 02 '11 at 14:53
  • @R47: Then you could always copy-and-paste the backtick from any of the pages I referred to you. – doncherry Nov 02 '11 at 14:54
  • 1
    @R47:not having the backtick could be a problem for someone who wants to use LaTeX...I suggest that you find a keyboard layout (or keyboard) that has one... – Yossi Farjoun Nov 02 '11 at 19:08

1 Answers1

27
\@ifnextchar\bgroup

See the definition of \input in the kernel:

\def\input{\@ifnextchar\bgroup\@iinput\@@input}

where \@iinput is able to cope with \input{file} and \@@input is an alias for the primitive \input so \input file will be processed as well.

\@ifnextchar has three arguments: (1) the token to be looked for, (2) what to do if it's found, and (3) what to do if the token is not there. After storing the arguments, it makes TeX look at the following token (not argument) and compares it (with \ifx) to the stored first argument. In case #1 is \bgroup it compares successfully to an open brace because of the statement given in the kernel

\let\bgroup={

This doesn't mean that \bgroup can be always used as a substitute for an open brace; it's allowed for this purpose only in some particular cases. This is exploited, for instance, in the definition of minipage or lrbox. For comparison purposes, \bgroup is the right substitute of {, as it can be seen by TeX as an argument for a macro.

Suppose we want to do something different when macro \xyz is followed by an open brace or not; say we want to support the syntaxes

\xyz{abc}
\xyz abc\stopxyz

using abc as the argument. Then we would do

\newcommand{\xyz}{\@ifnextchar\bgroup\@xyzb\@xyz}
\def\@xyz#1\stopxyz{\@xyzb{#1}}
\def\@xyzb#1{do something with #1}

This can also be used to define a macro with an "unknown" number of arguments, say a list of authors to go in the header:

\def\authorslist{\ignorespaces} % initialization
\def\authors#1{\g@addto@macro\authorslist{ #1}\@ifnextchar\bgroup\authors{}}

\fancyhead[R]{\authorslist}

The macro \authors appends its argument to the list (initialized so as to ignore the space before the first author) and then execute again itself until there's not a brace any more (when it does nothing).

egreg
  • 1,121,712
  • 7
    Here, \bgroup is an 'implicit' token. It's a copy of {, but as it is not { does not count toward the number of braces used in the 'container' macro, so can be used in places where { cannot. Also, \@ifnextchar needs to be able to absorb the search token as an argument, which again requires that you don't use a literal {. – Joseph Wright Nov 02 '11 at 14:20
  • I tried \bgroup, but yield no luck. I used

    '\def\test#1{#1 @ifnextchar\bgroup{yes}{no}} '\test{first}{second}

    which outputs:

    'first no

    – R47 Nov 02 '11 at 14:22
  • @R47 See edited answer – egreg Nov 02 '11 at 14:29
  • Okay, that one works now: I had made some other mistake. But I still cannot yield any success with the following:

    '\def\authors#1{\fancyhead[R]{#1 @ifnextchar\bgroup{@einmehr}{}}} '\def@einmehr#1{& #1 @ifnextchar\bgroup{@einmehr}{}}}

    – R47 Nov 02 '11 at 14:32
  • 1
    @R47 Please, edit your original question instead of putting code in comments. – egreg Nov 02 '11 at 14:34
  • You can find a real example in the definition of frame environment of beamer class. See the definition of \beamer@checkframetitle in beamerbaseframe.sty. – Leo Liu Nov 02 '11 at 15:23
  • @R47: Usually \@ifnextchar\bgroup is the way to go, but keep in mind that this also works if the macro is followed by \bgroup not only by {. I have code in my collcell package where I first do this test, then read the next token and check if it is \bgroup or something else. In the second case it really was a {. – Martin Scharrer Nov 02 '11 at 15:37