Wie kann ich einen Befehl definieren oder neu definieren (durch Mischen von \providecommand + \renewcommand)?

Wie kann ich einen Befehl definieren oder neu definieren (durch Mischen von \providecommand + \renewcommand)?

In manchen Situationen wünschte ich, es gäbe eine Möglichkeit, einen Befehl \tmpso zu definieren,

  • wenn \tmpnicht vorhanden: Definiert\tmp
  • wenn \tmpes beendet wird: Neu definieren\tmp

\newcommandMein 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 \tmpdefiniert 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 \providecommanddefiniert #1werden soll, wenn #1es 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, \defaber mit Parametern wie \newcommand. Es ist möglich, unsere eigenen zu definieren, \newcommanddie 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 xparseMethode 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}

verwandte Informationen