Leer sólo una determinada parte del argumento de un nuevo comando

Leer sólo una determinada parte del argumento de un nuevo comando

Estoy usando el paquete extra de glosarios para mi lista de símbolos. Por alguna razón que no es relevante aquí, he definido un nuevo comando.

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

de modo que las entradas de mi glosario tengan la forma:

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

Me gustaría "transferirlos" a la plantilla de tesis de mi universidad, donde no usan el paquete de glosarios, sino que definen un entorno donde se deben ingresar los símbolos como:

\begin{symbols}

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

\end{symbols}

Este es simplemente un entorno de tabulación, imprime directamente todo lo que escriba en los argumentos del comando \sym. Entonces mi plan era definir algo como

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

Esto funciona excepto que el uso del paquete de glosarios de alguna manera interfiere con otra parte del archivo de estilo de la universidad. Por eso me gustaría definir

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

Sin embargo, no quiero tener "descripción = {Conjunto de campos vectoriales suavizados}" para el segundo argumento, quiero tener "Conjunto de campos vectoriales suavizados". ¿Hay alguna forma de extraer sólo la parte "Conjunto de campos vectoriales suaves" del segundo argumento de \symb?

Solución: Una versión simplificada de la solución para gatos de @Schrödinger me funciona:

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

Respuesta1

Con el siguiente código, la rutina redefinida \symbactúa de la siguiente manera:

Los argumentos se pasan \glsxtrnewsymbolintactos/tal como están.

Los argumentos se pasan a \symdespués de extraer la descripción del \symbargumento opcional de la siguiente manera:

En caso de que ese argumento no contenga la frase inicial "descripción=", se pasa tal cual. (Se tienen en cuenta los tokens de espacio que rodean la frase completa y/o un token de espacio entre "descripción" y "=").

En caso de que ese argumento contenga la frase inicial "descripción=", esa frase se elimina.

  • En caso de que el resto consista sólo en tokens espaciales o nada, el resultado de la extracción estará vacío/no consistirá en ningún token en absoluto.
  • En caso de que el resto consista en un único argumento no delimitado, es decir, ya sea de un único token sin llave o de un conjunto de tokens anidados entre llaves, se eliminará un nivel de llaves que rodean todo el resto si están presentes, entonces se eliminará el espacio. -Se eliminarán los tokens que rodean todo el resto.
  • En caso de que el resto consista en algo más que un único argumento no delimitado, no se eliminarán las llaves, pero se eliminarán los espacios que rodean todo el resto.

Como \symy \glsxtrnewsymbolno están disponibles para mí, proporcioné "definiciones ficticias" que no hacen más que presentar sus argumentos de forma detokenizada, anidados entre corchetes angulares.

Hice todo esto espontáneamente, por lo que no hay garantías. ;-)

Observe también mi comentario sobre su rutina no redefinida \symby sobre anidar material arbitrario entre llaves {y }cuando lo pasa a otra macro donde forma un argumento opcional.

Todo el "mecanismo" se implementa sin utilizar nada \if..... \else... \fi. Por lo tanto, el mecanismo no se confundirá con macroargumentos que contengan \ifo \elseo incomparables \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}

ingrese la descripción de la imagen aquí

Respuesta2

Esto es algo que hace eso. Obviamente no tengo su \symcomando, así que uso algo que muestra que tiene los argumentos correctos.

\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}

ingrese la descripción de la imagen aquí

Esto supone que, siempre que el primer argumento no esté vacío, contiene un =signo. Puedes hacerlo inmune contra eso, pero entonces recomendaría usar algún sistema de administración de claves. Por ejemplo, si ya estás cargando pgfserá muy sencillo.

información relacionada