Nur einen bestimmten Teil des Arguments eines neuen Befehls auslesen

Nur einen bestimmten Teil des Arguments eines neuen Befehls auslesen

Ich verwende das Paket glossaries-extra für meine Symbolliste. Aus einem Grund, der hier nicht relevant ist, habe ich einen neuen Befehl definiert

\newcommand{\symb}[3][]{%
\glsxtrnewsymbol[#1]{#2}{#3}%
 }

sodass meine Glossareinträge die Form haben:

\symb[description={Set of Smooth Vector Fields}]{vfs}{\ensuremath{\mathfrak{X}}}

Ich möchte diese in die Abschlussarbeitsvorlage meiner Universität „übertragen“. Dort wird nicht das Glossarpaket verwendet, sondern stattdessen eine Umgebung definiert, in der Symbole wie folgt eingegeben werden sollen:

\begin{symbols}

\sym{\ensuremath{\mathfrak{X}}}{Set of Smooth Vector Fields}

\end{symbols}

Dies ist einfach eine Tabulatorumgebung, die direkt alles ausgibt, was Sie in den Argumenten des Befehls \sym angeben. Mein Plan war also, etwas wie

\renewcommand{\symb}[3][]{%
\glsxtrnewsymbol[#1]{#2}{#3}%
\sym{#3}{\glsdesc{#2}}%
}

Dies funktioniert, außer dass die Verwendung des Glossarpakets irgendwie einen anderen Teil der Stildatei der Universität durcheinander bringt. Aus diesem Grund möchte ich definieren

 \renewcommand{\symb}[3][]{%
            \sym{#3}{#1}%
    }

Ich möchte jedoch nicht "description={Set of Smooth Vector Fields}" als zweites Argument haben, sondern "Set of Smooth Vector Fields". Gibt es eine Möglichkeit, nur den Teil "Set of Smooth Vector Fields" aus dem zweiten Argument von \symb zu extrahieren?

Lösung: Eine vereinfachte Version der Lösung von @Schrödingers Katze funktioniert bei mir:

\newcommand{\symb}[3][]{%
\def\mysplit##1=##2{\sym{#3}{##2}}%
\expandafter\mysplit#1%
}

Antwort1

Mit dem folgenden Code \symbverhält sich die neu definierte Routine wie folgt:

Argumente werden \glsxtrnewsymbolunverändert bzw. unverändert weitergegeben.

\symNach dem Extrahieren der Beschreibung aus \symbdem optionalen Argument von werden Argumente wie folgt übergeben :

Falls dieses Argument nicht die führende Phrase „description=“ enthält, wird es so übergeben, wie es ist. (Leerzeichen, die die gesamte Phrase umgeben und/oder ein Leerzeichen zwischen „description“ und „=“ werden berücksichtigt.)

Falls das Argument die einleitende Phrase „description=“ enthält, wird diese Phrase entfernt.

  • Falls der Rest nur aus Leerzeichen-Token oder nichts besteht, ist das Extraktionsergebnis leer bzw. besteht aus überhaupt keinen Token.
  • Falls der Rest aus einem einzelnen, nicht abgegrenzten Argument besteht, also entweder aus einem einzelnen Token ohne Klammern oder aus einer Reihe von Token, die in Klammern verschachtelt sind, wird eine Klammernebene, die den gesamten Rest umgibt, entfernt (falls vorhanden). Anschließend werden die Leerzeichen-Token entfernt, die den gesamten Rest umgeben.
  • Falls der Rest aus etwas anderem als nur einem einzelnen nicht abgegrenzten Argument besteht, werden keine Klammern entfernt, aber die Leerzeichen, die den gesamten Rest umgeben, werden entfernt.

Da mir \symund nicht zur Verfügung stehen, habe ich „Dummy-Definitionen“ bereitgestellt, die nichts anderes tun, als ihre Argumente in detokenisierter Form und verschachtelt in spitzen Klammern bereitzustellen.\glsxtrnewsymbol

Das habe ich alles spontan gemacht, daher keine Garantie. ;-)

Bitte beachten Sie auch meinen Kommentar zu Ihrer nicht neu definierten \symb-Routine und zum Verschachteln beliebigen Materials in geschweiften Klammern {und }bei der Übergabe an ein anderes Makro, wo es ein optionales Argument bildet.

Der gesamte „Mechanismus“ wird ohne Verwendung von \if..… implementiert \else. \fiDaher wird der Mechanismus nicht durch Makroargumente verwirrt, die nicht übereinstimmende \ifoder \elseoder enthalten \fi.

\documentclass{article}
\makeatletter
%%=============================================================================
%% 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>}%
%%
%% Due to \romannumeral0-expansion the result is delivered after two
%% expansion-steps/after two "hits" by \expandafter.
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%=============================================================================
%% Check whether argument is blank (empty or only spaces):
%%=============================================================================
%% -- Take advantage of the fact that TeX discards space tokens when
%%    "fetching" _un_delimited arguments: --
%% \UD@CheckWhetherBlank{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that
%%                        argument which is to be checked is blank>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked is not blank}%
\newcommand\UD@CheckWhetherBlank[1]{%
  \romannumeral\expandafter\expandafter\expandafter\@secondoftwo
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo#1{}.}%
}%
%%=============================================================================
%% Exchange two arguments. (From each argument an outermost level of 
%% surrounding braces will be removed if present.)
%%=============================================================================
\newcommand\UD@Exchange[2]{#2#1}%
%%=============================================================================
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category code 1 or 2:
%%=============================================================================
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category code
%%                                1 or 2>}%
%%                              {a <single non-space token> that does 
%%                                _not_ occur in <token sequence> >}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[4]{%
  \romannumeral0\UD@CheckWhetherNull{#1}%
  {\UD@Exchange{ }\expandafter\@secondoftwo}%
  {\expandafter\@secondoftwo\string{\expandafter
   \UD@@CheckWhetherLeadingTokens#4#3#1#2}{}}%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\UD@Exchange{\@firstoftwo}}{\UD@Exchange{\@secondoftwo}}%
  {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter}\expandafter\expandafter
   \expandafter}\expandafter\@secondoftwo\expandafter{\string}%
}%
%%=============================================================================
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%=============================================================================
\newcommand\UD@internaltokencheckdefiner[2]{%
  \@ifdefinable#1{\long\def#1##1#2{{##1}}}%
}%
%%=============================================================================
\UD@internaltokencheckdefiner{\UD@ExtractDescriptionEqual}{description=}%
\UD@internaltokencheckdefiner{\UD@ExtractDescriptionSpaceEqual}{description =}%
\UD@internaltokencheckdefiner{\UD@ExtractDescriptionEqualSpace}{description= }%
\UD@internaltokencheckdefiner{\UD@ExtractDescriptionSpaceEqualSpace}{description = }%
\UD@internaltokencheckdefiner{\UD@ExtractSpaceDescriptionEqual}{ description=}%
\UD@internaltokencheckdefiner{\UD@ExtractSpaceDescriptionSpaceEqual}{ description =}%
\UD@internaltokencheckdefiner{\UD@ExtractSpaceDescriptionEqualSpace}{ description= }%
\UD@internaltokencheckdefiner{\UD@ExtractSpaceDescriptionSpaceEqualSpace}{ description = }%
\UD@internaltokencheckdefiner{\UD@ExtractSpace}{ }%
%%=============================================================================
%% Trim all leading and trailing spaces:
%%=============================================================================
\newcommand\UD@RemoveSpaces[1]{%
   \romannumeral0\@firstofone{\UD@TrimTrailSpaceLoop{#1}.#1\UD@Bizarre} \UD@Bizarre\relax\UD@Bizarre
}%
\@ifdefinable\UD@TrimTrailSpaceLoop{%
  \long\def\UD@TrimTrailSpaceLoop#1#2 \UD@Bizarre#3\relax\UD@Bizarre{%
     \UD@CheckWhetherNull{#3}{%
       \UD@TrimLeadSpaceLoop{#1}%
     }{%
       \@firstofone{\expandafter\UD@TrimTrailSpaceLoop\expandafter{\@gobble#2}#2\UD@Bizarre} \UD@Bizarre\relax\UD@Bizarre
     }%
  }%
}%
\@ifdefinable\UD@gobblespace{%
  \@firstofone{\def\UD@gobblespace} {}%
}%
\newcommand\UD@TrimLeadSpaceLoop[1]{%
  \UD@CheckWhetherLeadingTokens{#1}{ }{.}{\UD@ExtractSpace}{\expandafter\UD@TrimLeadSpaceLoop\expandafter{\UD@gobblespace#1}}{ #1}%
}%
%%=============================================================================
%% Extract description:
%%=============================================================================    
\newcommand\UD@ExtractDescription[1]{%
  \romannumeral0%
  \UD@CheckWhetherLeadingTokens{#1}{ description = }{.}{\UD@ExtractSpaceDescriptionSpaceEqualSpace}{%
    \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractSpaceDescriptionSpaceEqualSpace#1}%
  }{%
    \UD@CheckWhetherLeadingTokens{#1}{ description= }{.}{\UD@ExtractSpaceDescriptionEqualSpace}{%
      \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractSpaceDescriptionEqualSpace#1}%
    }{%
      \UD@CheckWhetherLeadingTokens{#1}{ description =}{.}{\UD@ExtractSpaceDescriptionSpaceEqual}{%
        \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractSpaceDescriptionSpaceEqual#1}%
      }{%
        \UD@CheckWhetherLeadingTokens{#1}{ description=}{.}{\UD@ExtractSpaceDescriptionEqual}{%
          \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractSpaceDescriptionEqual#1}%
        }{%
          \UD@CheckWhetherLeadingTokens{#1}{description = }{.}{\UD@ExtractDescriptionSpaceEqualSpace}{%
            \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractDescriptionSpaceEqualSpace#1}%
          }{%
            \UD@CheckWhetherLeadingTokens{#1}{description= }{.}{\UD@ExtractDescriptionEqualSpace}{%
              \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractDescriptionEqualSpace#1}%
            }{%
              \UD@CheckWhetherLeadingTokens{#1}{description =}{.}{\UD@ExtractDescriptionSpaceEqual}{%
                \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractDescriptionSpaceEqual#1}%
              }{%
                \UD@CheckWhetherLeadingTokens{#1}{description=}{.}{\UD@ExtractDescriptionEqual}{%
                  \expandafter\UD@ExtractDescriptionCheckArgAmount\expandafter{\UD@ExtractDescriptionEqual#1}%
                }{ #1}%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}%
\newcommand\UD@ExtractDescriptionCheckArgAmount[1]{%
  \expandafter\UD@CheckWhetherBlank\expandafter{\@gobble#1}{ }{%
    \expandafter\UD@CheckWhetherBlank\expandafter{\@gobbletwo#1}{%
       \UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter}%
       \expandafter\UD@RemoveSpaces\expandafter{\@secondoftwo#1}%
    }{%
      \UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter}%
      \expandafter\UD@RemoveSpaces\expandafter{\@firstoftwo{}#1}%
    }%
  }%
}%
%%=============================================================================
%% Your definition of \symb with a modification:
%% When passing arbitrary arguments as optional arguments, I strongly recommend 
%% nesting them in braces for ensuring that nesting of square brackets won't 
%% lead to problems:
%%=============================================================================
\newcommand{\symb}[3][]{%
  \glsxtrnewsymbol[{#1}]{#2}{#3}%  <- Here the content of #1 is arbitrary.
}%                              %     Problems due to nested square brackets
                                %     might occur in case #1 contains
                                %     [ or ]. 
                                %     Some day someone might do something like
                                %     \symb[{description=optional\macro[macro's optional]}]{...}{...}.
                                %     Therefore nest #1 in braces.
                                %     These braces will be removed by LaTeX 
                                %     when processing \glsxtrnewsymbol's 
                                %     optional argument.
                                %     They prevent confusion when it comes
                                %     to nesting optional arguments within
                                %     optional arguments.
%%=============================================================================
%% Redefinition of  \symb:
%%=============================================================================
\renewcommand{\symb}[3][]{%
  \romannumeral0%
  \expandafter\expandafter\expandafter\UD@Exchange
  \expandafter\expandafter\expandafter{%
  \expandafter\expandafter\expandafter{\UD@ExtractDescription{#1}}}{ \sym{#3}}%
  \glsxtrnewsymbol[{#1}]{#2}{#3}%
}%
%%=============================================================================
%% Dummy-definition for \glsxtrnewsymbol which displays the arguments verbatim
%%=============================================================================
\newcommand\glsxtrnewsymbol[3][]{%
  \par\noindent
  \texttt{\string\glsxtrnewsymbol}'s optional argument: $\langle$\texttt{\detokenize{#1}}$\rangle$
  \par\noindent
  \texttt{\string\glsxtrnewsymbol}'s mandatory argument 1: $\langle$\texttt{\detokenize{#2}}$\rangle$
  \par\noindent
  \texttt{\string\glsxtrnewsymbol}'s mandatory argument 2: $\langle$\texttt{\detokenize{#3}}$\rangle$
  \par
}%
%%=============================================================================
%% Dummy-definition for \sym which displaysthe arguments verbatim
%%=============================================================================
\newcommand\sym[2]{%
  \par\noindent
  \texttt{\string\sym}'s mandatory argument 1: $\langle$\texttt{\detokenize{#1}}$\rangle$
  \par\noindent
  \texttt{\string\sym}'s mandatory argument 2: $\langle$\texttt{\detokenize{#2}}$\rangle$
  \par
}%
\makeatother


\begin{document}
\vspace*{-1in}%
\noindent
\texttt{\detokenize{\symb[description={Set of Smooth Vector Fields}]{vfs}{\ensuremath{\mathfrak{X}}}}}:

\smallskip

\symb[description={Set of Smooth Vector Fields}]{vfs}{\ensuremath{\mathfrak{X}}}

\bigskip

\noindent\null\hrulefill\null

\bigskip

\noindent
\texttt{\detokenize{\symb[ description = { Set of Smooth Vector Fields } ]{vfs}{\ensuremath{\mathfrak{X}}}}}:

\smallskip

\symb[ description = { Set of Smooth Vector Fields } ]{vfs}{\ensuremath{\mathfrak{X}}}

\bigskip

\noindent\null\hrulefill\null

\bigskip

\noindent
\texttt{\detokenize{\symb[description = Set of Smooth Vector Fields ]{vfs}{\ensuremath{\mathfrak{X}}}}}:

\smallskip

\symb[description = Set of Smooth Vector Fields ]{vfs}{\ensuremath{\mathfrak{X}}}

\bigskip

\noindent\null\hrulefill\null

\bigskip

\noindent
\texttt{\detokenize{\symb{vfs}{\ensuremath{\mathfrak{X}}}}}:

\smallskip

\symb{vfs}{\ensuremath{\mathfrak{X}}}

\bigskip

\noindent\null\hrulefill\null

\bigskip

\noindent
\texttt{\detokenize{\symb[whatsoever]{vfs}{\ensuremath{\mathfrak{X}}}}}:

\smallskip

\symb[whatsoever]{vfs}{\ensuremath{\mathfrak{X}}}

\end{document}

Bildbeschreibung hier eingeben

Antwort2

Das hier ist etwas, das das tut. Offensichtlich verfüge ich nicht über Ihren \symBefehl, also verwende ich etwas, das zeigt, dass die Argumente richtig sind.

\documentclass{article}
\usepackage{amsfonts}
\def\forgetit{}
\newcommand{\symb}[3][]{%
\glsxtrnewsymbol[#1]{#2}{#3}%
}
\newcommand{\sym}[2]{first argument=\ensuremath{#1},second argument=#2}
\renewcommand{\symb}[3][\forgetit]{%
\def\mysplit##1=##2;{\def\mylast{##2}}%
\ifx#1\forgetit
\sym{#3}{empty}%
\else
\expandafter\mysplit#1;%
\sym{#3}{\mylast}%
\fi
}
\begin{document}
\symb[description={Set of Smooth Vector Fields}]{vfs}{\ensuremath{\mathfrak{X}}}

\symb{vfs}{\ensuremath{\mathfrak{X}}}
\end{document}

Bildbeschreibung hier eingeben

Dies setzt voraus, dass das erste Argument, wenn es nicht leer ist, ein =Zeichen enthält. Sie können es dagegen immun machen, aber dann würde ich die Verwendung eines Schlüsselverwaltungssystems empfehlen. Wenn Sie beispielsweise bereits laden, pgfist es sehr einfach.

verwandte Informationen