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 in need of a macro which receives a control sequence as argument to test if this control sequence is actually an \outer macro. I can code it myself as below .

\documentclass{minimal}
\usepackage{expl3}
\ExplSyntaxOn
\group_begin:
\char_set_lccode:nn { `\; } { `\: }
\char_set_lccode:nn { `\Z } { `\t }
\char_set_lccode:nn { `\T } { `\T }
\char_set_lccode:nn { `\F } { `\F }
\tl_map_function:nN { O U Z E R M A C R ; } \char_set_catcode_other:N
\tl_to_lowercase:n
  {
    \group_end:
    \prg_new_conditional:Nnn \cs_if_outer_macro:c { p, T , F , TF }
      {
        \exp_last_unbraced:Nf \cs_if_outer_macro_aux:w
        \cs_meaning:c {#1} OUZER ~ MACRO ; \q_stop
      }
    \cs_new_nopar:Npn \cs_if_outer_macro_aux:w #1 OUZER ~ MACRO ; #2 \q_stop
      {
        \prg_case_str:xxn { #1 ~ }
          {
            { \token_to_str:N \ }
            { \prg_return_true: }
            { \token_to_str:N \long \token_to_str:N \ }
            { \prg_return_true: }
            { \token_to_str:N \protected \token_to_str:N \ }
            { \prg_return_true: }
            { \token_to_str:N \protected \token_to_str:N \long \token_to_str:N \ }
            { \prg_return_true: }
          }
          { \prg_return_false: }
      }
  }
\cs_new_eq:NN \IfOuterMacroTF \cs_if_outer_macro:cTF
\ExplSyntaxOff

\long\outer\protected\def\fooa{}
\outer\def\foob{}
\def\fooc{}
\def\food{outer macro:}

\typeout{It's \IfOuterMacroTF{fooa}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{foob}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{fooc}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{food}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{relax}{}{NOT }an outer macro.}

It is inspired by the l3token package. The test is expandable. I have used it in the xeCJK package. But, it only receives the csname instead of control sequence. What is more, I think it is a bit slow.

I think it is a good question and like to see other possible approaches.

share|improve this question
    
A macro cannot receive an outer token as an argument: TeX will raise an error. –  Joseph Wright May 25 '12 at 18:18
    
@MarcoDaniel I meant you can't do \outer\def\foo{}\def\baz#1{}\baz\foo, i.e. pass an outer token as an argument. –  Joseph Wright May 25 '12 at 18:53
    
@QingLee: for completeness about \outer tokens, you also have to be careful about \foo defined by \halign{#\cr\global\futurelet\foo\relax\cr}. Its \meaning is \outer endtemplate: and it indeed is outer. –  Bruno Le Floch Jul 17 '12 at 16:04

1 Answer 1

This is not expandable, but maybe the test can be modified to be:

\documentclass{article}
\usepackage{expl3,l3regex}

\ExplSyntaxOn
\cs_new_protected:Npn \isouter { \exp_after:wN \checkouter:w \token_to_meaning:N }
\cs_new:Npn \checkouter:w #1 \relax
  {
   \regex_match:nnTF { outer .* macro .* :-> } { #1 } 
    { \typeout{OUTER~MACRO} } 
    { \typeout{NON~OUTER~TOKEN} }
  }
\ExplSyntaxOff

\outer\def\bye{bye}

\isouter\bye\relax

\stop

However this test can't be used in arguments to other macros, because of the rule mentioned by Joseph Wright.

share|improve this answer
    
Thakns! But the test will be true when \def\bye{outer macro:->}. –  Qing Lee May 25 '12 at 21:03
    
@QingLee Yes: I don't think one can do much about this. –  egreg May 25 '12 at 21:05
    
does Bruno support ^ to anchor the regexp to start of string, in which case you could use that as the trick case would have meaning macro:->outer macro.... –  David Carlisle May 26 '12 at 9:57
    
@DavidCarlisle yes. –  Bruno Le Floch May 26 '12 at 23:15

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.