In manchen Situationen wünschte ich, es gäbe eine Möglichkeit, einen Befehl \tmp
so zu definieren,
- wenn
\tmp
nicht vorhanden: Definiert\tmp
- wenn
\tmp
es beendet wird: Neu definieren\tmp
\newcommand
Mein aktueller Ansatz besteht einfach darin, entweder oder zu verwenden \renewcommand
. Dies bedeutet jedoch, dass ich häufig von einer Version zur anderen wechseln muss, wenn ich meine Dokumente neu anordne, und schränkt manchmal die allgemeine Wiederverwendbarkeit meines Codes ein.
Indiese FrageIch habe etwas über gelernt \providecommand
, was mein Problem fast löst: Es kann unabhängig davon verwendet werden, ob \tmp
definiert ist, aber es definiert nur beim ersten Vorkommen und überschreibt nicht. Dies führte mich zu dem naiven Versuch:
\newcommand{\overwritecommand}[2]{
\providecommand{#1}{#2}
\renewcommand{#1}{#2}
}
Allerdings ist dieser Ansatz offensichtlich nicht allgemein genug:
% it works for
\overwritecommand{\tmp}{test}
% but not for commands with arguments like
\overwritecommand{\tmp}[1]{test: #1}
% Error: You can't use `macro parameter character #' in horizontal mode.
Gibt es eine andere Möglichkeit, das zu erreichen?definieren oder überschreibenVerhalten?
Antwort1
Ja, es gibt eine Methode:
\newcommand{\declarecommand}[1]{\providecommand{#1}{}\renewcommand{#1}}
Warum funktioniert es? Weil TeX Makroerweiterung verwendet und es irrelevant ist, was \providecommand
definiert #1
werden soll, wenn #1
es nicht definiert wurde, weil Sie es sofort neu definieren.
Jetzt, da Sie wissen, wie es geht, versuchen Sie es
\declarecommand{\box}[1]{\fbox{#1}}
und genieße das Wrack!
DortIstein Grund, warum LaTeX keine Funktion bietet \declarecommand
: SieMUSSAchten Sie darauf, ob Sie einen vorhandenen Befehl neu definieren.
Wenn Sie das optionale zulassen möchten *
, dann
\makeatletter
\newcommand\declarecommand{\@star@or@long\@declarecommand}
\newcommand\@declarecommand[1]{%
\provide@command{#1}{}%
\renew@command{#1}%
}
\makeatother
wird tun.
Antwort2
Ich verstehe, dass Sie das brauchen, \def
aber mit Parametern wie \newcommand
. Es ist möglich, unsere eigenen zu definieren, \newcommand
die ignorieren, ob die definierte Steuersequenz eine Bedeutung hat. Zum Beispiel können wir den Code von verwendendiese Seite:
\def\newcommand#1{\isnextchar[{\newcommandA#1}{\newcommandA#1[0]}}
\def\newcommandA#1[#2]{\edef\tmpp{\ifcase#2%
\or1\or12\or123\or1234\or12345\or123456\or1234567\or12345678\or123456789\fi}%
\edef\tmpp{\expandafter\addhashs\tmpp.}%
\isnextchar[{\newcommandB#1}{\long\expandafter\def\expandafter#1\tmpp}%
}
\def\newcommandB#1[#2]{%
\def#1{\isnextchar[{\runcommand#1}{\runcommand#1[#2]}}%
\long\expandafter\def\csname\string#1X\expandafter\endcsname\tmpp
}
\def\addhashs#1{\ifx.#1\else #####1\expandafter\addhashs\fi}
\long\def\runcommand#1[#2]{\csname\string#1X\endcsname{#2}}
Antwort3
Da die klassischen Beispiele bereits gezeigt wurden, füge ich nur noch die xparse
Methode hinzu, die recht benutzerfreundlich ist:
\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand{\foo}{m}
{Foo: #1}
\begin{document}
\foo{bar}
\DeclareDocumentCommand{\foo}{om}
{\IfNoValueTF{#1}%
{Bar: no optional, just #2}%
{Bar: optional = #1, plus #2}%
}%
\foo{Baz}
\foo[Bar]{Baz}
\end{document}