math-arr.mkiv /size: 19 Kb    last modification: 2020-07-01 14:35
1%D \module
2%D   [       file=math-arr,
3%D        version=2007.07.19,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Arrows,
6%D         author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14%D We keep this file around as reference of his things were done in the
15%D past. You can still load this module but it has been replaced by more
16%D modern code.
17
18\writestatus{loading}{ConTeXt Math Macros / Arrows}
19
20\unprotect
21
22%D These will be generalized! Is it still needed in \MKIV? Also, we need to
23%D to it using regular opentype math!
24
25% Plain code:
26%
27% \def\rightarrowfill
28%   {$%
29%    \mathsurround\zeropoint
30%    \smash-%
31%    \mkern-7mu%
32%    \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
33%    \mkern-7mu%
34%    \mathord\rightarrow
35%    $}
36%
37% \def\leftarrowfill % brrr no longer in luatex
38%   {$%
39%    \mathsurround\zeropoint
40%    \mathord\leftarrow
41%    \mkern-7mu%
42%    \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
43%    \mkern-7mu
44%    \smash-%
45%    $}
46
47%D Extensible arrows are arrows that change their length according to the width of
48%D the text to be placed above and below the arrow.
49%D
50%D Since we need to define a lot of arrows, we first define some helper macros. The
51%D basic idea is to measure the width of the box to be placed above and below the
52%D arrow, and make the \quote {body} of the arrow as long as the bigger of the two
53%D widths.
54
55\installcorenamespace{matharrowsettings}
56
57\def\m_math_arrows_factor{1}
58\def\m_math_arrows_extra {0}
59
60\setvalue{\??matharrowsettings\v!none   }{\def\m_math_arrows_factor{0}}
61\setvalue{\??matharrowsettings\v!small  }{\def\m_math_arrows_extra{10}}
62\setvalue{\??matharrowsettings\v!medium }{\def\m_math_arrows_extra{15}}
63\setvalue{\??matharrowsettings\v!big    }{\def\m_math_arrows_extra{20}}
64\setvalue{\??matharrowsettings\v!normal }{}
65\setvalue{\??matharrowsettings          }{}
66\setvalue{\??matharrowsettings\s!unknown}{\doifelsenumber\p_math_spacing{\let\m_math_arrows_extra\p_math_spacing}\donothing}
67
68\def\math_arrows_construct#1#2#3#4#5% hm, looks like we do a double mathrel (a bit cleaned up .. needs checking)
69  {\begingroup
70   \let\m_math_arrows_factor\!!plusone
71   \let\m_math_arrows_extra \!!zerocount
72   \edef\p_math_spacing{#1}%
73   \csname\??matharrowsettings
74     \ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi
75   \endcsname
76   \mathsurround\zeropoint
77   \scratchmuskipone\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax
78   \scratchmuskiptwo\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax
79   \setbox\scratchboxone\hbox
80     {\normalstartimath
81      \scriptstyle
82      \mkern\scratchmuskipone\relax
83      #5\relax
84      \mkern\scratchmuskiptwo\relax
85      \normalstopimath}%
86   \setbox\scratchboxtwo\hbox
87     {\normalstartimath
88      \scriptstyle
89      \mkern\scratchmuskipone\relax
90      #4\relax
91      \mkern\scratchmuskiptwo\relax
92      \normalstopimath}%
93   \setbox\scratchboxthree\hbox{#3\displaystyle}%
94   \scratchdimenone\wd\scratchboxone\relax
95   \ifdim\wd\scratchboxtwo>\scratchdimenone
96     \scratchdimenone\wd\scratchboxtwo\relax
97   \fi
98   \ifdim\wd\scratchboxthree>\scratchdimenone
99     \scratchdimenone\wd\scratchboxthree\relax
100   \fi
101   \ifdim\wd\scratchboxthree=\scratchdimenone\else
102     \setbox\scratchboxthree\hbox to \scratchdimenone{#3\displaystyle}%
103   \fi
104   \mathrel
105     {\mathop
106        {\hpack to \scratchdimenone{\hss\box\scratchboxthree\hss}}% pack ? copy ?
107        \limits
108        \normalsuperscript{\box\scratchboxone}%
109        \normalsubscript  {\box\scratchboxtwo}}%
110   \endgroup}
111
112\let\math_arrows_construct_single\math_arrows_construct
113
114%D There are some arrows which are created by stacking two arrows. The next
115%D macro helps in defining such \quotation{double arrows}.
116
117% weird, we get a shift with the double ... but will become core luatex anyway
118%
119% \startchemicalformula
120%     \chemical{S}
121%     \chemical{+}
122%     \chemical{O_2}
123%     \chemical{EQUILIBRIUM}{boven}{onder}
124%     \chemical{SO_2}
125% \stopchemicalformula
126
127\def\math_arrows_construct_double#1#2#3#4#5#6#7% opt l r sp rs top bot
128  {\mathrel
129     {\scratchdimen.32\exheight\relax % was .22, todo: make configurable
130      \setbox\scratchboxone\hbox{\normalstartimath\math_arrows_construct{#1}{#2}{#4}{\phantom{#6}}{#7}\normalstopimath}%
131      \setbox\scratchboxtwo\hbox{\normalstartimath\math_arrows_construct{#1}{#3}{#5}{#6}{\phantom{#7}}\normalstopimath}%
132      \raise\scratchdimen\box\scratchboxone
133      \kern-\wd\scratchboxtwo
134      \lower\scratchdimen\box\scratchboxtwo}}
135
136%D \macros{definematharrow}
137%D
138%D Macro for defining new arrows. We can define two types of arrows|<|single arrows
139%D and double arrows. Single arrows are defined as
140%D
141%D \starttyping
142%D \definematharrow [xrightarrow]        [0359] [\rightarrowfill]
143%D \stoptyping
144%D
145%D The first argument is the name of the arrow (\tex {xrightarrow} in this case.) The
146%D second argument consists of a set of 4 numbers and specify the spacing correction
147%D in math units~\type {mu}. These numbers define:
148%D
149%D \startlines
150%D   1st number: arrow||tip correction
151%D   2nd number: arrow||tip correction
152%D   3rd number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
153%D   4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
154%D \stoplines
155%D
156%D The third argument is the name of the extensible fill. The third argument is optional
157%D when the arrow is redefined later (this is useful for font specific tweaking of the
158%D skips.) For example,
159%D
160%D \startbuffer
161%D \math{\xrightarrow{above}}
162%D \definematharrow[xrightarrow][0000]
163%D \math{\xrightarrow{above}}
164%D \definematharrow[xrightarrow][55{50}{50}]
165%D \math{\xrightarrow{above}}
166%D \stopbuffer
167%D \typebuffer gives {\getbuffer}
168%D
169%D The double arrows are defined as follows
170%D
171%D \starttyping
172%D \definematharrow [xrightleftharpoons] [3095,0359]
173%D                  [\rightharpoonupfill,\leftharpoondownfill]
174%D \stoptyping
175%D
176%D The second and the third set of arguments consist of comma separated values. The
177%D first element of the second argument (\type {3095}) corresponds to the spacing
178%D correction of top arrow fill (\tex{rightarrowupfill}). Similarly, \type {0359}
179%D corresponds to bottom arrow fill \tex {leftharpoondownfill}). Stacking them on
180%D top of each other we get $\xrightleftharpoons [big] {above} {below}$. The
181%D following math arrows are defined
182%D
183%D \placetable[none]{}{\starttable[|l|m|]
184%D   \NC \tex{xrightarrow}        \NC \xrightarrow        [big] \NC \NR
185%D   \NC \tex{xleftarrow}         \NC \xleftarrow         [big] \NC \NR
186%D   \NC \tex{xequal}             \NC \xequal             [big] \NC \NR
187%D   \NC \tex{xRightarrow}        \NC \xRightarrow        [big] \NC \NR
188%D   \NC \tex{xLeftarrow}         \NC \xLeftarrow         [big] \NC \NR
189%D   \NC \tex{xLeftrightarrow}    \NC \xLeftrightarrow    [big] \NC \NR
190%D   \NC \tex{xleftrightarrow}    \NC \xleftrightarrow    [big] \NC \NR
191%D   \NC \tex{xmapsto}            \NC \xmapsto            [big] \NC \NR
192%D   \NC \tex{xtwoheadrightarrow} \NC \xtwoheadrightarrow [big] \NC \NR
193%D   \NC \tex{xtwoheadleftarrow}  \NC \xtwoheadleftarrow  [big] \NC \NR
194%D   \NC \tex{xrightharpoondown}  \NC \xrightharpoondown  [big] \NC \NR
195%D   \NC \tex{xrightharpoonup}    \NC \xrightharpoonup    [big] \NC \NR
196%D   \NC \tex{xleftharpoondown}   \NC \xleftharpoondown   [big] \NC \NR
197%D   \NC \tex{xleftharpoonup}     \NC \xleftharpoonup     [big] \NC \NR
198%D   \NC \tex{xhookleftarrow}     \NC \xhookleftarrow     [big] \NC \NR
199%D   \NC \tex{xhookrightarrow}    \NC \xhookrightarrow    [big] \NC \NR
200%D   \NC \tex{xleftrightharpoons} \NC \xleftrightharpoons [big] \NC \NR
201%D   \NC \tex{xrightleftharpoons} \NC \xrightleftharpoons [big] \NC \NR
202%D \stoptable}
203
204%D If needed this can be optimized (i.e. we can preexpand using \type
205%D {\docheckedpair}).
206
207\unexpanded\def\definematharrow
208  {\doquadrupleargument\math_arrows_define}
209
210\def\math_arrows_define[#1][#2][#3][#4]% name type[none|both] template command
211  {\iffourthargument
212      \executeifdefined{math_arrows_define_#2}\gobblethreearguments{#1}{#3}{#4}%
213   \else\ifthirdargument
214      \math_arrows_define_both{#1}{#2}{#3}%
215   \else\ifsecondargument
216      \math_arrows_define_both_again{#1}{#2}{#3}%
217   \fi\fi\fi}
218
219\def\math_arrows_define_both_again#1#2#3% real dirty, this overload!
220  {\ifcsname#1\endcsname
221     \pushmacro\math_arrows_do
222     \def\math_arrows_do[##1][##2]{\setuvalue{#1}{\math_arrows_do[#2][##2]}}%
223     \csname#1\endcsname
224     \popmacro\math_arrows_do
225   \fi}
226
227\def\math_arrows_define_both#1#2#3%
228  {\setuvalue{#1}{\math_arrows_do[#2][#3]}}
229
230\unexpanded\def\math_arrows_do
231  {\doquadrupleempty\math_arrows_handle}
232
233\def\math_arrows_handle[#1][#2][#3][#4]% #3 == optional arg .. \empty can be just 'empty' [#4] gobbles spaces
234  {\def\math_arrows_handle_indeed{\math_arrows_handle_finalize[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
235   \dodoublegroupempty\math_arrows_handle_indeed}
236
237\def\math_arrows_handle_finalize[#1,#2,#3][#4,#5,#6][#7]#8#9% [#7] is the optional arg
238  {\edef\!!stringa{#2}%
239   \ifx\!!stringa\empty
240     \ifsecondargument
241       \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{#8}{#9}}%
242     \else
243       \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{}{#8}}%
244     \fi
245   \else
246     \ifsecondargument
247       \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
248     \else
249       \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{}{#8}}%
250     \fi
251   \fi}
252
253% Adapted from amsmath.
254
255%D \macros{mtharrowfill,defaultmtharrowfill}
256%D
257%D To extend the arrows we need to define a \quotation {math arrow fill}. This
258%D command takes 8 arguments: the first four correspond the second argument of
259%D \tex {definematharrow} explained above. The other three specify the tail,
260%D body and head of the arrow. The last argument specifies the math-mode in which
261%D the arrow is drawn. \tex {defaultmtharrowfill} has values tweaked to match
262%D Latin Modern fonts. For fonts that are significantly different (e.g. cows) a
263%D different set of values need to be determined.
264
265\def\mtharrowfill#1#2#3#4#5#6#7#8%
266  {\normalstartimath
267   \mathsurround\zeropoint
268   \thickmuskip\zeromuskip\medmuskip\thickmuskip\thinmuskip\thickmuskip
269   \relax#8#5%
270   \mkern-#1\onemuskip
271   \cleaders\hbox{\normalstartimath#8\mkern-#2\onemuskip#6\mkern-#3\onemuskip\normalstopimath}\hfill
272   \mkern-#4\onemuskip#7%
273   \normalstopimath}
274
275\def\defaultmtharrowfill{\mtharrowfill 7227}
276
277%D We now define some arrow fills that will be used for defining the arrows. Plain
278%D \TEX\ already defines \tex {leftarrowfill} and \tex {rightarrowfill}. The \tex
279%D {defaultmtharrowfill} command defines an arrowfill that takes an argument (so
280%D that it can also be used with over and under arrows). However the Plain \TEX\
281%D definitions of \tex {leftarrowfill} and \tex {rightarrowfill} do not take this
282%D extra argument. To be backward compatible with Plain \TEX, we define two
283%D arrowfills: \tex {specrightarrowfill} which takes an extra argument, and \tex
284%D {rightarrowfill} which does not.
285
286\unexpanded\def\specrightarrowfill   {\defaultmtharrowfill \relbar               \relbar \rightarrow}
287\unexpanded\def\specleftarrowfill    {\defaultmtharrowfill \leftarrow            \relbar \relbar}
288
289\unexpanded\def\rightarrowfill       {\specrightarrowfill\textstyle}
290\unexpanded\def\leftarrowfill        {\specleftarrowfill \textstyle}
291
292\unexpanded\def\equalfill            {\defaultmtharrowfill \Relbar               \Relbar \Relbar}
293\unexpanded\def\Rightarrowfill       {\defaultmtharrowfill \Relbar               \Relbar \Rightarrow}
294\unexpanded\def\Leftarrowfill        {\defaultmtharrowfill \Leftarrow            \Relbar \Relbar}
295\unexpanded\def\Leftrightarrowfill   {\defaultmtharrowfill \Leftarrow            \Relbar \Rightarrow}
296\unexpanded\def\leftrightarrowfill   {\defaultmtharrowfill \leftarrow            \relbar \rightarrow}
297\unexpanded\def\mapstofill           {\defaultmtharrowfill{\mapstochar\relbar}   \relbar \rightarrow}
298\unexpanded\def\twoheadrightarrowfill{\defaultmtharrowfill \relbar               \relbar \twoheadrightarrow}
299\unexpanded\def\twoheadleftarrowfill {\defaultmtharrowfill \twoheadleftarrow     \relbar \relbar}
300\unexpanded\def\rightharpoondownfill {\defaultmtharrowfill \relbar               \relbar \rightharpoondown}
301\unexpanded\def\rightharpoonupfill   {\defaultmtharrowfill \relbar               \relbar \rightharpoonup}
302\unexpanded\def\leftharpoondownfill  {\defaultmtharrowfill \leftharpoondown      \relbar \relbar}
303\unexpanded\def\leftharpoonupfill    {\defaultmtharrowfill \leftharpoonup        \relbar \relbar}
304\unexpanded\def\hookleftfill         {\defaultmtharrowfill \leftarrow            \relbar{\relbar\joinrel\rhook}}
305\unexpanded\def\hookrightfill        {\defaultmtharrowfill{\lhook\joinrel\relbar}\relbar \rightarrow}
306\unexpanded\def\relfill              {\defaultmtharrowfill \relbar               \relbar \relbar}
307
308\unexpanded\def\triplerelbar {\mathrel\equiv}
309\unexpanded\def\triplerelfill{\defaultmtharrowfill\triplerelbar\triplerelbar\triplerelbar}
310
311\unexpanded\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}}
312\unexpanded\def\doublebond{{\xequal}}
313\unexpanded\def\triplebond{{\xtriplerel}}
314
315%D A bit or arrow juggling:
316%D
317%D \startbuffer
318%D \hbox to \hsize{\rightoverleftarrowfill}
319%D \stopbuffer
320%D
321%D \typebuffer \blank \getbuffer \blank
322
323\unexpanded\def\rightoverleftarrowfill
324   {\specrightoverleftarrowfill}
325
326\unexpanded\def\specrightoverleftarrowfill
327  {\defaultmtharrowfill
328     \ctxdoublearrowfillleftend
329     \ctxdoublearrowfillmiddlepart
330     \ctxdoublearrowfillrightend
331     \textstyle}
332
333%D Now we define most commonly used arrows. These include arrows defined in \filename
334%D {amsmath.sty}, \filename {extarrows.sty}, \filename {extpfel.sty} and \filename
335%D {mathtools.sty} packages for \LATEX\ (plus a few more).
336
337\definematharrow [xrightarrow]         [0359]      [\specrightarrowfill]
338\definematharrow [xleftarrow]          [3095]      [\specleftarrowfill]
339\definematharrow [xequal]              [0099]      [\equalfill]
340\definematharrow [xRightarrow]         [0359]      [\Rightarrowfill]
341\definematharrow [xLeftarrow]          [3095]      [\Leftarrowfill]
342\definematharrow [xLeftrightarrow]     [0099]      [\Leftrightarrowfill]
343\definematharrow [xleftrightarrow]     [0099]      [\leftrightarrowfill]
344\definematharrow [xmapsto]             [3599]      [\mapstofill]
345\definematharrow [xtwoheadrightarrow]  [5009]      [\twoheadrightarrowfill]
346\definematharrow [xtwoheadleftarrow]   [0590]      [\twoheadleftarrowfill]
347\definematharrow [xrightharpoondown]   [0359]      [\rightharpoondownfill]
348\definematharrow [xrightharpoonup]     [0359]      [\rightharpoonupfill]
349\definematharrow [xleftharpoondown]    [3095]      [\leftharpoondownfill]
350\definematharrow [xleftharpoonup]      [3095]      [\leftharpoonupfill]
351\definematharrow [xhookleftarrow]      [3095]      [\hookleftfill]
352\definematharrow [xhookrightarrow]     [0395]      [\hookrightfill]
353\definematharrow [xrel]                [0099]      [\relfill]
354\definematharrow [xtriplerel]          [0099]      [\triplerelfill]
355\definematharrow [xrightoverleftarrow] [0359,3095] [\specrightarrowfill,\specleftarrowfill]
356\definematharrow [xleftrightharpoons]  [3399,3399] [\leftharpoonupfill,\rightharpoondownfill]
357\definematharrow [xrightleftharpoons]  [3399,3399] [\rightharpoonupfill,\leftharpoondownfill]
358
359%D These arrows can be used as follows:
360%D
361%D \startbuffer
362%D \startformula \xrightarrow{stuff on top}\stopformula
363%D \startformula \xrightarrow{}{stuff on top}\stopformula
364%D \startformula \xrightarrow{stuff below}{}\stopformula
365%D \startformula \xrightarrow{stuff below}{stuff on top}\stopformula
366%D
367%D \startformula \xleftarrow [none]{stuff below}{stuff on top}\stopformula
368%D \startformula \xleftarrow [small]{stuff below}{stuff on top}\stopformula
369%D \startformula \xleftarrow [medium]{stuff below}{stuff on top}\stopformula
370%D \startformula \xleftarrow [big]{stuff below}{stuff on top}\stopformula
371%D \stopbuffer
372%D
373%D \typebuffer which gives \getbuffer
374
375%D \macros{definemathoverarrow,defineunderarrow}
376%D
377%D These macros for define math-overarrows are adapted from \filename {amsmath.sty}
378
379\unexpanded\def\definemathoverarrow
380  {\dotripleargument\math_arrows_define_over}
381
382\def\math_arrows_define_over[#1][#2][#3]%
383  {\ifthirdargument
384      \setuvalue{#1}{\math_arrows_over_handle[#2][#3]}%
385    \else
386      \setuvalue{#1}{\math_arrows_over_handle[\zeropoint][#2]}%
387    \fi}
388
389\def\math_arrows_over_handle[#1][#2]%
390  {\mathpalette{\math_arrows_over_handle_indeed{#1}{#2}}}
391
392%D Note: \filename {math-pln.tex} has \type {\kern-\onepoint} and \filename
393%D {amsmath.sty} does not. We keep the kern amount configurable. This is useful
394%D for harpoons.
395
396\def\math_arrows_over_handle_indeed#1#2#3#4%
397  {\vbox{\ialign{%
398     \alignmark\alignmark
399     \crcr
400     #2#3%
401     \crcr
402     \noalign{\kern#1\nointerlineskip}%
403     \normalstartimath
404     \mathsurround\zeropoint\hfil#3#4\hfil
405     \normalstopimath
406     \crcr
407  }}}
408
409%D Now the under arrows
410
411\unexpanded\def\definemathunderarrow
412  {\dotripleargument\math_arrows_define_under}
413
414%D For underarrows the default kern is 0.3ex
415
416\def\math_arrows_define_under[#1][#2][#3]%
417  {\ifthirdargument
418      \setuvalue{#1}{\math_arrows_under_handle[#2][#3]}%
419    \else
420      \setuvalue{#1}{\math_arrows_under_handle[0.3ex][#2]}%
421    \fi}
422
423\def\math_arrows_under_handle[#1][#2]%
424  {\mathpalette{\math_arrows_under_handle_indeed{#1}{#2}}}
425
426\def\math_arrows_under_handle_indeed#1#2#3#4%
427  {\vtop{\ialign{%
428     \alignmark\alignmark
429     \crcr
430     \normalstartimath\mathsurround\zeropoint\hfil#3#4\hfil\normalstopimath
431     \crcr
432     \noalign{\nointerlineskip\kern#1}%
433     #2#3%
434     \crcr
435  }}}
436
437%D Now we define the arrows
438
439\definemathoverarrow  [overleftarrow]         [\specleftarrowfill]
440\definemathoverarrow  [overrightarrow]        [\specrightarrowfill]
441\definemathoverarrow  [overleftrightarrow]    [\leftrightarrowfill]
442\definemathoverarrow  [overtwoheadrightarrow] [\twoheadrightarrowfill]
443\definemathoverarrow  [overtwoheadleftarrow]  [\twoheadleftarrowfill]
444\definemathoverarrow  [overrightharpoondown]  [1pt] [\rightharpoondownfill]
445\definemathoverarrow  [overrightharpoonup]    [\rightharpoonupfill]
446\definemathoverarrow  [overleftharpoondown]   [1pt] [\leftharpoondownfill]
447\definemathoverarrow  [overleftharpoonup]     [\leftharpoonupfill]
448
449\definemathunderarrow [underleftarrow]        [\specleftarrowfill]
450\definemathunderarrow [underrightarrow]       [\specrightarrowfill]
451\definemathunderarrow [underleftrightarrow]   [\leftrightarrowfill]
452\definemathunderarrow [undertwoheadrightarrow][\twoheadrightarrowfill]
453\definemathunderarrow [undertwoheadleftarrow] [\twoheadleftarrowfill]
454\definemathunderarrow [underrightharpoondown] [\rightharpoondownfill]
455\definemathunderarrow [underrightharpoonup]   [\rightharpoonupfill]
456\definemathunderarrow [underleftharpoondown]  [\leftharpoondownfill]
457\definemathunderarrow [underleftharpoonup]    [\leftharpoonupfill]
458
459%D These can be used as follows:
460%D
461%D \startbuffer
462%D  $\overleftarrow{A}$ $\overleftarrow{ABC}$
463%D  $a_{\overleftarrow{A}}$ $b_{\overleftarrow{ABC}}$
464%D \stopbuffer
465%D \typebuffer which gives \getbuffer
466
467%D TODO: Possibly have a single arrow command define all the arrows.
468
469\protect \endinput
470