1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
|
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{dvgloss}[2012/08/06 v0.1 Flexible glossing commands]
%<*driver>
\documentclass{article}
\usepackage{doc}
\usepackage{dvgloss}
\usepackage{expex}
\usepackage{sverb}
\EnableCrossrefs
\RecordChanges
\aboveglskip=-3pt
\begin{document}
\DocInput{dvgloss.dtx}
\end{document}
%</driver>
% \fi
% \title{The \textsf{dvgloss} package}
% \author{Dan Bridges Velleman}
% \maketitle
%\tableofcontents
%\section{What it does}
%This is a package that lets you set interlinear linguistic examples like
%the one below:
%\begin{demo}[w]{A linguistic example}
%\gl{{K'a tee} ka-r-il ri achih ri jun keej xaa maa pwaq
% k-u-kisii-j.}
% {{suddenly} {\sc inc-a}3s-see the man the one horse
% just {\sc exclam} money {\sc inc-a}3s-shit-{\sc ss}}
%\ft{Suddenly, the man saw a horse that was just shitting money.}
%\lb{Mondloch 1981}
%\end{demo}
%
%Some characters have been set up as shortcuts for
%various useful things within an example --- inserting a line break
%(using {\tt /})
%putting subscripts on brackets (\emph{e.g.}~\verb+]Contr+ in the example
%below), etcetera.
%
%\begin{demo}[w]{Using a shortcut}
%\gl{No [ morir\'e ]Contr / {sino que} [ vivir\'e ]Contr}
% {not will.die but will.live}
%\ft{You will not die, but will live.}
%\end{demo}
%What makes this package different from others that exist so far (and in
% particular from
%{\sf expex}, which offers a similar set of shortcuts) is that these
%shortcuts are \emph{customizable}. You can declare new characters as shortcuts,
%change the meanings of existing shortcuts, and so on. For instance, if the
%slash hadn't already been set up as a newline character, you could make it
%one like this:
%\begin{verbatim}
%\makeglshortcut / {\par}
%\end{verbatim}
%If you wanted to repurpose it --- let's say you've been using it to mark
%prosodic boundaries, but you decide you want those to show up as the IPA
%double-pipe character as in the example below ---
%you could do that too.
%
%\begin{demo}[w]{Redefining a shortcut}
%\begingroup
%\makeglshortcut / {\unskip\quad$\|$\quad}
%\gl{No [ morir\'e ]Contr / {sino que} [ vivir\'e ]Contr}
% {not will.die rather will.live}
%\ft{You will not die, but will live.}
%\endgroup
%\end{demo}
%
%Finally, for one-off situations where you don't want to define a new shortcut,
%there is an ``escape character'' which lets you issue any command you want from
%within an argument of \verb+\gl+. Suppose you redefine {\tt /} to generate the
%double-pipe character, but then you run into a tricky formatting situation
%where you really need to force a line break. Just say \verb+!{\par}+ --- or,
%for that matter, \verb+!{\par\vspace{\jot}\mbox{}\qquad}+, if that's what
%floats your boat --- and you'll get what you want. (The default escape character
%is {\tt !}, but if you're a Khoisanist or otherwise need to start words with
%a bang, you can redefine it to something else.)
%\section{What it doesn't do}
%\begin{itemize}
%\item It doesn't handle example numbering. There are plenty of other packages
% that do, so I doubt I'll bother to reinvent that particular wheel any time
% soon.
%\item It doesn't do three-line glosses, or anything bigger. This is a dumb
% limit and could easily be removed --- but I probably won't get around to it
% unless someone else asks, because two-line glosses are all I ever use.
%\item Shortcuts or escaped commands can take arguments, and can (if you arrange
% it right) take scope over more than one word of interlinear gloss; but there
% are limits --- in particular, scope-taking commands can't be \emph{nested}.
% This is a limit that could in principle be removed, but it would take some work.
%\end{itemize}
% So for instance, as an example of that last limit: you can define a pair of shortcut characters that will
% cause a box to be drawn around any number of intervening words, as in the example below; but
% you will not be able to use those shortcuts to produce nested boxes.
%
%\begin{demo}[w]{A scope-taking shortcut}
%\gl{Los * frase-s nominal-es * est\'a-n en * caja-s. * No s\'e porqu\'e.}
% {the phrase-pl nominal-pl are-3pl in box-pl not know.1sg why}
%\ft{The noun phrases are in boxes. I don't know why.}
%\end{demo}
%
%\section{How to use it}
%\subsection{The basics}
% \begin{macro}{\gl}
%\begin{macro}{\ft}
% The \verb+\gl+ macro takes two arguments. It treats each argument as a list of
% (space-delimited) items, and aligns the items from the first argument atop the
% items from the second.
%
% The \verb+\ft+ macro is for putting a \emph{free translation} after an
% interlinear gloss. It takes a single argument.
%
%\begin{demo}[w]{A generic example}
%\gl{dolorem ipsum quia dolor sit amet}
% {pain.acc.sg itself.acc.sg because
% because pain.nom.sg be.3sg.subj love.3sg}
%\ft{``loves pain itself because it is pain''}
%\end{demo}
%
%\end{macro}
% \end{macro}
%\begin{macro}{\lb}
% The \verb+\lb+ macro gives you a ``label'' --- a bit of text set on the same line
% as what came before (if there's room) but pushed right to the end of the line.
% You can use this, among other things, for citations.
%
%\begin{demo}[w]{An example with a label}
%\gl{dolorem ipsum quia dolor sit amet}
% {pain.acc.sg itself.acc.sg because pain.nom.sg be.3sg.subj love.3sg}
%\ft{loves pain itself just for being pain}
%\lb{Cicero}
%\end{demo}
% If there isn't room for the label on one line, a line break will be added.
%
%\begin{demo}[w]{An example with a long label}
%\gl{dolorem ipsum quia dolor sit amet}
% {pain.acc.sg itself.acc.sg because pain.nom.sg be.3sg.subj love.3sg}
%\ft{loves pain itself just for being pain}
%\lb{Cicero, \emph{de Finibus Bonorum et Malorum}}
%\end{demo}
%\end{macro}
%
%\subsection{Grouping}
%You can use curly braces to group multiple words together; \verb+\gl+ will
% then treat them like a single word.
%
%\begin{demo}{Grouping two words together}
%\gl{Edormi crapulam}
% {{sleep off} hangover}
%\ft{``Sleep off that hangover.''}
%\lb{Cicero, Philippic 2 30}
%\end{demo}
%
%The \verb+\gl+ macro ignores spaces in all the same places that \LaTeX\ normally
%ignores spaces --- for instance after a control sequence. To make sure that
%a space after a control sequence will be recognized, wrap the control sequence
%in curly braces, as in the first two words below.
%
%\begin{demo}{Spaces ignored after control sequences}
%\gl{{\aa} {n\aa} Bl\aa-\aa s-en}
% {to reach blue-ridge-def}
%\ft{to reach Bl\aa\aa sen}
%\end{demo}
%\subsection{Prebuilt shortcuts}
% For a shortcut character to do anything at all, (i) it must be in the first
% argument of \verb+\gl+, and (ii) it must be at the beginning of a word.
%
% If the shortcut character has non-space characters after it, they will be
% treated as an argument. The right-bracket shortcut which we saw back in
% \S1 is an example of this: if you type \verb+]Contr+, then \verb+Contr+ is
% treated as the shortcut's argument --- which in this case means it's typeset
% as a subscript.
%
% \begin{itemize}
% \item[\tt /] Insert a line break. The argument, if present, specifies an
% amount of extra vertical space to be added afterward.
% \item[{$\tt [$}] Insert a left bracket in the top line, with nothing aligned
% with it below. The argument, if present, specifies a label to be set as a
% subscript to the left bracket.
% \item[{$\tt ]$}] As above, but insert a right bracket.
% \item[\tt * *] Everything between the two asterisks is set with a
% \verb+\framebox+ around it. If an argument is present after the second
% asterisk, it's set as a label on top of the \verb+\framebox+.
% \end{itemize}
%
%\subsection{New shortcuts}
%\begin{macro}{\makeglshortcut}
%To define a new shortcut along the lines of \verb+/+ and \verb+[+, use the command
%\verb+\makeglshortcut+. It takes two arguments --- the first is the character you
%want to turn into a shortcut, the second is the macro code that will be executed when
%that character is encountered. If the shortcut character is encountered with other,
%non-space characters after it, those will be passed to the macro code you supply as
%an argument --- so you can capture those characters as \verb+#1+.
% (If you try to do something with \verb+#1+ but the user hasn't supplied an argument,
% then \verb+#1+will be empty. You might want to test for this --- as in the example
% below --- if this is an issue. If the user does supply an argument, but you don't
% do anything with it, then that's not a problem --- the argument will be silently
% discarded.)
%\end{macro}
%We've already seen an example of a shortcut definition that doesn't use an argument.
%\begin{verbatim}
%\makeglshortcut / {\par}
%\end{verbatim}
%Here's an example of one which does.
%\begin{verbatim}
%\makeglshortcut / {\par\ifx#1\empty\else\vskip#1\fi}
%\end{verbatim}
%
%Shortcuts have to be single characters. \verb+\makeglshortcut{somethingverylong}{code}+ will
%not do what you want.
%\begin{macro}{\makeglsurround}
%To define a new shortcut along the lines of \verb+*+ --- a set of delimiters which can surround
% multiple
%words of glossed text and ``take scope'' over them --- use the command \verb+\makeglsurround+.
%It takes three arguments: the left-hand delimiter, the right-hand delimiter, and the code
%that will be executed when they're encountered. The two delimiters can be the same --- as
%with \verb+*+, above --- but they don't have to be.
%
%If there are extra non-space characters after the left-hand delimiter, they are passed in as
%argument \verb+#1+. The characters between the two delimiters are passed in as argument
%\verb+#2+. Extra non-space characters after the right-hand delimiter are passed in as argument
%\verb+#3+. You'll almost certainly want to do something with \verb+#2+, but ignoring \verb+#1+
%and \verb+#3+ is completely fine.
%\end{macro}
%As an example, here's how the asterisk shortcut was defined:
%\begin{verbatim}
%\makeglsurround ** {%
% \rlap{\raisebox{1.5em}{\footnotesize\sf#3}}%
% \fbox{\noglstrut#2\unskip}\glspace}
%\end{verbatim}
%
%\subsection{The escape character}
%Spacing and line-beaking commands, among others, need to be ``escaped'' if you want to use
%them inside of \verb+\gl+. (See \S4 for an explanation of why this is. For now, just
%trust me.) The escape character by default is \verb+!+, and it's best to enclose whatever
%comes after it in curly braces. So you could use \verb+!{\par)}+ to insert a new line if
%you'd already redefined \verb+/+, or \verb+!{\qquad}+ to insert some extra horizontal space.
%
%\macro{\glescape}
%If you want to change the escape character, redefine \verb+\glescape+. Like shortcuts,
%the escape has to be a single character. \verb+\def\glescape{averylongescape}+ will not
%do what you want.
%\section{What's going on}
%
% Internally, there is a command called \verb+\glossword+ which is responsible for stacking
% two words on top of one another. The arguments you give to the \verb+\gl+ command are
% converted into a series of \verb+\glossword+s, like so:
% \begin{verbatim}
% \gl{a b c d}{1 2 3 4}
% ===>
% \glossword{a}{1}
% \glossword{b}{2}
% \glossword{c}{3}
% \glossword{d}{4}
% \end{verbatim}
%
% Normally, command sequences that appear inside of \verb+\gl+ will be wrapped up inside a
% \verb+\glossword+. Sometimes this is what you want.
% \begin{verbatim}
% \gl{a b \bf c d}{1 2 3 4}
% ===>
% \glossword{a}{1}
% \glossword{b}{2}
% \glossword{\bf c}{3}
% \glossword{d}{4}
% \end{verbatim}
% But sometimes it is really not at all what you want.
% \begin{verbatim}
% \gl{a b \par c d}{1 2 3 4}
% ===>
% \glossword{a}{1}
% \glossword{b}{2}
% \glossword{\par c}{3}
% \glossword{d}{4}
% \end{verbatim}
%
% So we need a way to get a command like \verb+\par+ to show up \emph{outside} of
% a \verb+\glossword+. That's what the escape character is for.
% \begin{verbatim}
% \gl{a b !{\par} c d}{1 2 3 4}
% ===>
% \glossword{a}{1}
% \glossword{b}{2}
% \par
% \glossword{c}{3}
% \glossword{d}{4}
% \end{verbatim}
%
% The expansion of a shortcut character also ends up outside of any \verb+\glossword+s.
% \begin{verbatim}
% \gl{a b / c d}{1 2 3 4}
% ===>
% \glossword{a}{1}
% \glossword{b}{2}
% \par
% \glossword{c}{3}
% \glossword{d}{4}
% \end{verbatim}
%
% \StopEventually{}
%\section{Code}
% To begin with we set up temporary token list registers, and some spacing and formatting parameters.
% \begin{macrocode}
\newtoks\ta\newtoks\tb
\newdimen\glhangindent\glhangindent=2em
\newdimen\betweenglskip\betweenglskip=1\jot
\newdimen\withinglskip\withinglskip=0pt
\newdimen\aboveglftskip\aboveglftskip=2\jot
\newdimen\aboveglskip\aboveglftskip=2\jot
\newdimen\glstrutheight\newdimen\glstrutdepth
\def\glspace{\penalty0\hspace{1ex plus 2em minus 2pt}}
\def\everygla{\itshape}
\def\everyglb{}
% \end{macrocode}
% We also specify an escape character.
% \begin{macrocode}
\def\glescape{!}
% \end{macrocode}
%
%\begin{macro}{\addtokens}
%\begin{macro}{\popoff}
% Here's some helper macros for wrangling lists in which the items are separated
% by spaces.
% \begin{macrocode}
\long\def\addtokens#1\to#2{\ta={#1}\tb=\expandafter{#2}\edef#2{\the\tb\the\ta}}
\def\pop#1\to#2{\expandafter\popoff#1\to#2\remainderin#1}
\long\def\popoff#1 #2\to#3\remainderin#4{#3={#1}\def#4{#2}}
% \end{macrocode}
%\end{macro}
%\end{macro}
%\begin{macro}{\split}
%\begin{macro}{\istchar}
%\begin{macro}{\restchars}
% Here's one
% for splitting off a single token from a longer string. If you
% execute \verb+\split{Lorem}+, then the \verb+L+ is stored in
% \verb+\istchar+ and the rest of the word --- \verb+orem+ --- is stored in
% \verb+\restchars+.
% \begin{macrocode}
\long\def\split#1{\expandafter\ssplit#1\xyzzy}
\long\def\ssplit#1#2\xyzzy{\gdef\istchar{#1}\gdef\restchars{#2}}
% \end{macrocode}
%\end{macro}
%\end{macro}
%\end{macro}
%
%\begin{macro}{\ifnotin}
% There's one truly devious helper macro here: a really tricky way of testing
% whether one serious of tokens occurs
% within another. This is cribbed from the doc package, which credits Michael
% Spivak with the original invention.
% \begin{macrocode}
\def\ifnotin#1#2{%
\def\@ifnotin##1#1##2##3\zyzzy{\ifx\ifnotfound##2}%
\expandafter\@ifnotin#2#1\notfound\zyzzy}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\ifspecial}
%\begin{macro}{\checkspecial}
%\begin{macro}{\makespecial}
% We need this bit of deviousness because we're going to keep a list of characters that have been
% declared as special shortcuts. \verb+\makespecial+ adds something to the list;
% \verb+\checkspecial+ checks whether it's on the list (using \verb+\ifnotin+) and stores the answer in
% \verb+\ifspecial+.
% \begin{macrocode}
\newif\ifspecial
\def\dvglspecials{}
\def\checkspecial#1{%
\ifnotin#1{\dvglspecials}\specialfalse\else\specialtrue\fi}
\def\makespecial#1{%
\xdef\dvglspecials{\dvglspecials#1}}
% \end{macrocode}
%\end{macro}
%\end{macro}
%\end{macro}
%
%\subsection{Glossing}
%\begin{macro}{\glossword}
% First we define the basic formatting macro: it stacks a word and its gloss
% atop one another.
% \begin{macrocode}
\def\glossword#1#2{%
\mbox{\vtop{\halign{##\hfil\cr\everygla#1\strut\cr\everyglb#2\strut\cr}}}%
\glstrut\glspace}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\zipper}
% Now we have the rearranging macro.
% To use a functional programming analogy:
% \verb+\zipper\a\and\b\to\c+ basically means \verb+c = zipWith(glossword) a b+.
% In other words, if \verb+\a+ is a list macro containing the tokens \verb+1 2 3+
% and \verb+\b+ is a list macro containing the tokens \verb+4 5 6+, and we execute
% \verb+\zipper\a\and\b\to\c+, then \verb+\c+ will end up containing
% \verb+\glossword{1}{4}\glossword{2}{5}\glossword{3}{6}+.
%
% In fact, though, \verb+\zipper+ is not quite \verb+zipWith+. It also catches
% ``special'' or escaped tokens in its first argument and adds them to the output
% \emph{without} pairing them off or wrapping them in a \verb+\glossword+.
% \begin{macrocode}
\def\zipper#1\and#2\to#3{%
% \end{macrocode}
% If there's any items left on list \#1, pull one off (storing it in
% \verb+\ta+) and split off its first token so we can peek and see if it's an
% escape character or a special character.
% \begin{macrocode}
\ifx\empty#1\else%
\pop#1\to\ta%
\def\istchar{}\def\restchar{}%
\edef\temp{\the\ta}\split\temp%
% \end{macrocode}
% If that first token is an escape character, we pass the rest of the item through
% to the output.
% \begin{macrocode}
\ifx\istchar\glescape\expandafter\addtokens\restchars\to#3%
% \end{macrocode}
% If that first token is a special character, we convert it into a control sequence
% and make the remaining characters in the item into its argument.
% \begin{macrocode}
\else%
\expandafter\checkspecial\istchar\ifspecial%
\expandafter\addtokens\csname gl\istchar\endcsname\to#3%
\expandafter\addtokens\expandafter<\restchars>\to#3%
% \end{macrocode}
% If neither of those two conditions hold, then we're just building a normal
% glossword. That means we should also pull an item off of list \#2, storing it
% in \verb+\tb+.
% \begin{macrocode}
\else
\ifx\empty#2\else%
\pop#2\to\tb%
% \end{macrocode}
% Finally, we wrap the contents of \verb+\ta+ and \verb+\tb+ in a
% \verb+\glossword+ command and pass it to the output.
% Here we need to be careful: we want to expand \verb+\the\ta+ and \verb+\the\tb+
% \emph{once} --- to \emph{get} their contents. But having gotten their contents,
% we don't want to do any further expansion.\footnote{Why not? Because trying to
% expand an unexpandable macro here would be messy and unpleasant.}
% \begin{macrocode}
\edef\temp{\noexpand\glossword{\the\ta}{\the\tb}}%
\expandafter\addtokens\temp\to#3%
\fi%
\fi%
\fi%
\zipper#1\and#2\to#3%
\fi%
}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\gl}
% Based on \verb+\zipper+, we can define a user-friendly gloss command: take
% two arguments, \verb+\zipper+ them together, call \verb+\fixglstrut+ (see below)
% to make sure everything is spaced real nice, and
% send everything off to be typeset.
% \begin{macrocode}
\long\def\gl#1#2{%
\begingroup%
\def\x{#1 }\def\y{#2 }\def\z{}%
\zipper\x\and\y\to\z%
\fixglstrut%
\ifvmode\vskip\aboveglskip\fi\z%
\endgroup%
}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\fixglstrut}
%\begin{macro}{\noglstrut}
% The \verb+\fixglstrut+ command is issued in \verb+\gl+ right before we begin
% typesetting. It sets \verb+\glstrut+ to be as tall as a normal glossbox at
% the current font size \emph{plus} the current value of \verb+\betweenglskip+.
% Sometimes we'll also want to be able to suppress \verb+\glstrut+ temporarily
% as a way of preventing the \verb+\betweenglskip+ space from being inserted.
% \verb+\noglstrut+ does that. (It's temporary because \verb+\fixglstrut+ will
% be called again at the beginning of the next gloss and things will go back to
% normal. If you issue \verb+\noglstrut+ within a group, it's of course even
% temporary-er than that.)
% \begin{macrocode}
\def\fixglstrut{%
\def\glstrut{}%
\setbox0=\hbox{\glossword{}{}}%
\glstrutheight=\ht0%
\glstrutdepth=\dp0%
\advance\glstrutdepth by \betweenglskip%
\global\edef\glstrut{\vrule height\glstrutheight width0pt depth\glstrutdepth}}
\def\noglstrut{\def\glstrut{}}
% \end{macrocode}
%\end{macro}
%\end{macro}
%\begin{macro}{\ft}
% Usually after an interlinear gloss there's a line of ``free translation.''
% This is a user-facing command for setting that free translation line --- or,
% really, for setting \emph{anything} that needs to come on a new line right after
% an interlinear gloss. The only time this matters is when \verb+betweenglskip+
% and \verb+belowglskip+ are different sizes.
% \begin{macrocode}
\def\ft#1{\nobreak\par\nobreak\vskip-\betweenglskip\vskip\aboveglftskip #1}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\lb}
% Here's a labeling macro, swiped from the \TeX book.
% \begin{macrocode}
\def\lb#1{{\unskip\nobreak\hfil\penalty0\hskip2em\mbox{}\nobreak\hfill\mbox{#1}}}
% \end{macrocode}
%\end{macro}
%\subsection{Declaring shortcuts}
% We have a macro \verb+\makespecial+ which will tell the parser ``treat
% this character as special.''
%
% But that alone won't get us anywhere interesting. We also need to \emph{define}
% the macro that will be executed when the special character in question is
% encountered. And it would be nice if we could wrap both steps --- calling
% \verb+\makespecial+ and defining the macro --- in a user-friendly package.
% That's what this last section does.
%
% Suppose we want to declare {\tt /} as a shortcut character which inserts
% a line break. Step one is simple:
% \begin{center}
% \verb+\makespecial{/}+
% \end{center}
% Now let's consider how the parser will respond after we've done this.
% Suppose we then execute this command:
% \begin{center}
% \verb+\gl{a b * c}{1 2 3}+
% \end{center}
% The output which is sent to be typeset will look like this
% \begin{center}
% \verb+\glossword{a}{1}+\\
% \verb+\glossword{b}{2}+\\
% \verb+ \gl/<>+\\
% \verb+\glossword{c}{3}+\\
% \end{center}
% where \verb+\gl/+ is a control sequence --- one which could not normally be
% input directly. And if we execute the command
% \begin{center}
% \verb+\gl{a b /argument c}{1 2 3}+
% \end{center}
% The output which is sent to be typeset will look like this:
% \begin{center}
% \verb+\glossword{a}{1}+\\
% \verb+\glossword{b}{2}+\\
% \verb+ \gl/<argument>+\\
% \verb+\glossword{c}{3}+\\
% \end{center}
%
% Step two, then, is to define a macro that will do something useful in those
% contexts. If the slash were a normal character, this would be easy:
% \begin{center}
% \verb+\def\gl/<#1>{\par\ifx#1\empty\else\vskip{#1}\fi}+
% \end{center}
% But since the slash isn't a normal character, we need to do it this way instead:
% \begin{center}
% \verb+\expandafter\def\csname gl/\endcsname<#1>{\par\ifx#1\empty\else\vskip{#1}\fi}+
% \end{center}
% \begin{macro}{\makeglshortcut}
% Well, that's just what \verb+\makeglshortcut+ does: carries out Step One and
% Step Two for an arbitrary character and arbitrary macro code.
% \begin{macrocode}
\long\def\makeglshortcut#1#2{%
\makespecial{#1}%
\expandafter\gdef\csname gl#1\endcsname<##1>{#2}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{/}
% Here are a few examples of \verb+\makeglshortcut+ in action. To make the slash
% into a newline character, like we did in our example, the user-friendly way to
% do it is this:
% \begin{macrocode}
\makeglshortcut/{\par\ifx#1\empty\else\vskip{#1}\fi}
% \end{macrocode}
% \end{macro}
% \begin{macro}{[ ]}
% We declare that square brackets in the input will give square brackets in the output --- but with
% nice spacing, and an optional argument set as a subscript.
% \begin{macrocode}
\makeglshortcut[{[$_\textrm{\footnotesize#1}$\thinspace}
\makeglshortcut]{\unskip\thinspace]$_\textrm{\footnotesize#1}$\glspace}
% \end{macrocode}
% \end{macro}
%
% This is where it gets a little hairy. We also want to be able to set up
% shortcut characters that turn into the left- and right-hand sides of a
% \emph{delimited macro}. For instance, suppose we want to be able to use
% asterisks as shortcuts, such that everything in between
% two asterisks is put into a \verb+\framebox+. Well, step one is as easy
% as it was before.
%\begin{center}
%\verb+\makespecial{*}+
%\end{center}
% And if the asterisk were a normal character, step two would also be
% reasonably easy.
%\begin{center}
%\verb+\def\gl*<#1>#2\gl*<#3>{\framebox{#2}}+
%\end{center}
% \begin{macro}{makeglsurround}
% But as before, because the asterisk is not a normal
% character, we need to invoke \verb+\csname+. And this time, it's ugly:
% \begin{macrocode}
\long\def\makeglsurround#1#2#3{%
\xdef\dvglspecials{\dvglspecials#1#2}%
\ta=\expandafter{\csname gl#1\endcsname}%
\tb=\expandafter{\csname gl#2\endcsname}%
\expandafter\expandafter\expandafter\gdef%
\expandafter\expandafter\the\ta%
\expandafter<\expandafter##\expandafter1\expandafter>%
\expandafter##\expandafter2\the\tb<##3>{#3}}
% \end{macrocode}
% \end{macro}
%\begin{macro}{* *}
% Luckily, the user is protected from that ugliness. Here's a slightly more complicated
% version of that \verb+\framebox+-making macro, with elegant spacing and an optional
% argument set as a label on top of the frame. Note the use of \verb+\noglstrut+
% here to prevent extra space from ending up \emph{inside} the frame.
% \begin{macrocode}
\makeglsurround ** {%
\rlap{\raisebox{1.5em}{\footnotesize\sf#3}}%
\fbox{\noglstrut#2\unskip}\glspace}
% \end{macrocode}
% \end{macro}
% \Finale
|