Изменен \IfStrEqCase с несколькими совпадениями на случай

Изменен \IfStrEqCase с несколькими совпадениями на случай

Я часто использую xtring's \IfStrEqCaseдля условной обработки. Это работает отлично, но интересно, есть ли простой способ улучшить текущее поведение и позволить группировать несколько случаев в одно совпадение.

В MWE ниже вывод для case 1, case 3и case 4идентичен, но мне приходится дублировать текст в нескольких местах. Когда этот текст длинный, он довольно подвержен ошибкам, поэтому было бы неплохо иметь возможность объединить их все вместе в синтаксисе, похожем на:

\IfStrEqCaseModified{#1}{% <--- Need to define this
    {{case 1}{case 3}{case 4}}{%
        some long text which is identical for case 1, case 3 and case 4.%
    }%
    {{case 2}{case 5}}{%
        other text for case 2 and case 5.%
    }%
}[{Error: Unknown parameter ``#1'' to ConditionalTextDesired}]%

Использованная литература:

Примечания:

  • Одним из решений, конечно, было бы определение макроса

    \newcommand{\RepeatedText}{some long text which is identical for case 1, case 3 and case 4.}
    

    но предпочел бы этого избежать, если это возможно.

Код:

\documentclass{article}
\usepackage{xstring}

\newcommand*{\ConditionalText}[1]{%
    \IfStrEqCase{#1}{%
        {case 1}{%
            some long text which is identical for case 1, case 3 and case 4.%
        }%
        {case 2}{%
            other text for case 2 and case 5.%
        }%
        {case 3}{%
            some long text which is identical for case 1, case 3 and case 4.%
        }%
        {case 4}{%
            some long text which is identical for case 1, case 3 and case 4.%
        }%
        {case 5}{%
            other text for case 2 and case 5.%
        }%
    }[{Error: Unknown parameter ``#1'' to ConditionalText}]%
}%

\newcommand*{\ConditionalTextDesired}[1]{%
    \IfStrEqCaseModified{#1}{% <--- Need to define this
        {{case 1}{case 3}{case 4}}{%
            some long text which is identical for case 1, case 3 and case 4.%
        }%
        {{case 2}{case 5}}{%
            other text for case 2 and case 5.%
        }%
    }[{Error: Unknown parameter ``#1'' to ConditionalTextDesired}]%
}%


\begin{document}
    \par\ConditionalText{case 1}
    \par\ConditionalText{case 2}
    \par\ConditionalText{case 3}
    \par\ConditionalText{case 4}
    \par\ConditionalText{case 5}

    %\bigskip\par
    %This should produce identical output
    %\par\ConditionalTextDesired{case 1}
    %\par\ConditionalTextDesired{case 2}
    %\par\ConditionalTextDesired{case 3}
    %\par\ConditionalTextDesired{case 4}
    %\par\ConditionalTextDesired{case 5}
\end{document}

решение1

Медленно, но работает. Код обрабатывает входные данные, чтобы сделать их приемлемыми для\str_case:nnTF

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\cs_new_protected:Nn \grill_str_multicase:nnTF
 {
  \seq_set_split:Nnn \l__grill_str_multicase_cases_seq { } { #2 }
  \tl_clear:N \l__grill_str_multicase_cases_tl
  \int_step_inline:nnnn { 1 } { 2 } { \seq_count:N \l__grill_str_multicase_cases_seq }
   {
    \seq_set_split:Nnx \l__grill_str_multicase_subcases_seq { }
     { \seq_item:Nn \l__grill_str_multicase_cases_seq { ##1 } }
    \seq_map_inline:Nn \l__grill_str_multicase_subcases_seq
     {
      \tl_put_right:Nx \l__grill_str_multicase_cases_tl
       {
        {\exp_not:n{####1}}{\seq_item:Nn \l__grill_str_multicase_cases_seq { ##1 + 1}}
       }
     }
   }
   \str_case:nVTF { #1 } \l__grill_str_multicase_cases_tl { #3 } { #4 }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\cs_new_protected:Nn \grill_str_multicase:nn
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { } { }
 }
\cs_new_protected:Nn \grill_str_multicase:nnT
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { #3 } { }
 }
\cs_new_protected:Nn \grill_str_multicase:nnF
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { } { #3 }
 }

\NewDocumentCommand{\IfStringCaseX}{mmo}
 {
  \IfNoValueTF{#3}
   { \grill_str_multicase:nn { #1 } { #2 } }
   { \grill_str_multicase:nnF { #1 } { #2 } { #3 } }
 }
\ExplSyntaxOff

\newcommand{\ConditionalText}[1]{%
  \IfStringCaseX{#1}
   {
    {{case 1}{case 3}{case 4}}
    {%
     some long text which is identical for case 1, case 3 and case 4.%
    }
    {{case 2}{case 5}}
    {%
     other text for case 2 and case 5.%
    }%
   }[{Error: Unknown parameter ``#1'' to ConditionalText}]%
}

\begin{document}

\ConditionalText{case 1}

\ConditionalText{case 2}

\ConditionalText{case 3}

\ConditionalText{case 4}

\ConditionalText{case 5}

\ConditionalText{case 6}

\end{document}

введите описание изображения здесь

Использование переменных может быть реализовано:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\cs_new_protected:Nn \grill_str_multicase:nnTF
 {
  \seq_set_split:Nnn \l__grill_str_multicase_cases_seq { } { #2 }
  \tl_clear:N \l__grill_str_multicase_cases_tl
  \int_step_inline:nnnn { 1 } { 2 } { \seq_count:N \l__grill_str_multicase_cases_seq }
   {
    \seq_set_split:Nnx \l__grill_str_multicase_subcases_seq { }
     { \seq_item:Nn \l__grill_str_multicase_cases_seq { ##1 } }
    \seq_map_inline:Nn \l__grill_str_multicase_subcases_seq
     {
      \tl_put_right:Nx \l__grill_str_multicase_cases_tl
       {
        {\exp_not:n{####1}}{\seq_item:Nn \l__grill_str_multicase_cases_seq { ##1 + 1}}
       }
     }
   }
   \str_case:nVTF { #1 } \l__grill_str_multicase_cases_tl { #3 } { #4 }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\cs_new_protected:Nn \grill_str_multicase:nn
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { } { }
 }
\cs_new_protected:Nn \grill_str_multicase:nnT
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { #3 } { }
 }
\cs_new_protected:Nn \grill_str_multicase:nnF
 {
  \grill_str_multicase:nnTF { #1 } { #2 } { } { #3 }
 }
\cs_generate_variant:Nn \grill_str_multicase:nn { o }
\cs_generate_variant:Nn \grill_str_multicase:nnF { o }

\NewDocumentCommand{\IfStringCaseX}{mmo}
 {
  \IfNoValueTF{#3}
   { \grill_str_multicase:nn { #1 } { #2 } }
   { \grill_str_multicase:nnF { #1 } { #2 } { #3 } }
 }
\NewDocumentCommand{\IfStringCaseXO}{mmo}
 {
  \IfNoValueTF{#3}
   { \grill_str_multicase:on { #1 } { #2 } }
   { \grill_str_multicase:onF { #1 } { #2 } { #3 } }
 }
\ExplSyntaxOff

\NewDocumentCommand{\ConditionalText}{sm}{%
  \IfBooleanTF{#1}{\IfStringCaseXO{#2}}{\IfStringCaseX{#2}}%
   {
    {{case 1}{case 3}{case 4}}
    {%
     some long text which is identical for case 1, case 3 and case 4.%
    }
    {{case 2}{case 5}}
    {%
     other text for case 2 and case 5.%
    }%
   }[{Error: Unknown parameter ``#2'' to ConditionalText}]%
}
\ExplSyntaxOff

\begin{document}

\ConditionalText{case 1}

\ConditionalText{case 2}

\ConditionalText{case 3}

\ConditionalText{case 4}

\ConditionalText{case 5}

\ConditionalText{case 6}

\def\casesix{case 6}

\ConditionalText*{\casesix}

\end{document}

решение2

Вот listofitemsподход. Ключ в том, как определен разделитель. Используя \setsepchar{case 1||case 3||case 4/case 2||case 5}, парсинг верхнего уровня ищет случаи 1, 3 и 4. Парсинг второго уровня ищет случаи 2 и 5. Парсинг выполняется с помощью \readlist\tmp{#1}. Затем, \listlen\tmp[]показывает, сколько элементов создано путем разделения по фразе уровня парсинга 1. Аналогично, показывает, \listlen\tmp[1]сколько элементов создано путем разделения по фразе уровня парсинга 2. Если фраза найдена, ответом будет 2, что указывает на пробел (даже если он нулевой) до и после проанализированной фразы, а если ответом будет 1, это означает, что фраза не была проанализирована.

Подход также позволит задать более 2 уровней, хотя можно просто \setsepcharзадать 3 или более уровней синтаксического анализа.

\documentclass{article}
\usepackage{xstring,listofitems}
\newcommand*{\ConditionalText}[1]{%
  \setsepchar{case 1||case 3||case 4/case 2||case 5/case 6}
  \readlist\tmp{#1}%
  \IfStrEqCase{\listlen\tmp[]\listlen\tmp[1]\listlen\tmp[1,1]}{%
      {211}{some long text which is identical for case 1, case 3 and case 4.}%
      {121}{other text for case 2 and case 5.}%
      {112}{for case 6 only.}%
  }[{Error: Unknown parameter ``#1'' to ConditionalText}]%
}
\begin{document}
    \par\ConditionalText{case 1}
    \par\ConditionalText{case 2}
    \par\ConditionalText{case 3}
    \par\ConditionalText{case 4}
    \par\ConditionalText{case 5}
    \par\ConditionalText{case 6}
    \par\ConditionalText{case 7}
\end{document}

введите описание изображения здесь

Конечно, xstringможно вообще исключить из процесса с помощью вложенных \ifnums:

\documentclass{article}
\usepackage{listofitems}
\setsepchar{\\}
\readlist*\thecases{
some long text which is identical for case 1, case 3 and case 4.\\
other text for case 2 and case 5.\\
for case 6 only.
}
\newcommand*{\ConditionalText}[1]{%
  \setsepchar{case 1||case 3||case 4/case 2||case 5/case 6}
  \readlist\tmp{#1}%
  \edef\tmpnum{\listlen\tmp[]\listlen\tmp[1]\listlen\tmp[1,1]}
  \ifnum\tmpnum=211\relax\thecases[1]%
  \else\ifnum\tmpnum=121\relax\thecases[2]%
  \else\ifnum\tmpnum=112\relax\thecases[3]%
  \else Error: Unknown parameter ``#1'' to ConditionalText%
  \fi\fi\fi
}
\begin{document}
    \par\ConditionalText{case 1}
    \par\ConditionalText{case 2}
    \par\ConditionalText{case 3}
    \par\ConditionalText{case 4}
    \par\ConditionalText{case 5}
    \par\ConditionalText{case 6}
    \par\ConditionalText{case 7}
\end{document}

ОРИГИНАЛЬНЫЙ ОТВЕТ

Почему бы просто не определить \msgAи \msgBи не ссылаться на них косвенно по регистру? Это позволяет избежать необходимости многократного повторного ввода одного и того же сообщения.

\documentclass{article}
\usepackage{xstring}
\def\msgA{some long text which is identical for case 1, case 3 and case 4.}
\def\msgB{other text for case 2 and case 5.}
\newcommand*{\ConditionalText}[1]{%
    \IfStrEqCase{#1}{%
        {case 1}{\msgA}%
        {case 2}{\msgB}%
        {case 3}{\msgA}%
        {case 4}{\msgA}%
        {case 5}{\msgB}%
    }[{Error: Unknown parameter ``#1'' to ConditionalText}]%
}
\begin{document}
    \par\ConditionalText{case 1}
    \par\ConditionalText{case 2}
    \par\ConditionalText{case 3}
    \par\ConditionalText{case 4}
    \par\ConditionalText{case 5}
\end{document}

решение3

Несколько лет назад я написал процедуру \UD@KeepKthOfLArguments, которая позволяет выбрать произвольный неразделенный аргумент из произвольного количества неразделенных аргументов, которое — из-за рекурсии — не ограничено ограничением в 9 аргументов, обычно налагаемым на макропрограммирование TeX.

К сожалению, \IfStrEqCaseсам по себе не является полностью расширяемым и, следовательно, не может быть использован в \UD@KeepKthOfLArgumentsпервом аргументе для оценки числа K.
Таким образом, вам придется сделать это другим способом, т. е. вызвать \UD@KeepKthOfLArgumentsизнутри \IfStrEqCaseдля выбора одного из трех аргументов:

\documentclass{article}
\usepackage{xstring}

\makeatletter
%%=========================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond
%%.........................................................................
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
%%-------------------------------------------------------------------------
%% Check whether argument is empty:
%%.........................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% A concern in his posting is that the argument is hit with \string
%% after some expansions which in edge cases might result in unbalancing
%% surrounding \if..\fi-constructs if the macro is used inside of such
%% \if..\fi-constructs.
%%
%% That challenging concern sickened me. ;-)
%%
%% Therefore I decided to implerment a variant where this cannot happen
%% as expansion is forced by \romannumeral:
%%
%% After the first expansion-step, \string is not applied yet.
%% After the second expansion-step, any possibly disturbing remainders
%% are already removed due to \romannumeral-expansion.
%%
%% No eTeX- or whatsoever extensions. No \if.. .Only \romannumeral,
%% digit 0, space token for terminating \romannumeral-expansion,
%% \string, \expandafter, \UD@firstoftwo, \UD@secondoftwo, {, }.
%%
%% May 20, 2016
%%
%% Ulrich Diez (e-mail: [email protected])
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-------------------------------------------------------------------------
%% Keep only the K-th of L consecutive undelimited arguments.
%%   ( IF K < 1 OR K > L just remove L consecutive undelimited arguments. )
%%.........................................................................
%% \UD@KeepKthOfLArguments{<integer number K>}%
%%                        {<integer number L>}%
%%                        {<Tokens to insert before K-th argument>}%
%%                        <L consecutive undelimited arguments>
%%
%% If K >= 1 and K <= L  yields:
%%       <Tokens to insert before K-th argument><K-th undelimited argument>
%% If K < 1 or K > L
%%       (-> there is no K-th argument in the set
%%           of <L consecutive undelimited arguments> )
%% yields:
%%       <Tokens to insert before K-th argument>
%%
%% Examples:
%%
%% X\UD@KeepKthOfLArguments{3}{7}{<Tokens to insert>}{A}{B}{C}{D}{E}{F}{G}X
%% yields: X<Tokens to insert>CX
%%
%% X\UD@KeepKthOfLArguments{5}{2}{<Tokens to insert>}{A}{B}X
%% yields X<Tokens to insert>X
%%
%% X\UD@KeepKthOfLArguments{0}{2}{<Tokens to insert>}{A}{B}X
%% yields X<Tokens to insert>X
%%
%% X\romannumeral0%
%%  \UD@KeepKthOfLArguments{3}{7}{ <Tokens to insert>}{A}{B}{C}{D}{E}{F}{G}X
%% yields: X\romannumeral0 <Tokens to insert>CX
%% yields: X<Tokens to insert>CX
%% In case of embedding the whole thing in other expansion-contexts,
%% you need to have "hit" \romannumeral by only one \expandafter-chain for
%% obtaining the result...
%%
%% January 17, 2005
%%
%% Ulrich Diez (e-mail: [email protected])
%%
\newcommand\UD@KeepKthOfLArguments[2]{%
  \expandafter\UD@KeepKthOfLArgumentsA
  \expandafter{\romannumeral\number\number#1 000\expandafter}%
  \expandafter{\romannumeral\number\number#2 000}%
}%
\newcommand\UD@KeepKthOfLArgumentsA[3]{%
  \UD@CheckWhetherNull{#1}{%
    \UD@RemoveNArguments{#2}{#3}{}%
  }{%
    \expandafter\UD@PassFirstToSecond
    \expandafter{%
    \UD@firstoftwo{}#1}{\UD@KeepKthOfLArgumentsB{#1}{#2}}{#2}{#3}%
  }%
}%
\newcommand\UD@KeepKthOfLArgumentsB[5]{%
  \UD@CheckWhetherNull{#1}{%
     \UD@RemoveNArguments{#3}{\UD@RemoveNArguments{#2}{#5}}{}%
  }{%
    \UD@CheckWhetherNull{#2}{%
      \UD@RemoveNArguments{#4}{#5}{}%
    }{%
      \expandafter\UD@PassFirstToSecond
      \expandafter{%
      \UD@firstoftwo{}#2}{\expandafter\UD@KeepKthOfLArgumentsB
                       \expandafter{%
                       \UD@firstoftwo{}#1}}{#3}{#4}{#5}%
    }%
  }%
}%
\newcommand\UD@RemoveNArguments[3]{%
  \UD@CheckWhetherNull{#1}{#2#3}{%
    \UD@firstoftwo{%
      \expandafter\UD@RemoveNArguments
      \expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
    }%
  }%
}%
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\newcommand*{\ConditionalTextDesired}[1]{%
  % \IfStrEqCase will deliver the call to \UD@KeepKthOfLArguments plus
  % \UD@KeepKthOfLArguments's first argument:
  \IfStrEqCase{#1}{%
       {case 1}{\UD@KeepKthOfLArguments{1}}%
       {case 2}{\UD@KeepKthOfLArguments{2}}%
       {case 3}{\UD@KeepKthOfLArguments{1}}%
       {case 4}{\UD@KeepKthOfLArguments{1}}%
       {case 5}{\UD@KeepKthOfLArguments{2}}%
  }[{\UD@KeepKthOfLArguments{3}}]%
  % Here come the remaining arguments of \UD@KeepKthOfLArguments:
  {3}{}%
  {some long text which is identical for case 1, case 3 and case 4.}%
  {other text for case 2 and case 5.}%
  {Error: Unknown parameter ``#1'' to ConditionalText.}%
}%
\makeatother

\begin{document}
    \par\ConditionalTextDesired{case 1}
    \par\ConditionalTextDesired{case 2}
    \par\ConditionalTextDesired{case 3}
    \par\ConditionalTextDesired{case 4}
    \par\ConditionalTextDesired{case 5}
\end{document}

Кстати: если вы хотите сделать такой выбор в рамках чистого контекста расширения, вот пример стратегии, основанной на использовании разделенных аргументов:

\documentclass{article}
\makeatletter
%%=========================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond
%%.........................................................................
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
%%-------------------------------------------------------------------------
%% Check whether argument is empty:
%%.........................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% A concern in his posting is that the argument is hit with \string
%% after some expansions which in edge cases might result in unbalancing
%% surrounding \if..\fi-constructs if the macro is used inside of such
%% \if..\fi-constructs.
%%
%% That challenging concern sickened me. ;-)
%%
%% Therefore I decided to implerment a variant where this cannot happen
%% as expansion is forced by \romannumeral:
%%
%% After the first expansion-step, \string is not applied yet.
%% After the second expansion-step, any possibly disturbing remainders
%% are already removed due to \romannumeral-expansion.
%%
%% No eTeX- or whatsoever extensions. No \if.. .Only \romannumeral,
%% digit 0, space token for terminating \romannumeral-expansion,
%% \string, \expandafter, \UD@firstoftwo, \UD@secondoftwo, {, }.
%%
%% May 20, 2016
%%
%% Ulrich Diez (e-mail: [email protected])
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-------------------------------------------------------------------------
%% Keep only the K-th of L consecutive undelimited arguments.
%%   ( IF K < 1 OR K > L just remove L consecutive undelimited arguments. )
%%.........................................................................
%% \UD@KeepKthOfLArguments{<integer number K>}%
%%                        {<integer number L>}%
%%                        {<Tokens to insert before K-th argument>}%
%%                        <L consecutive undelimited arguments>
%%
%% If K >= 1 and K <= L  yields:
%%       <Tokens to insert before K-th argument><K-th undelimited argument>
%% If K < 1 or K > L
%%       (-> there is no K-th argument in the set
%%           of <L consecutive undelimited arguments> )
%% yields:
%%       <Tokens to insert before K-th argument>
%%
%% Examples:
%%
%% X\UD@KeepKthOfLArguments{3}{7}{<Tokens to insert>}{A}{B}{C}{D}{E}{F}{G}X
%% yields: X<Tokens to insert>CX
%%
%% X\UD@KeepKthOfLArguments{5}{2}{<Tokens to insert>}{A}{B}X
%% yields X<Tokens to insert>X
%%
%% X\UD@KeepKthOfLArguments{0}{2}{<Tokens to insert>}{A}{B}X
%% yields X<Tokens to insert>X
%%
%% X\romannumeral0%
%%  \UD@KeepKthOfLArguments{3}{7}{ <Tokens to insert, be aware of the space behind the opening brace!>}{A}{B}{C}{D}{E}{F}{G}X
%% yields: X\romannumeral0 <Tokens to insert>CX
%% yields: X<Tokens to insert>CX
%% In case of embedding the whole thing in other expansion-contexts,
%% you need to have "hit" \romannumeral by only one \expandafter-chain for
%% obtaining the result...
%%
%% January 17, 2005
%%
%% Ulrich Diez (e-mail: [email protected])
%%
\newcommand\UD@KeepKthOfLArguments[2]{%
  \expandafter\UD@KeepKthOfLArgumentsA
  \expandafter{\romannumeral\number\number#1 000\expandafter}%
  \expandafter{\romannumeral\number\number#2 000}%
}%
\newcommand\UD@KeepKthOfLArgumentsA[3]{%
  \UD@CheckWhetherNull{#1}{%
    \UD@RemoveNArguments{#2}{#3}{}%
  }{%
    \expandafter\UD@PassFirstToSecond
    \expandafter{%
    \UD@firstoftwo{}#1}{\UD@KeepKthOfLArgumentsB{#1}{#2}}{#2}{#3}%
  }%
}%
\newcommand\UD@KeepKthOfLArgumentsB[5]{%
  \UD@CheckWhetherNull{#1}{%
     \UD@RemoveNArguments{#3}{\UD@RemoveNArguments{#2}{#5}}{}%
  }{%
    \UD@CheckWhetherNull{#2}{%
      \UD@RemoveNArguments{#4}{#5}{}%
    }{%
      \expandafter\UD@PassFirstToSecond
      \expandafter{%
      \UD@firstoftwo{}#2}{\expandafter\UD@KeepKthOfLArgumentsB
                       \expandafter{%
                       \UD@firstoftwo{}#1}}{#3}{#4}{#5}%
    }%
  }%
}%
\newcommand\UD@RemoveNArguments[3]{%
  \UD@CheckWhetherNull{#1}{#2#3}{%
    \UD@firstoftwo{%
      \expandafter\UD@RemoveNArguments
      \expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
    }%
  }%
}%
%%-------------------------------------------------------------------------
%% Check whether argument contains no exclamation-mark on top-brace-level:
%%.........................................................................
%% \UD@CheckWhetherNoExclamationMark{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that
%%                    argument which is to be checked does not contain !>}%
%%                  {<Tokens to be delivered in case that
%%                    argument which is to be checked does contain !>}%
\long\def\UD@RemoveToExclamationMark#1!{}%
\long\def\UD@CheckWhetherNoExclamationMark#1{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@RemoveToExclamationMark#1!}%
}%
%%-------------------------------------------------------------------------
%% Fork depending on some tokens:
%%.........................................................................
%% \ConditionalTextDesired{<Argument which is to be checked>}%
%%           {<Tokens to be delivered in case <Argument which is to be checked> is "case 1" or "case 3" or "case 4">}%
%%           {<Tokens to be delivered in case <Argument which is to be checked> is "case 2" or "case 5" >}%
%%
%% In case <Argument which is to be checked> is neither "case 1" nor
%% "case 2" the phrase "Error: Unknown parameter ``<Argument which is
%% to be checked>'' to \ConditionalTextDesired." will be delivered.
%%
\newcommand\@ConditionalTextDesired{}%
\long\def\@ConditionalTextDesired%
   #1!!case 1!case 2!case 3!case 4!case 5!#2#3!!!!{#2}%
\newcommand\ConditionalTextDesired[1]{%
  \romannumeral0%
  \UD@KeepKthOfLArguments{%
    \UD@CheckWhetherNoExclamationMark{#1}{%
      \@ConditionalTextDesired
      !#1!case 1!case 2!case 3!case 4!case 5!{1}%<- #1 is EMPTY
      !!#1!case 2!case 3!case 4!case 5!{2}% <- #1 = case 1
      !!case 1!#1!case 3!case 4!case 5!{3}% <- #1 = case 2
      !!case 1!case 2!#1!case 4!case 5!{2}% <- #1 = case 3
      !!case 1!case 2!case 3!#1!case 5!{2}% <- #1 = case 4
      !!case 1!case 2!case 3!case 4!#1!{3}% <- #1 = case 5
      !!case 1!case 2!case 3!case 4!case 5!{1}% <- #1 = something else without exclamation mark
      !!!!%
    }{1}% <- #1 = something else with exclamation mark
  }{3}{ }% <- The remaining arguments of \UD@KeepKthOfLArguments.
  % You could put the three text-arguments into the macro at this place.
  % You can also provide only the one here, where the macro-parameter #1
  % is needed and provide the other ones at run-time of the macro.
  % The latter will be done for demonstration-purposes.
  {%
    Error: Unknown parameter ``#1'' to \texttt{\string\ConditionalTextDesired}.%
    %In case eTeX-extensions are available you might wish to use \detokenize:
    %Error: Unknown parameter ``\detokenize{#1}'' to \texttt{\string\ConditionalTextDesired}.%
  }%
}%
\makeatother

\begin{document}
% This should yield "Error: Unknown parameter ``'' to \ConditionalTextDesired."
\ConditionalTextDesired{}
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "Error: Unknown parameter ``!case 1'' to \ConditionalTextDesired."
\ConditionalTextDesired{!case 1}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "Error: Unknown parameter ``case 6'' to \ConditionalTextDesired."
\ConditionalTextDesired{case 6}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "some long text which is identical for case 1, case 3 and case 4."
\ConditionalTextDesired{case 1}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "some long text which is identical for case 1, case 3 and case 4."
\ConditionalTextDesired{case 3}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "some long text which is identical for case 1, case 3 and case 4."
\ConditionalTextDesired{case 4}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "other text for case 2 and case 5."
\ConditionalTextDesired{case 2}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

% This should yield "other text for case 2 and case 5."
\ConditionalTextDesired{case 5}%
                       {some long text which is identical for case 1, case 3 and case 4.}%
                       {other text for case 2 and case 5.}%

\end{document}

Связанный контент