TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to write a macro that expands differently depending on the pattern following it. Specifically I want to use it to allow a more readable notation for quantum mechanical states, e.g.

% 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 }

The way LaTeX works, it can expand only one of the definitions. If I skipped the last one, a possible fix would be to change the catcode of <,|,> to 11, but that brings issues of its own (e.g. by breaking \ifnum .. < .. forms).

Is there some facility in latex, maybe through a package, that allows matching a single macro to multiple patterns of subsequent tokens?

Clarification Because it came up: I don not want to define commands \bra, ket, etc, or rather this is what I did so far. I am trying to move to a solution that results in more readable code and while writing \bra <\psi_i| \Operator \ket |\psi_j> would be a step towards that target, I'd prefer a form as close as possible to <\psi_i|\Operator|\psi_j>; Pattern matching would be the closest solution I could think of that could work without preprocessing outside of latex.

Furthermore writing complex macros, that analyze the token stream, isn't something I want to do on a per-document level. I'd prefer if there was a package that abstracts such things away, such that even the definition of the pattern remains well-readable for the sake of avoiding unexpected behaviour. If TeX's \def natively supported pattern-matching, the example code above would suit that requirement.

share|improve this question
1  
This can be done using a look-ahead but we need to know the 'conditions'. In particular, how is \m<#1| different from \m<#1|#2>? (We can look after a | for 'something' but will need a clue, for example is the first case always followed by a space?) – Joseph Wright Feb 19 at 10:14
1  
@kdb That still doesn't answer the question I posed: how do we differentiate between the first pattern and the last one? What is it that tells us in the first case to stop and not look ahead for a closing >? – Joseph Wright Feb 19 at 12:03
2  
@kdb But the pattern will then absorb all of the rest of the document if there is no closing >. You have to have some restriction on what can be present in #2 to allow us to know when to stop! – Joseph Wright Feb 19 at 12:24
1  
Pattern-matching on a grabbed argument is easier (either in TeX or as @Mico suggests in Lua). However, you want to do pattern matching to define the grabbed argument, which is harder. For example, if we know that < is always ultimately followed by > we can grab everything up to > then use a variety of approaches to process the text. – Joseph Wright Feb 19 at 12:27
2  
If you accept something like \m*...* where ... can have the various forms <#1>, <#1|, |#1>, <#1|#2> or <#1|#2|#3>, then it's doable. But without a fixed terminator it would be very hard and fragile. – egreg Feb 19 at 12:38
up vote 6 down vote accepted

UPDATE Embrace the power of expl3 and xparse. I choose the delimiter ; to make the macro possible. To be honest v.2: it was quite simple and I totally lied earlier! This is the new macro

\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

Look how beautiful it is!

enter image description here

You can use the macro as follows: \BrKt<j|\otimes<k|e^{a^\dagger/\hbar}|n>\otimes|m>;, \BrKt|0>|1>|0>|1> = |3>_4; or \BrKt|m>\equiv<\Psi|A|B|\varphi>|n>;$. This allows a much greater variety then originally intended.


Old Post To be honest: I don't think you can't perfectly achieve what you want with little effort. It would be possible though. But if you stick to the basics you could use the power of xparse. I worked out the start

\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

This command structure strictly demands input of the form \m<input1|input2>, however it checks whether input1 or input2 is empty and processes the input accordingly. But note, this cannot create something like <\Psi\Phi>, without the pipe in the middle. Also note, in this realization the opening < is not mandatory and will only produce a warning if it's missing. I hope you can work with this and go on further.

share|improve this answer

This is somewhat possible with the suffix package:

\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}

However, there's a significant limitation with this approach, in that the same "suffix" can only be used once, so your proposed \m<#1> syntax cannot be supported by this package as well as \m<#1|. This no doubt makes the approach a non-starter, but I thought it would be good to add this answer for completeness.

share|improve this answer
1  
It certainly is the simplest solution that comes close. Since I made the experience that any complicated solution is likely to come back to bite me, that's a plus. But yes, overall it doesn't quite fit the purpose -- it doesn't allow avoiding the verbosity of having different macros instead of one pattern-interpreting macro. – kdb Feb 19 at 19:05

With expl3 the proposed syntax \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}

And with plain LaTeX and a bit different syntax \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}

enter image description here

PS: instead of \: the usual thing is to use \; but they look too big to me, you could use \nonscript\muskip5mu or whatever you want instead.

share|improve this answer

(Revised the Lua code after noticing that the OP doesn't want "set" notation (with curly braces) for items such as <a|b> but, instead, large angle brackets and a tall middle vertical bar.)

A comment up-front: I strongly recommend that you use a delimiter symbol that's unlikely to occur in your braket-like expressions. That way, no ambiguity can arise as to when these expressions starts and when they end. In the code below, I use & as this symbol; feel free to switch to a different one.

I'd prefer a form as close as possible to <\psi_i|\Operator|\psi_j>

With the notational convention I'm proposing, you'd write & <\psi_i|\Operator|\psi_j> &.

Here's a LuaLaTeX-based solution. The Lua function brkt is set to scan each input line and perform sequential pattern matching. Patterns for which there's a match are converted into instructions that use the macros of the braket package -- \Braket, \Bra, and \Ket. The scanning and replacing happens at a very early stage of processing, i.e., before TeX's "eyes" and "mouth" begin their work.

Two TeX-side macros are provided as well: \braketON to start the processing, and \braketOFF in case you need to stop processing at some point in the document.

enter image description here

% !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}
share|improve this answer
    
Probably having \m at the start can help in avoiding problems if multiple calls are present in the same line: just stop scanning when \m is seen. – egreg Feb 19 at 15:06
    
I'm unsure what happens if you try <\phi| < 2 or something like that. – egreg Feb 19 at 15:11
    
@egreg - I decided to rework the answer so that it assumes that the braket-like expressions are delimited by symbols that act as delimiters. I suggest using & as such a delimiter; obviously, there are many other possibilities. As you and Joseph noted in earlier comments, the presence of such explicit delimiters guarantees that the pattern matching can be carried out unambiguously. – Mico Feb 19 at 16:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.