
私はシンボルのリストにglossaries-extraパッケージを使用しています。ここでは関係のない理由で、新しいコマンドを定義しました。
\newcommand{\symb}[3][]{%
\glsxtrnewsymbol[#1]{#2}{#3}%
}
私の用語集のエントリは次の形式になります。
\symb[description={Set of Smooth Vector Fields}]{vfs}{\ensuremath{\mathfrak{X}}}
これらを大学の論文テンプレートに「転送」したいと思います。そこでは用語集パッケージは使用されず、代わりに次のように記号を入力する環境が定義されています。
\begin{symbols}
\sym{\ensuremath{\mathfrak{X}}}{Set of Smooth Vector Fields}
\end{symbols}
これは単にタブ環境であり、\symコマンドの引数に書き込んだものを直接出力します。そこで、次のようなものを定義するつもりでした。
\renewcommand{\symb}[3][]{%
\glsxtrnewsymbol[#1]{#2}{#3}%
\sym{#3}{\glsdesc{#2}}%
}
これは、glossariesパッケージを使用すると大学のスタイルファイルの別の部分が何らかの形で混乱することを除けば機能します。このため、定義したいと思います。
\renewcommand{\symb}[3][]{%
\sym{#3}{#1}%
}
しかし、2 番目の引数に「description={Set of Smooth Vector Fields}」ではなく、「Set of Smooth Vector Fields」を指定したいのです。\symb の 2 番目の引数から「Set of Smooth Vector Fields」の部分だけを抽出する方法はありますか?
解決策: @Schrödinger の猫の解決策の簡略版が私の場合は機能しています:
\newcommand{\symb}[3][]{%
\def\mysplit##1=##2{\sym{#3}{##2}}%
\expandafter\mysplit#1%
}
答え1
次のコードでは、再定義されたルーチンは\symb
次のように動作します。
引数は\glsxtrnewsymbol
そのまま渡されます。
引数は、次のように のオプション引数\sym
から説明を抽出した後に に渡されます。\symb
引数に先頭のフレーズ「description=」が含まれていない場合は、そのまま渡されます。(フレーズ全体を囲むスペース トークン、および/または「description」と「=」の間のスペース トークンが考慮されます。)
引数に先頭のフレーズ「description=」が含まれている場合、そのフレーズは削除されます。
- 残りがスペース トークンのみで構成されている場合、または何も含まれていない場合は、抽出結果は空になり、トークンがまったく含まれなくなります。
- 残りが単一の区切られていない引数、つまり単一の非中括弧トークンまたは中括弧内にネストされたトークンのセットで構成されている場合、残り全体を囲む 1 レベルの中括弧が存在する場合は削除され、次に残り全体を囲むスペース トークンが削除されます。
- 残りが単一の区切られていない引数以外のもので構成されている場合、中括弧は削除されませんが、残り全体を囲むスペースは削除されます。
\sym
およびは利用できないため\glsxtrnewsymbol
、山括弧でネストされた、トークン化されていない形式で引数を提供するだけの「ダミー定義」を提供しました。
これはすべて即興でやったことなので、保証はありません。 ;-)
再定義されていない\symb
ルーチンと、中括弧内に任意の素材をネストすること{
、および}
それを別のマクロに渡してオプションの引数を形成する場合についての私のコメントにも注意してください。
全体の「メカニズム」は、\if..
...を一切使用せずに実装されます\else
。したがって、一致しないorまたは\fi
を含むマクロ引数によってメカニズムが混乱することはありません。\if
\else
\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}
答え2
これはそれを実行するものです。明らかに私はあなたのコマンドを持っていないので\sym
、引数が正しいことを示すものを代わりに使用します。
\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}
これは、最初の引数が空でない場合は常に、符号が含まれていることを前提としています=
。これに対して耐性を持たせることもできますが、その場合は何らかのキー管理システムを使用することをお勧めします。たとえば、すでにロードしている場合はpgf
非常に簡単になります。