
Ich verwende Latex schon seit einiger Zeit, aber nur auf die Grundlagen beschränkt. Ich versuche, wann immer möglich Pakete zu verwenden. Ich versuche jetzt, selbst einige Codes zu schreiben, um mein Latex-Dokument übersichtlicher zu gestalten. Das möchte ich erreichen:
Wenn ich definiere:
\symb{flow}{f_#1^#2}[a,b]
Ich möchte nutzen können
\flow % outputs $f_a^b$
\flow[x,y] % outputs $f_x^y$
Beachten Sie, dass die Anzahl der Indizes nicht unbedingt 2 sein muss; sie kann auch 1 oder mehr als 2 betragen.
Folgendes habe ich jetzt:
\NewDocumentCommand{\symb}{m m m}
{ \expandafter\NewDocumentCommand\csname#1\endcsname{>{\SplitList{,}}O{#3}}
{
% Not sure what I need to write here
}
}
Grundsätzlich möchte ich in der Lage sein, \symb{flow}{f_#1^#2}[a,b]
ein Makro zu definieren \flow
, das ein optionales Argument annimmt, nämlich einen durch Kommas getrennten Index der Variable. Falls das optionale Argument nicht angegeben wird, werden die Standardindizes (in diesem Fall a, b) verwendet.
In Python würde dies wie folgt geschrieben:
def symb(expr, default):
def fn(*args):
if len(args) == 0:
return expr % args
else:
return expr % default
return fn
flow = symb('$f_%s^%s$', (a, b))
flow() % outputs $f_a^b$
flow(x, y) % outputs $f_x^y$
Antwort1
Das ist möglich, allerdings sollten Sie Python nicht als Vorbild für die Programmierung in LaTeX nehmen.
In LaTeX werden Argumente in Klammern gesetzt und können nicht durch Kommalisten ersetzt werden.
Wie dem auch sei, hier ist eine Implementierung mit einer beliebigen Anzahl von Argumenten in der Vorlage (aber Sie müssen natürlich angeben, wie viele Sie möchten).
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\symb}{mmmm}
{% #1=name of command to define, #2=number of args, #3=template, #4=default
% define the internal version
\cs_new_protected:cn { kelvin_symb_#1:\prg_replicate:nn{#2}{n} } { #3 }
% define the external version
\exp_args:Nc \NewDocumentCommand { #1 } { O{#4} }
{
\__kelvin_symb_do:nnx { #1 } { #2 } { \clist_map_function:nN { ##1 } \__kelvin_symb_brace:n }
}
}
\cs_new:Nn \__kelvin_symb_do:nnn
{
\use:c { kelvin_symb_#1:\prg_replicate:nn{#2}{n} } #3
}
\cs_generate_variant:Nn \__kelvin_symb_do:nnn { nnx }
\cs_new:Nn \__kelvin_symb_brace:n { {#1} }
\ExplSyntaxOff
\symb{flow}{2}{f_{#1}^{#2}}{a,b}
\symb{foo}{4}{\int_{#1}^{#2}#3\,d#4}{0,1,x,x}
\begin{document}
$\flow$
$\flow[x,y]$
$\foo$
$\foo[a,b,f(x),x]$
\end{document}
Noch ein paar Worte zum Code. Zuerst die einfachen Dinge:
\exp_args:Nc \NewDocumentCommand { #1 } { O{#4} }
ist die expl3
Version von
\expandafter\NewDocumentCommand\csname#1\endcsname { O{#4 } }
und sollte bevorzugt werden.
Als nächstes eine Beschreibung der \symb
Funktionsweise. Zuerst wird eine interne Funktion mit so vielen Argumenten wie deklariert definiert; ihr Ersatztext wird von der angegebenen Vorlage bereitgestellt. Damit \symb{flow}{2}{f_{#1}^{#2}}{a,b}
definiert
\kelvin_symb_flow:nn { f_{#1}^{#2} }
Hinweis. Es gibt kein Problem mit der Tatsache, dass es _
sich um einen Brief im Rahmen von handelt \ExplSyntaxOn
, da die Erklärung \symb{flow}{2}{...}{...}
gegeben wirddraußendieser Umfang.
Danach definieren wir den Befehl auf Benutzerebene \flow
mit einem optionalen Argument, dessen Standard das vierte Argument von ist \symb
. Dieser Befehl ruft die zuvor definierte Funktion indirekt mittels auf \__kelvin_symb_do:nnx
.
Das erste Argument ist in diesem Fall , flow
das zweite ist die Anzahl der Argumente; ihr Zweck ist es, die innere Funktion aufrufen zu können. Das letzte Argument ist die Kommaliste (die Standardeinstellung oder die als optionales Argument angegebene \flow
), jedoch vorverarbeitet, sodass eine Liste mit geschweiften Elementen entsteht.
Die normale Version \__kelvin_symb_do:nnn
bildet einfach die interne Funktion \kelvin_symb_flow:nn
und löst das dritte Argument. Aber wir verwenden eine Variante davon; wenn
\clist_map_function:nN { #1 } \__kelvin_symb_brace:n
ist vollständig erweitert (aufgrund der x
Variante), wenn man a,b
es darauf anwendet, erhält man {a}{b}
. Somit erhalten wir
\kelvin_symb_flow:nn { a } { b }
und LaTeX erweitert sich gerne wie gewohnt auf f_{a}^{b}
.
Antwort2
Sie können beispielsweise Folgendes verwenden:
\def\sdef#1{\expandafter\def\csname#1\endcsname}
\def\symb#1#2[#3,#4]{%
\sdef{#1}{\expandafter\futurelet\expandafter\next\csname#1:a\endcsname}%
\sdef{#1:a}{\ifx\next[\csname#1:b\expandafter\endcsname
\else \csname#1:b\endcsname[#3,#4]\fi}%
\sdef{#1:b}[##1,##2]{#2}%
}
\symb{flow}{f_#1^#2}[a,b]
$\flow$ and $\flow[x,y]$.
Die zweite Version dieses Makros implementiert Ihre Anforderung aus den Kommentaren:
\def\sdef#1{\expandafter\def\csname#1\endcsname}
\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\symb#1#2[#3]{%
\sdef{#1}{\expandafter\futurelet\expandafter\next\csname#1:a\endcsname}%
\sdef{#1:a}{\ifx\next[\csname#1:b\expandafter\endcsname
\else \csname#1:c\endcsname #3,,,,,,,,\end \fi}%
\sdef{#1:b}[##1]{\def\paramslistA{#3,}\def\paramslistB{}\setparams ##1,\end,
\csname#1:c\expandafter\endcsname \paramslistB,,,,,,,,\end}%
\sdef{#1:c}##1,##2,##3,##4,##5,##6,##7,##8,##9\end{#2}%
}
\def\setparams #1,{\ifx\end#1%
\expandafter\addto\expandafter\paramslistB\expandafter{\paramslistA}%
\else \expandafter \setparamslist \paramslistA \end #1,%
\expandafter\setparams\fi}
\def\setparamslist#1,#2\end#3,{\def\paramslistA{#2}\addto\paramslistB{#3,}}
\symb{flow}{f_#1^#2}[a,b]
\symb{test}{test: 1=#1, 2=#2, 3=#3, 4=#4}[a,b,c,d]
$\flow$ and $\flow[x,y]$.
\test
\test[mmm]
\test[x,y,z]
Diese Lösung unterscheidet sich von der Lösung von egreg: Sie müssen keine komplizierten Makros erklären, es werden nur TeX-Grundelemente verwendet.
Antwort3
Dies ist ähnlich wie bei Wipet, macht aber das Argument für Symb obligatorisch, wie in den Kommentaren erläutert.
\documentclass{article}
\def\symb#1#2#3{%
\expandafter\def\csname x#1\endcsname##1##2{#2}%
\expandafter\newcommand\csname #1\endcsname[1][#3]{%
\expandafter\splitcomma\csname x#1\endcsname ##1\relax}}
\def\splitcomma#1#2,#3\relax{#1{#2}{#3}}
\begin{document}
\symb{flow}{f_#1^#2}{a,b}
$\flow$
$\flow[x,y]$
\end{document}
Und eine Version, die mehrere (bis zu 8) Einträge in der Argumentliste zulässt.
\documentclass{article}
\def\symb#1#2#3{%
\expandafter\def\csname x#1\endcsname##1##2##3##4##5##6##7##8##9{#2}%
\expandafter\newcommand\csname #1\endcsname[1][#3]{%
\expandafter\splitcomma\csname x#1\endcsname ##1,,,,,,,,,,\relax}}
\def\splitcomma#1#2,#3,#4,#5,#6,#7,#8,#9\relax{#1{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\relax}
\begin{document}
\symb{flow}{f_#1^#2}{a,b}
\symb{flowb}{f_#1^#2g_#3^#4}{a,b,c,d}
$\flow$
$\flow[x,y]$
$\flowb$
$\flowb[x,y,w,z]$
\end{document}