
그에 따른 패턴에 따라 다르게 확장되는 매크로를 작성하고 싶습니다. 특히 나는 양자 역학적 상태에 대해 더 읽기 쉬운 표기법을 허용하기 위해 그것을 사용하고 싶습니다.
% Non-working example
\def \m<#1| { \left\langle #1 \right|}
\def \m|#1> { \left| #1 \right\rangle }
\def \m<#1> { \left\langle #1 \right\rangle }
\def \m<#1|#2> { \left\langle #1 \middle| #2 \right\rangle }
LaTeX의 작동 방식은 정의 중 하나만 확장할 수 있습니다. 마지막 항목을 건너뛴 경우 가능한 수정 방법은 <
, |
, 의 catcode를 >
11로 변경하는 것이지만 그 자체로 문제가 발생합니다(예: \ifnum .. < ..
양식 깨짐).
패키지를 통해 단일 매크로를 후속 토큰의 여러 패턴과 일치시킬 수 있는 기능이 라텍스에 있습니까?
설명그것이 나왔기 때문입니다: 나는 명령을 정의하고 싶지 않습니다 \bra
. ket
또는 오히려 이것이 내가 지금까지 한 일입니다. 나는 더 읽기 쉬운 코드를 생성하는 솔루션으로 이동하려고 노력하고 있으며 작성하는 것이 \bra <\psi_i| \Operator \ket |\psi_j>
해당 목표를 향한 단계이기는 하지만 가능한 한 <\psi_i|\Operator|\psi_j>
; 패턴 일치는 라텍스 외부의 전처리 없이도 작동할 수 있다고 생각하는 가장 가까운 솔루션이 될 것입니다.
게다가 토큰 스트림을 분석하는 복잡한 매크로를 작성하는 것은 문서별 수준에서 수행하고 싶은 작업이 아닙니다. 예상치 못한 동작을 피하기 위해 패턴의 정의조차 쉽게 읽을 수 있도록 그러한 것들을 추상화하는 패키지가 있다면 더 좋습니다. TeX가 \def
기본적으로 패턴 일치를 지원하는 경우 위의 예제 코드는 해당 요구 사항에 적합합니다.
답변1
업데이트expl3
및 의 힘을 활용하세요 xparse
. ;
매크로를 가능하게 하기 위해 구분 기호를 선택했습니다 . 솔직히 말해서 v.2: 아주 간단했고 아까까지 완전히 거짓말을 했어요! 새로운 매크로입니다
\ExplSyntaxOn
\tl_new:N \kdb_temp
\DeclareDocumentCommand{\BrKt}{u;}%
{
\left.
\tl_set:Nn \kdb_temp {#1}
\tl_replace_all:Nnn \kdb_temp{<}{\middle\langle}
\tl_replace_all:Nnn \kdb_temp{|}{\middle|}
\tl_replace_all:Nnn \kdb_temp{>}{\middle\rangle}
\tl_use:N \kdb_temp
\right.
}
\ExplSyntaxOff
얼마나 아름다운지 보세요!
다음과 같이 매크로를 사용할 수 있습니다: \BrKt<j|\otimes<k|e^{a^\dagger/\hbar}|n>\otimes|m>;
, \BrKt|0>|1>|0>|1> = |3>_4;
또는 \BrKt|m>\equiv<\Psi|A|B|\varphi>|n>;$
. 이는 원래 의도했던 것보다 훨씬 더 다양한 다양성을 허용합니다.
오래된 게시물
솔직히 말하면, 적은 노력으로 원하는 것을 완벽하게 달성할 수는 없다고 생각합니다. 그래도 가능할 것입니다. 하지만 기본에 충실하면 의 힘을 활용할 수 있습니다 xparse
. 나는 시작을 준비했다
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareDocumentCommand{\m}{t< u{|} u>}%
{
\IfBooleanTF{#1}{}{\GenericWarning{}{Watch out! A missing "<" encountered!}}
\if\relax\detokenize{#2}\relax
\if\relax\detokenize{#3}\relax
% \langle\rangle
\else
\left| #3\right\rangle
\fi
\else
\if\relax\detokenize{#3}\relax
\left\langle #2\right|
\else
\left\langle #2 \middle| #3\right\rangle
\fi
\fi
}
\ExplSyntaxOff
이 명령 구조는 형식의 입력을 엄격하게 요구 \m<input1|input2>
하지만 비어 있는지 여부를 확인 input1
하고 input2
그에 따라 입력을 처리합니다. 하지만 <\Psi\Phi>
중간에 파이프가 없으면 와 같은 것을 만들 수 없습니다 . 또한 이 구현에서는 열기가 <
필수가 아니며 누락된 경우에만 경고가 생성됩니다. 나는 당신이 이것으로 일하고 더 나아갈 수 있기를 바랍니다.
답변2
이는 접미사 패키지를 사용하면 어느 정도 가능합니다:
\documentclass{article}
\usepackage{suffix}
\begin{document}
\WithSuffix\def\m<#1|{\left\langle #1 \right|}
\WithSuffix\def\m|#1>{\left| #1 \right\rangle}
\[ \m<x| \quad \m|y> \]
\end{document}
그러나 이 접근 방식에는 동일한 "접미사"를 한 번만 사용할 수 있다는 점에서 상당한 제한이 있습니다. 따라서 제안된 \m<#1>
구문은 이 패키지와 에서 지원될 수 없습니다 \m<#1|
. 이로 인해 접근 방식이 시작되지 않는 것은 의심할 여지가 없지만 완전성을 위해 이 답변을 추가하는 것이 좋을 것이라고 생각했습니다.
답변3
expl3
제안된 구문을 사용합니다 \m{<x|y>}
.
\documentclass{article}
\usepackage{mathtools,xparse}
\usepackage{mleftright}
\ExplSyntaxOn
\NewDocumentCommand \m { m } { \kdb_m:n {\begm#1\endm} }
\cs_new_protected:Npn \kdb_m:n #1
{
\group_begin:
\tl_set:Nn \l_tmpa_tl {#1}
\tl_replace_once:Nnn \l_tmpa_tl { \begm< } { \mleft\langle }
\tl_replace_once:Nnn \l_tmpa_tl { \begm| } { \mleft\lvert }
\tl_replace_once:Nnn \l_tmpa_tl { >\endm } { \mright\rangle }
\tl_replace_once:Nnn \l_tmpa_tl { |\endm } { \mright\rvert }
\tl_replace_all:Nnn \l_tmpa_tl { | } { \:\middle\vert\: }
\tl_use:N \l_tmpa_tl
\group_end:
}
\ExplSyntaxOff
\begin{document}
\[
\m{<x>} \quad \m{<x|} \quad \m{|x>} \quad \m{<x|y|z>} \quad \m{<x^{2^{2^{2^{2^{2^2}}}}}|y>}
\]
\end{document}
그리고 일반 LaTeX와 약간 다른 구문을 사용합니다 \m<x|>
.
\documentclass{article}
\usepackage{mathtools}
\usepackage{mleftright}
\makeatletter
\def\activevert{\@ifnextchar\mlast{\mright\rvert\@gobble}{\:\middle\vert\:}}
{\catcode`\|=\active\gdef|{\activevert}}
\gdef\m<#1>{\begingroup\mathcode`\|="8000
\@ifnextchar|{\mleft\lvert\@gobble}{\mleft\langle}#1\mlast\endgroup}
\def\mlast{\mright\rangle}
\makeatother
\begin{document}
\[
\m<x> \quad \m<x|> \quad \m<|x> \quad \m<x|y|z> \quad \m<x^{2^{2^{2^{2^{2^2}}}}}|y>
\]
\end{document}
추신: \:
일반적인 방법 \;
대신에 사용하는 것이 나에게는 너무 커 보입니다. \nonscript\muskip5mu
대신 원하는 대로 사용할 수 있습니다.
답변4
<a|b>
(OP가 큰 꺾쇠 괄호와 긴 중앙 수직 막대와 같은 항목에 대해 "설정" 표기법(중괄호 사용)을 원하지 않는다는 점을 알아낸 후 Lua 코드를 수정했습니다 .)
미리 설명: 괄호와 같은 표현에서는 발생할 가능성이 없는 구분 기호를 사용하는 것이 좋습니다. 그렇게 하면 이러한 표현이 언제 시작되고 언제 끝나는지에 대해 모호함이 발생하지 않습니다. 아래 코드에서는 &
이 기호를 사용합니다. 자유롭게 다른 것으로 전환해 보세요.
나는 가능한 한 가까운 형태를 선호한다.
<\psi_i|\Operator|\psi_j>
내가 제안하는 표기법 규칙에 따라 & <\psi_i|\Operator|\psi_j> &
.
LuaLaTeX 기반 솔루션은 다음과 같습니다. Lua 함수는 brkt
각 입력 라인을 스캔하고 순차적인 패턴 매칭을 수행하도록 설정됩니다. 일치하는 패턴은 패키지의 매크로 braket
( \Braket
, \Bra
및 ) 를 사용하는 명령으로 변환됩니다 \Ket
. 스캐닝 및 교체는 처리 초기 단계에서 발생합니다. 즉,~ 전에TeX의 "눈"과 "입"이 작업을 시작합니다.
두 개의 TeX 측 매크로도 제공됩니다. \braketON
처리를 시작하고 \braketOFF
문서의 특정 지점에서 처리를 중지해야 하는 경우입니다.
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode,braket,mathtools,mleftright}
\DeclarePairedDelimiter\abs\lvert\rvert % just for this example
%% Lua-side code
\begin{luacode}
function brkt ( buff )
buff = string.gsub ( buff, "&[%s]-<([^&]-)|([^&]-)|([^&]-)>[%s]-&", "\\Braket{%1|%2|%3}" )
buff = string.gsub ( buff, "&[%s]-<([^&]-)|([^&]-)>[%s]-&" , "\\mleft\\langle %1\\;\\middle|\\; %2\\mright\\rangle" )
buff = string.gsub ( buff, "&[%s]-<([^&]-)>[%s]-&", "\\mleft\\langle %1\\mright\\rangle " )
buff = string.gsub ( buff, "&[%s]-<([^&]-)%|[%s]-&", "\\Bra{%1}" )
buff = string.gsub ( buff, "&[%s]-|([^&]-)>[%s]-&", "\\Ket{%1}" )
return buff
end
\end{luacode}
%% TeX-side code
\newcommand\braketON{\directlua{%
luatexbase.add_to_callback ( "process_input_buffer", brkt, "brkt" )}}
\newcommand\braketOFF{\directlua{%
luatexbase.remove_from_callback ( "process_input_buffer", "brkt" )}}
\begin{document}
\braketON
$
&< \phi | \frac{\partial^2}{\partial t^2} | \psi > &, \quad
& <x\in\mathbf{R}^2 | 0<\abs*{\frac{x}{2}}<5 > & , \quad
& <\frac{a}{b},\frac{c}{d}> &$
\medskip
$ \displaystyle
& < \phi | \frac{\partial^2}{\partial t^2} | \psi > &, \quad
&<x\in\mathbf{R}^2 | 0<\abs*{\frac{x}{2}}<5 >&,
\quad
& <\frac{a}{b},\frac{c}{d}> &$
\medskip
$ &<A|&, &<B|&, &|C>&, &<D|& $
\bigskip
$ & <x^{2^{2^{2^{2^{2^2}}}}}|y> &$ % with a nod to @Manuel's code :-)
\end{document}