
\d x
나는 자주 사용되는 기호(예 : 미분 dx 또는 \v
벡터가 필요한 경우) 에 대한 수학 공식에 짧은 매크로를 자주 사용합니다.V내용을 더 쉽게 읽을 수 있도록 내 텍스트에 자주 사용합니다. 그러나 \d
다음 문자 아래의 점과 v
재정의하고 싶지 않은 hacek 악센트를 나타내기 때문에 미리 정의된 매크로와 충돌이 발생합니다 (참고문헌에 필요할 수도 있습니다...).
그래서 저는 수학 모드에서만 해당 매크로를 재정의하기 위해 다음을 생각해냈습니다.
\documentclass{article}
\usepackage{everyhook}
\newcommand{\mathdef}[2]{%
\PushPostHook{math}{\expandafter\def\csname #1\endcsname{#2}}%
\PushPostHook{display}{\expandafter\def\csname #1\endcsname{#2}}}
\mathdef{d}{\mathrm{d}}%
\begin{document}
\d x is an x with a dot below and $\int f(x) \d x$ is an integral over $x$.
\end{document}
\mathdef{\d}{\mathrm{d}}
그러나 명령이 일반 매크로(예: )처럼 정의되고 인수도 사용할 수 있기를 원하지만 , 등을 expandafter
사용한 모든 실험 unexpanded
은 제대로 작동하지 않았고 일반적인 이상한 오류 메시지만 표시되었습니다. 어떻게 할 수 있는지 힌트가 있나요?
\everymath
게다가 대용량 문서에서 그렇게 사용하면 성능이 크게 저하된다고 생각하시나요 ?
답변1
내 아이디어는 egreg의 아이디어와 매우 유사하지만 선택적 인수를 추가하여 math 명령이 인수 자체를 처리할 수 있도록 하고 싶습니다. 코드:
\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand{\mathdef}{mO{0}m}{%
\expandafter\let\csname old\string#1\endcsname=#1
\expandafter\newcommand\csname new\string#1\endcsname[#2]{#3}
\DeclareRobustCommand#1{%
\ifmmode
\expandafter\let\expandafter\next\csname new\string#1\endcsname
\else
\expandafter\let\expandafter\next\csname old\string#1\endcsname
\fi
\next
}%
}
\mathdef{\v}[1]{\tilde{#1}}
\mathdef{\d}{\mathrm{d}}
\begin{document}
Ha\v{c}ek and tilde $\v{a}+\v{b}=1$.
\d x is an x with a dot below and $\int f(x) \d x$ is an integral over $x$.
\end{document}
결과:
답변2
나는 사용하지 않을 것이다 \everymath
.
\documentclass{article}
\usepackage{letltxmacro}
\makeatletter
\newcommand{\mathdef}[2]{%
\@ifundefined{#1}{\@mathdef@new{#1}{#2}}{\@mathdef@remember{#1}{#2}}
}
\newcommand{\@mathdef@remember}[2]{%
\expandafter\LetLtxMacro
\csname textmode@#1\expandafter\endcsname
\csname #1\endcsname
\expandafter\def\csname mathmode@#1\endcsname{#2}%
\expandafter\DeclareRobustCommand\csname#1\endcsname{%
\ifmmode\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\csname mathmode@#1\endcsname}{\csname textmode@#1\endcsname}%
}%
}
\newcommand{\@mathdef@new}[2]{%
\expandafter\DeclareRobustCommand\csname#1\endcsname{#2}%
}
\makeatother
\mathdef{d}{\mathop{}\!\mathrm{d}}
\begin{document}
\d{x} is an x with a dot below and $\int f(x) \d x$ is an integral over $x$.
\end{document}
하지만 나는 이것이 좋은 방법이라고 생각하지 않습니다. 혼란스럽고 오류가 발생하기 쉽습니다.
보다\LetLtxMacro는 언제 사용하나요?에 대한 정보를 보려면 \LetLtxMacro
.
다음을 사용하면 조금 더 쉽습니다 etoolbox
.
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newcommand{\mathdef}[2]{%
\@ifundefined{#1}{\@mathdef@new{#1}{#2}}{\@mathdef@remember{#1}{#2}}
}
\newcommand{\@mathdef@remember}[2]{%
\expandafter\robustify\csname#1\endcsname
\csletcs{textmode@#1}{#1}%
\csdef{mathmode@#1}{#2}%
\protected\csdef{#1}{%
\ifmmode\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\csuse{mathmode@#1}}{\csuse{textmode@#1}}%
}%
}
\newcommand{\@mathdef@new}[2]{%
\protected\csdef{#1}{#2}%
}
\makeatother
\mathdef{d}{\mathop{}\!\mathrm{d}}
\begin{document}
\d{x} is an x with a dot below and $\int f(x) \d x$ is an integral over $x$.
\end{document}
\DeclareRobustCommand
(첫 번째 버전) 또는 \protected
(두 번째 버전)을 모두 사용하는 이유는 무엇입니까 ?
TeX가 쓰기 작업을 수행할 때 전혀 모드가 아닙니다. 특히 수학 모드가 아닙니다. 다음과 같은 단순한 정의
\newcommand{\foo}{%
\relax % if this comes first in an alignment
\ifmmode
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
\foo@math\foo@text
}
~일 것이다언제나\foo@text
에서 발견된 경우 선택하십시오 \write
. 위의 보호는 \mathdef
명령을 스스로 작성하도록 하므로 \write
시간에 선택이 이루어지지 않습니다.
왜 사용하지 않습니까 \everymath
? 다음 예제를 시도해보고 확인하세요.
\documentclass{article}
\everymath{\let\foo\foomath}
\newcommand{\foo}{Foo}
\newcommand{\foomath}{Ops}
\begin{document}
Text: \foo
Math: $\foo$
Ops: abc\textsuperscript{\foo}
\end{document}
답변3
\PushPostHook
-macro를 사용하고 싶습니다 .모든 걸-인수를 처리하는 매크로를 (재)정의하기 위한 패키지?
문제 1:
LaTeX에서 인수는 #1
및 #2
등으로 표시됩니다. 즉, 1..9 범위의 숫자 뒤에 해시 시퀀스가 표시됩니다.
중첩 정의의 경우 내부 정의에 대해 해시를 두 배로 늘려야 합니다.
\def\outsidemacro#1{%
\def\insidemacro##1{This is insidemacro's argument: ##1.}%
This is outsidemacro's argument: #1.%
}
확장하는 동안 두 개의 연속 해시가 하나의 해시로 축소됩니다. 즉, 해시 양이 절반으로 줄어듭니다.
즉, 다음과 같은 \outsidemacro{foo}
결과가 나옵니다.
\def\insidemacro#1{This is insidemacro's argument: #1.}%
This is outsidemacro's argument: foo.%
\PushPostHook
비아 \show\PushPostHook
수율 의 정의를 살펴보면 다음과 같습니다 .
> \PushPostHook=\protected\long macro:
#1#2->\eh@checkhook {#1}\PushPostHook \letcs \eh@tempi {eh@post#1}\expandafter
\gdef \csname eh@post#1\expandafter \endcsname \expandafter {\eh@tempi \eh@hook
separator #2}\undef \eh@tempi .
보시다시피 토큰은 이름이 패턴인 매크로에 보관됩니다 .\eh@post⟨name of hook⟩
예를 들어, \eh@postmath
그리고 \eh@postdisplay
.
이러한 매크로에 토큰을 추가하려면 \PushPostHook
문제의 매크로를 동일하게 만든 \eh@tempi
다음 해당 매크로 뒤에 문제의 토큰을 추가하여 문제의 매크로를 재정의합니다.확장의 \eh@tempi
.
확장은 \eh@tempi
중요한 포인트입니다.
정의에 \eh@tempi
해시가 포함된 경우( #
) 확장 중에 두 개의 연속 해시가 그 중 하나로 축소됩니다.
이는 다음을 의미합니다.
또는 \PushPostHook
에 항목을 추가해야 할 때마다 이미 있거나 있는 항목과의 연속 해시 양이 절반으로 줄어듭니다.\eh@postmath
\eh@postdisplay
\eh@postmath
\eh@postdisplay
이는 특히 또는 \PushPostHook
에 항목을 추가하기 위해 여러 번 호출할 때 문제가 됩니다 .\eh@postmath
\eh@postdisplay
\the
토큰 레지스터의 내용이 를 통해 "뱉어내면" 해시 양이 줄어들지 않기 때문에 토큰 레지스터를 통해 항목을 유지함으로써 연속 해시 양이 절반으로 줄어드는 것을 방지할 수 있습니다 . \the
동안에 "뱉어내기"가 발생하면 \edef
해시 양이 줄어들 뿐만 아니라 두 배로 늘어납니다.
만약 그렇게 한다면, 예를 들어,
\myscratchtoks{#}
\edef\mymacro{\the\myscratchtoks}
, 정의에 따르면 \mymacro
해시 양이 \myscratchtoks
두 배가 됩니다. 확장할 때 \mymacro
두 배로 늘어난 양은 절반으로 줄어들므로 확장은 \mymacro
에서 전달하는 것과 동일한 양의 해시를 전달합니다 \the\myscratchtoks
.
따라서 토큰 레지스터에 항목을 추가하고 \PushPostHook
해당 토큰 레지스터를 "플러싱"하는 데에만 사용하는 것이 좋습니다.
문제 2:
인수도 처리할 수 있는 매크로를 유지하려면 접두사 \long
또는 와 유사하게 사용할 수 있는 것을 구현하는 것이 좋습니다 \global
.
아래 예에서는 중괄호로 묶인 인수 뒤에 오는 왼쪽 중괄호로 구분된 인수를 처리하는 #{
매크로를 구현하기 위해 -notation을 사용했습니다. 매크로의 \mathcommand
는 ⟨definition text⟩
항상 중괄호 안에 중첩되어야 하므로, 앞에 오는 모든 토큰을 가져오기 위해 왼쪽 중괄호로 구분된 인수 처리를 사용할 수 있습니다 ⟨definition text⟩
.
이러한 토큰은 정의 명령 자체(예: \renewcommand*
또는 \global\long\def
), (재)정의될 제어 시퀀스 토큰 및 ⟨parameter text⟩
.
예를 들어,
\mathcommand\renewcommand*\mymacrowitharguments[2]{%
\mbox{math-arg~1: }(#1)
\mbox{ math-arg~2: }(#2)
}%
, \mathcommand
의 첫 번째(왼쪽 중괄호로 구분된) 인수는 시퀀스가 되고 \renewcommand*\mymacrowitharguments[2]
두 번째 인수는 중괄호 안에 중첩된 항목으로 구성됩니다 \mbox{math-arg~1: }(#1) \mbox{ math-arg~2: }(#2)
.
\mathcommand
시퀀스 , 즉 토큰 레지스터에 시퀀스를 추가합니다 .⟨first argument⟩{⟨second argument⟩}
\renewcommand*\mymacrowitharguments[2]{\mbox{math-arg~1: }(#1) \mbox{ math-arg~2: }(#2) }
\mymathhooktoks
\mathcommandfromname
또한 왼쪽 중괄호로 구분된 인수를 가져오고 해당 인수 뒤에 있는 항목을 가져오며 따라서 다음을 통해 형성될 수 있는 제어 시퀀스 토큰의 이름에 대해 중괄호 안에 중첩되는 매크로를 구현했습니다 \csname..\endcsname
.
예:
\mathcommandfromname\renewcommand*{mymacrowitharguments}[2]{%
\mbox{math-arg~1: }(#1)
\mbox{ math-arg~2: }(#2)
}%
수익률:
\mathcommand\renewcommand*\mymacrowitharguments[2]{%
\mbox{math-arg~1: }(#1)
\mbox{ math-arg~2: }(#2)
}%
\documentclass{article}
\usepackage{everyhook}
\newtoks\myscratchtoks
\newcommand\mymathhookmacro{}%
\PushPostHook{math}{\mymathhookmacro}%
\PushPostHook{display}{\mymathhookmacro}%
\newcommand{\mathcommand}{}%
\long\def\mathcommand#1#{\innermathcommand{#1}}%
\newcommand{\innermathcommand}[2]{%
\begingroup
\expandafter\myscratchtoks\expandafter{\mymathhookmacro#1{#2}}%
\xdef\mymathhookmacro{\the\myscratchtoks}%
\endgroup
}
\newcommand\exchange[2]{#2#1}%
\newcommand\mathcommandfromname{}%
\long\def\mathcommandfromname#1#{\romannumeral0\innermathcommandfromname{#1}}%
\newcommand\innermathcommandfromname[2]{%
\expandafter\exchange\expandafter{\csname#2\endcsname}{ \mathcommand#1}%
}%
%----------------------------------------------------------------
\newcommand*\mymacrowitharguments[2]{%
non-math-arg~1: \textbf{(#1)} %
non-math-arg~2: \textbf{(#2)}%
}%
\mathcommand\renewcommand*\mymacrowitharguments[2]{%
\mbox{math-arg~1: }(#1)
\mbox{ math-arg~2: }(#2)
}%
\newcommand*\myothermacrowitharguments[2]{%
other-non-math-arg~1: \textbf{(#1)} %
other-non-math-arg~2: \textbf{(#2)}%
}%
\mathcommandfromname\renewcommand*{myothermacrowitharguments}[2]{%
\mbox{other-math-arg~1: }(#1)
\mbox{ other-math-arg~2: }(#2)
}%
\mathcommand\renewcommand*\d{\mathrm{d}}%
\parindent=0ex
\begin{document}
\d x is an x with a dot below and $\int f(x) \d x$ is an
integral over $x$.
\bigskip
Testing with \verb|\mymacrowitharguments|:\smallskip
outside math:\\
\mymacrowitharguments{arg A}{arg B}
\smallskip
inside math:\\
$\mymacrowitharguments{arg A}{arg B}$
\bigskip
Testing with \verb|\myothermacrowitharguments|:\smallskip
outside math:\\
\myothermacrowitharguments{arg A}{arg B}
\smallskip
inside math:\\
$\myothermacrowitharguments{arg A}{arg B}$
\end{document}