core-con.mkiv /size: 33 Kb    last modification: 2020-07-01 14:35
1
%D \module
2
%D [ file=core-con,
3
%D version=1997.26.08,
4
%D title=\CONTEXT\ Core Macros,
5
%D subtitle=Conversion,
6
%D author=Hans Hagen,
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
\writestatus
{
loading
}{
ConTeXt
Core
Macros
/
Conversion
}
15 16
\registerctxluafile
{
core
-
con
}{}
17 18
% todo: iso date ranges (from/to)
19 20
\unprotect
21 22
\ifdefined
\currentlanguage
\else
\let
\currentlanguage
\empty
\fi
23
\ifdefined
\labeltext
\else
\let
\labeltext
\firstofoneargument
\fi
24 25
%D This module deals with all kind of conversions from numbers and dates. I
26
%D considered splitting this module in a support one and a core one, but to keep
27
%D things simple as well as preserve the overview, I decided against splitting.
28 29
\let
\spr
\firstofoneargument
% separator
30
\let
\stp
\firstofoneargument
% stopper
31 32
% needed for arab:
33 34
\unexpanded
\def
\isolateseparators
% even works with list separator overloading
35
{
\def
\spr
##
1
{{
##
1
}}
% % we can probably best mess around with zwj
36
\def
\stp
##
1
{{
##
1
}}}
% and friends
37 38
%D \macros
39
%D {numbers}
40
%D
41
%D First we deal with the dummy conversion of numbers using the \TEX\ primitive
42
%D \type{\number}. The uppercase alternative is only there for compatibility with
43
%D the other conversion macros. We could do without \type{#1} but this way we get
44
%D rid of unwanted braces. For the savety we also define a non||sence uppercase
45
%D alternative.
46
%D
47
%D \showsetup{numbers}
48
%D
49
%D \starttyping
50
%D \def\numbers#1{\number#1}
51
%D \def\Numbers#1{\number#1}
52
%D \stoptyping
53
%D
54
%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear,
55
%D unless we use:
56 57
\def
\numbers
#
1
{
\purenumber
{
#
1
}}
58
\def
\Numbers
#
1
{
\purenumber
{
#
1
}}
59 60
%D \macros
61
%D {romannumerals,Romannumerals}
62
%D
63
%D \TEX\ the program uses a rather tricky conversion from numbers to their roman
64
%D counterparts. This conversion could of course be programmed in \TEX\ itself, but
65
%D I guess Knuth found the programming trick worth presenting.
66
%D
67
%D \showsetup{romannumerals}
68
%D \showsetup{Romannumerals}
69 70
\def
\romannumerals
#
1
{
\clf_romannumerals
\numexpr
#
1
\relax
}
71
\def
\Romannumerals
#
1
{
\clf_Romannumerals
\numexpr
#
1
\relax
}
72 73
%D Arabic etc:
74 75
\def
\abjadnumerals
#
1
{
\clf_abjadnumerals
\numexpr
#
1
\relax
}
76
\def
\abjadnodotnumerals
#
1
{
\clf_abjadnodotnumerals
\numexpr
#
1
\relax
}
77
\def
\abjadnaivenumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
arabic
}}
% okay?
78 79
\def
\hebrewnumerals
#
1
{
\clf_hebrewnumerals
\numexpr
#
1
\relax
}
80
\let
\yiddishnumerals
\hebrewnumerals
81 82
\def
\languagecharacters
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
\currentlanguage
}}
% new
83
\def
\languageCharacters
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{
\currentlanguage
}}
% new
84 85
\def
\alphabeticnumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{}}
86
\def
\Alphabeticnumerals
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{}}
87 88
\def
\thainumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
thai
}}
89
\def
\devanagarinumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
devanagari
}}
90
\def
\gurmurkhinumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
gurmurkhi
}}
91
\def
\gujaratinumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
gujarati
}}
92
\def
\tibetannumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
tibetan
}}
93
\def
\greeknumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
greek
}}
94
\def
\Greeknumerals
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{
greek
}}
95
\def
\arabicnumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
arabic
}}
96
\def
\persiannumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
persian
}}
97
\def
\arabicdecimals
#
1
{
\clf_decimals
\numexpr
#
1
\relax
{
arabic
}}
98
\def
\persiandecimals
#
1
{
\clf_decimals
\numexpr
#
1
\relax
{
persian
}}
99 100
\let
\arabicexnumerals
\persiannumerals
101 102
\def
\koreannumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
korean
}}
103
\def
\koreannumeralsp
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
korean
-
parenthesis
}}
104
\def
\koreannumeralsc
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
korean
-
circle
}}
105 106
\let
\koreanparentnumerals
\koreannumeralsp
107
\let
\koreanparenthesisnumerals
\koreannumeralsp
108
\let
\koreancirclenumerals
\koreannumeralsc
109 110
\def
\chinesenumerals
#
1
{
\clf_chinesenumerals
\numexpr
#
1
\relax
{
normal
}}
111
\def
\chinesecapnumerals
#
1
{
\clf_chinesenumerals
\numexpr
#
1
\relax
{
cap
}}
112
\def
\chineseallnumerals
#
1
{
\clf_chinesenumerals
\numexpr
#
1
\relax
{
all
}}
113 114
%D \macros
115
%D {character,Character}
116
%D
117
%D Converting a number into a character can of course only be done with numbers
118
%D less or equal to~26. At the cost of much more macros a faster conversion is
119
%D possible, using:
120
%D
121
%D \starttyping
122
%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
123
%D \stoptyping
124
%D
125
%D But we prefer a simpel \type{\case}.
126
%D
127
%D \showsetup{character}
128
%D \showsetup{Character}
129 130
\def
\unknowncharacter
{
-
}
% else in lists \relax
131 132
\def
\character
#
1
{
\clf_character
\numexpr
#
1
\relax
}
133
\def
\Character
#
1
{
\clf_Character
\numexpr
#
1
\relax
}
134 135
%D \macros
136
%D {characters,Characters}
137
%D
138
%D Converting large numbers is supported by the next two macros. This time we
139
%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$.
140
%D
141
%D \showsetup{characters}
142
%D \showsetup{Characters}
143 144
\def
\characters
#
1
{
\clf_characters
\numexpr
#
1
\relax
}
145
\def
\Characters
#
1
{
\clf_Characters
\numexpr
#
1
\relax
}
146 147
%D \macros
148
%D {greeknumerals,Greeknumerals}
149
%D
150
%D Why should we only honour the romans, and not the greek?
151 152
% \let\greeknumerals\gobbleoneargument
153
% \let\Greeknumerals\gobbleoneargument
154 155
%D \macros
156
%D {oldstylenumerals,oldstyleromannumerals}
157
%D
158
%D These conversions are dedicated to Frans Goddijn.
159 160
\unexpanded
\def
\oldstylenumerals
#
1
%
161
{
\begingroup
162
\os
\number
#
1
%
163
\endgroup
}
164 165
\unexpanded
\def
\oldstyleromannumerals
#
1
% will become obsolete
166
{
\dontleavehmode
167
\hbox
\bgroup
168
\ss
\txx
169
\setbox
\scratchbox
\hbox
\s!spread
.
1
5
\emwidth
{
\hss
\uppercased
{
\romannumerals
{
#
1
}}
\hss
}
%
170
\scratchwidth
\wd
\scratchbox
171
\scratchheight
\ht
\scratchbox
172
\scratchdimen
.
1
\exheight
173
\vrule
\s!width
\scratchwidth
\s!height
\dimexpr
\scratchheight
+
\scratchdimen
\relax
\s!depth
-
\dimexpr
\scratchheight
-+
\scratchdimen
\relax
174
\hskip
-
\scratchwidth
175
\vrule
\s!width
\scratchwidth
\s!height
\scratchdimen
\s!depth
\scratchdimen
176
\hskip
-
\scratchwidth
177
\box
\scratchbox
178
\egroup
}
179 180
%D \macros
181
%D {protectconversion}
182
%D
183
%D The previous two commands are not robust enough to be passed to \type
184
%D {\write} en \type{\message}. That's why we introduce:
185 186
\unexpanded
\def
\protectconversion
187
{
\let
\doconvertcharacters
\firstofoneargument
}
188 189
%D \macros
190
%D {normaltime,normalyear,normalmonth,normalday}
191
%D
192
%D The last part of this module is dedicated to converting dates. Because we want to
193
%D use as meaningful commands as possible, and because \TEX\ already uses up some of
194
%D those, we save the original meanings.
195 196
% \savenormalmeaning\time
197
% \savenormalmeaning\year
198
% \savenormalmeaning\month
199
% \savenormalmeaning\day
200 201
%D \macros
202
%D {month,MONTH}
203
%D
204
%D Converting the month number into a month name is done using a case statement,
205
%D abstact values and the label mechanism. This way users can easily redefine a
206
%D label from for instance german into austrian.
207
%D
208
%D \starttyping
209
%D \setuplabeltext [de] [january=J\"anner]
210
%D \stoptyping
211
%D
212
%D Anyhow, the conversion looks like:
213 214
\unexpanded
\def
\monthlong
#
1
{
\clf_monthname
\numexpr
#
1
\relax
}
215
\unexpanded
\def
\monthshort
#
1
{
\clf_monthmnem
\numexpr
#
1
\relax
}
216
\unexpanded
\def
\daylong
#
1
{
\clf_dayname
\numexpr
#
1
\relax
}
217
\unexpanded
\def
\dayshort
#
1
{
\clf_daymnem
\numexpr
#
1
\relax
}
218 219
\let
\convertmonth\monthlong
% for old times sake
220 221
%D We redefine the \TEX\ primitive \type{\month} as:
222
%D
223
%D \showsetup{month}
224
%D \showsetup{MONTH}
225 226
\let\month
\monthlong
227 228
\unexpanded
\def
\MONTH
#
1
{
\WORD
{
\clf_monthname
\numexpr
#
1
\relax
}}
229
\unexpanded
\def
\MONTHLONG
#
1
{
\WORD
{
\clf_monthname
\numexpr
#
1
\relax
}}
230
\unexpanded
\def
\MONTHSHORT
#
1
{
\WORD
{
\clf_monthmnem
\numexpr
#
1
\relax
}}
231 232
%D We never explicitly needed this, but Tobias Burnus pointed out that it would be
233
%D handy to convert to the day of the week. In doing so, we have to calculate the
234
%D total number of days, taking leapyears into account. For those who are curious:
235
%D
236
%D \startitemize[packed]
237
%D \item years that can be divided by 4 are leapyears
238
%D \item exept years that can be divided by 100
239
%D \item unless years can be divided by 400
240
%D \stopitemize
241 242
%D \macros
243
%D {weekday,WEEKDAY}
244
%D
245
%D The first one is sort of redundant. It takes the day number argument.
246
%D
247
%D \showsetup{weekday}
248
%D \showsetup{WEEKDAY}
249 250
\unexpanded
\def
\weekday
#
1
{
\clf_dayname
\numexpr
#
1
\relax
}
251
\unexpanded
\def
\WEEKDAY
#
1
{
\WORD
{
\clf_dayname
\numexpr
#
1
\relax
}}
252
\unexpanded
\def
\DAYLONG
#
1
{
\WORD
{
\clf_dayname
\numexpr
#
1
\relax
}}
253
\unexpanded
\def
\DAYSHORT
#
1
{
\WORD
{
\clf_daymnem
\numexpr
#
1
\relax
}}
254 255
%D \macros
256
%D {getdayoftheweek, dayoftheweek}
257 258
\newcount
\normalweekday
259 260
\def
\dayoftheweek
#
1
#
2
#
3
{
\clf_weekdayname
\numexpr
#
1
\relax\numexpr
#
2
\relax\numexpr
#
3
\relax
}
% name
261
\unexpanded
\def
\getdayoftheweek
#
1
#
2
#
3
{
\normalweekday
\clf_weekday
\numexpr
#
1
\relax\numexpr
#
2
\relax\numexpr
#
3
\relax\relax
}
% number
262 263
%D Using this macro in
264
%D
265
%D \startbuffer
266
%D monday: \dayoftheweek {4} {5} {1992}
267
%D friday: \dayoftheweek {16} {6} {1995}
268
%D monday: \dayoftheweek {25} {8} {1997}
269
%D saturday: \dayoftheweek {30} {8} {1997}
270
%D tuesday: \dayoftheweek {2} {1} {1996}
271
%D tuesday: \dayoftheweek {7} {1} {1997}
272
%D tuesday: \dayoftheweek {13} {1} {1998}
273
%D friday: \dayoftheweek {1} {1} {2000}
274
%D \stopbuffer
275
%D
276
%D \typebuffer
277
%D
278
%D gives
279
%D
280
%D \startlines
281
%D \getbuffer
282
%D \stoplines
283
%D
284
%D The macro \type {\getdayoftheweek} can be used to calculate the number \type
285
%D {\normalweekday}.
286 287
%D \macros
288
%D {doifleapyearelse,
289
%D getdayspermonth}
290
%D
291
%D Sometimes we need to know if we're dealing with a leapyear, so here is a
292
%D testmacro:
293
%D
294
%D \starttyping
295
%D \doifleapyearelse{year}{yes}{no}
296
%D \stoptyping
297
%D
298
%D An example of its use can be seen in the macro
299
%D
300
%D \starttyping
301
%D \getdayspermonth{year}{month}
302
%D \stoptyping
303
%D
304
%D The number of days is available in the macro \type {\numberofdays}.
305 306
\def
\doifelseleapyear
#
1
% expandable check
307
{
\clf_doifelseleapyear
\numexpr
#
1
\relax
}
308 309
\let
\doifleapyearelse\doifelseleapyear
310 311
\unexpanded
\def
\getdayspermonth
#
1
#
2
%
312
{
\edef
\numberofdays
{
\clf_nofdays
\numexpr
#
1
\relax\numexpr
#
2
\relax
}}
313 314
\def
\dayspermonth
#
1
#
2
%
315
{
\clf_nofdays
\numexpr
#
1
\relax\numexpr
#
2
\relax
}
316 317
% \dayoftheweek{2006}{9}{15}
318
% \doifleapyearelse{2000}{OK}{NOT OK}
319
% \doifleapyearelse{2100}{NOT OK}{OK}
320
% \doifleapyearelse{2004}{OK}{NOT OK}
321
% \doifleapyearelse{2003}{NOT OK}{OK}
322
% \dayspermonth{2000}{2}
323
% [\the\normaltime=\the\time]
324 325
%D \macros
326
%D {currentdate, rawdate, date}
327
%D
328
%D We use these conversion macros in the date formatting macro:
329
%D
330
%D \showsetup{currentdate}
331
%D
332
%D This macro takes care of proper spacing and delivers for instance:
333
%D
334
%D \startbuffer
335
%D \currentdate[weekday,day,month,year]
336
%D \currentdate[WEEKDAY,day,MONTH,year]
337
%D \stopbuffer
338
%D
339
%D \startlines
340
%D \getbuffer
341
%D \stoplines
342
%D
343
%D depending of course on the keywords. Here we gave:
344
%D
345
%D \typebuffer
346
%D
347
%D If needed one can also add non||keywords, like in
348
%D
349
%D \startbuffer
350
%D \currentdate[dd,--,mm,--,yy]
351
%D \stopbuffer
352
%D
353
%D \typebuffer
354
%D
355
%D or typeset: \getbuffer.
356
%D
357
%D When no argument is passed, the current date is given as specified per
358
%D language (using \type{\installlanguage}).
359
%D
360
%D \showsetup{currentdate}
361
%D
362
%D \startbuffer
363
%D \date
364
%D \date[d=12,m=12,y=1998][weekday]
365
%D \date[d=12,m=12,y=1998]
366
%D \stopbuffer
367
%D
368
%D We can also typeset arbitrary dates, using the previous
369
%D command.
370
%D
371
%D \typebuffer
372
%D
373
%D The date is specified by one character keys. When no date is given, we get the
374
%D current date.
375
%D
376
%D \startlines
377
%D \getbuffer
378
%D \stoplines
379 380
%D \starttabulate[|l|l|]
381
%D \HL
382
%D \NC year \NC (\currentdate[year]) \NC\NR
383
%D \NC yy \NC (\currentdate[yy]) \NC\NR
384
%D \NC y \NC (\currentdate[y]) \NC\NR
385
%D \NC Y \NC (\currentdate[Y]) \NC\NR
386
%D \HL
387
%D \NC month \NC (\currentdate[month]) \NC\NR
388
%D \NC mm \NC (\currentdate[mm]) \NC\NR
389
%D \NC m \NC (\currentdate[m]) \NC\NR
390
%D \NC M \NC (\currentdate[M]) \NC\NR
391
%D \HL
392
%D \NC day \NC (\currentdate[day]) \NC\NR
393
%D \NC dd \NC (\currentdate[dd]) \NC\NR
394
%D \NC d \NC (\currentdate[d]) \NC\NR
395
%D \NC D \NC (\currentdate[D]) \NC\NR
396
%D \HL
397
%D \NC weekday \NC (\currentdate[weekday]) \NC\NR
398
%D \NC w \NC (\currentdate[w]) \NC\NR
399
%D \NC W \NC (\currentdate[W]) \NC\NR
400
%D \HL
401
%D \NC referral \NC (\currentdate[referral]) \NC\NR
402
%D \HL
403
%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR
404
%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR
405
%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR
406
%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR
407
%D \HL
408
%D \stoptabulate
409
%D
410
%D \startbuffer
411
%D (\currentdate[D,.,M,.,Y])
412
%D (\currentdate[day,month,year])
413
%D (\currentdate[day,+,month,+,year])
414
%D \stopbuffer
415
%D
416
%D \typebuffer \getbuffer
417
%D
418
%D Some indirectness and abstraction:
419
%D
420
%D \starttyping
421
%D \definedate[crap][year]
422
%D \currentdate[crap]
423
%D \stoptyping
424 425
\installcorenamespace
{
date
}
426 427
\unexpanded
\def
\definedate
428
{
\dodoubleargument
\syst_converters_define_date
}
429 430
\def
\syst_converters_define_date
[#
1
][#
2
]
%
431
{
\setvalue
{
\??date
#
1
}{
#
2
}}
432 433
\def
\syst_converters_check_date_specification
#
1
%
434
{
\ifcsname
\??date
#
1
\endcsname
435
\edef
#
1
{
\lastnamedcs
}
%
436
\fi
}
437 438
\newtoks
\everycurrentdate
439 440
\unexpanded
\def
\currentdate
441
{
\dosingleempty
\syst_converters_current_date
}
442 443
\def
\syst_converters_current_date
[#
1
]
%
444
{
\dontleavehmode
445
\begingroup
446
\the
\everycurrentdate
447
\edef
\forceddatespecification
{
#
1
}
%
448
\syst_converters_check_date_specification
\forceddatespecification
449
\syst_converters_check_date_specification
\currentdatespecification
450
\clf_currentdate
451
{
\forceddatespecification
}{
\currentdatespecification
}{
\labellanguage
}
%
452
\normalyear\normalmonth\normalday
453
\endgroup
}
454 455
\unexpanded
\def
\date
456
{
\dodoubleempty
\syst_converters_date
}
457 458
\def
\syst_converters_date
[#
1
][#
2
]
% sets the date !
459
{
\dontleavehmode
460
\iffirstargument
461
\begingroup
462
\letdummyparameter
\c!d
\normalday
463
\letdummyparameter
\c!m
\normalmonth
464
\letdummyparameter
\c!y
\normalyear
465
\getdummyparameters
[#
1
]
%
466
\normalexpanded
467
{
\endgroup
468
\normalday
\number
\directdummyparameter
\c!d
\relax
469
\normalmonth\number
\directdummyparameter
\c!m
\relax
470
\normalyear
\number
\directdummyparameter
\c!y
\relax
}
%
471
\fi
472
\begingroup
473
\the
\everycurrentdate
474
\edef
\forceddatespecification
{
#
2
}
%
475
\syst_converters_check_date_specification
\forceddatespecification
476
\syst_converters_check_date_specification
\currentdatespecification
477
\clf_currentdate
478
{
\forceddatespecification
}{
\currentdatespecification
}{
\labellanguage
}
%
479
\normalyear\normalmonth\normalday
480
\endgroup
}
481 482
\def
\rawdate
[#
1
]
% expandable and no labels
483
{
\clf_currentdate
484
{
#
1
}{
\currentdatespecification
}{}
%
485
\normalyear\normalmonth\normalday
}
486 487
%D \macros
488
%D {currenttime}
489
%D
490
%D The currenttime is actually the jobtime. You can specify a pattern similar
491
%D to the previous date macro using the keys \type {h}, \type {m} and a separator.
492 493
\unexpanded
\def
\calculatecurrenttime
494
{
\edef
\currenthour
{
\clf_hour
}
%
495
\edef
\currentminute
{
\clf_minute
}
%
496
\edef
\currentsecond
{
\clf_second
}}
497 498
\let
\currenthour
\!!plusone
499
\let
\currentminute
\!!plusone
500
\let
\currentsecond
\!!plusone
501 502
% \def\currenttimespecification{h,:,m}
503 504
\unexpanded
\def
\currenttime
505
{
\doifelsenextoptional
\syst_converters_current_time_yes
\syst_converters_current_time_nop
}
506 507
\unexpanded
\def
\syst_converters_current_time_yes
[#
1
]
%
508
{
\calculatecurrenttime
509
\processallactionsinset
[#
1
][
h
=>
\currenthour
,
m
=>
\currentminute
,
\s!unknown
=>
\commalistelement
]
}
510 511
\unexpanded
\def
\syst_converters_current_time_nop
512
{
\normalexpanded
{
\syst_converters_current_time_yes
[
\currenttimespecification
]
}}
513 514
%D Because we're dealing with dates, we also introduce a few day loops:
515
%D
516
%D \starttyping
517
%D \processmonth{year}{month}{command}
518
%D \processyear{year}{command}{before}{after}
519
%D \stoptyping
520
%D
521
%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday}
522
%D can be used for for date manipulations.
523 524
\unexpanded
\def
\processmonth
#
1
#
2
#
3
% year month command
525
{
\begingroup
526
\getdayspermonth
{
#
1
}{
#
2
}
%
527
\dostepwiserecurse
\plusone
\numberofdays
\plusone
528
{
\normalyear
#
1
\relax
529
\normalmonth
#
2
\relax
530
\normalday
\recurselevel
\relax
531
#
3
}
%
532
\endgroup
}
533 534
\def
\lastmonth
{
1
2
}
% can be set to e.g. 1 when testing
535 536
\unexpanded
\def
\processyear
#
1
#
2
#
3
#
4
% year command before after
537
{
\begingroup
538
\dorecurse
\lastmonth
539
{
\normalyear
#
1
\relax
540
\normalmonth
\recurselevel
\relax
541
#
3
\processmonth
\normalyear\normalmonth
{
#
2
}
#
4
}
%
542
\endgroup
}
543 544
%D \macros
545
%D {defineconversion, convertnumber}
546
%D
547
%D Conversion involves the macros that we implemented earlier in this module.
548
%D
549
%D \showsetup{defineconversion}
550
%D \showsetup{convertnumber}
551
%D
552
%D We can feed this command with conversion macros as well as a set of conversion
553
%D symbols. Both need a bit different treatment.
554
%D
555
%D \starttyping
556
%D \defineconversion [roman] [\romannumerals]
557
%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
558
%D \stoptyping
559
%D
560
%D You can define a language dependent conversion with:
561
%D
562
%D \starttyping
563
%D \defineconversion [en] [whatever] [\something]
564
%D \stoptyping
565 566
\installcorenamespace
{
conversion
}
567
\installcorenamespace
{
conversionarguments
}
568
\installcorenamespace
{
conversionwords
}
569 570
%D It might be better to move more to \LUA\ as we also need conversion there and
571
%D doublicating logic doesn't make things cleaner. It means that all conversions
572
%D will get a language argument too. However, we permit definitions at the \TEX\ end
573
%D so we have to provide some hybrid method.
574 575
% checkedconversion(method,n,language)
576 577
\unexpanded
\def
\defineconversion
578
{
\dotripleempty
\syst_converters_define_conversion
}
579 580
\def
\syst_converters_define_conversion
[#
1
][#
2
][#
3
]
% from now on global (maybe local again some day)
581
{
\ifthirdargument
582
\syst_converters_define_conversion_indeed
{
#
1
#
2
}{
#
1
:
#
2
}{
#
3
}
%
583
\else
584
\syst_converters_define_conversion_indeed
{
#
1
}{
#
1
}{
#
2
}
%
585
\fi
}
586 587
\def
\syst_converters_define_conversion_indeed
#
1
#
2
#
3
%
588
{
\doifelseinstring
{
,
}{
\detokenize
{
#
3
}}
589
{
\clf_defineconversion
{
#
2
}{
\detokenize
{
#
3
}}
% a set e.g. of symbols
590
\setgvalue
{
\??conversion
#
1
}{
\syst_converters_checked_conversion
{
#
2
}}}
591
{
\setgvalue
{
\??conversion
#
1
}{
#
3
}}}
592 593
\def
\syst_converters_checked_conversion
#
1
#
2
%
594
{
\clf_checkedconversion
{
#
1
}
\numexpr
#
2
\relax
}
595 596
%D If a conversion is just a font switch then we need to make sure that the number
597
%D is indeed ends up as number in the input, so we need to handle the second
598
%D argument.
599 600
\def
\convertnumber
#
1
#
2
% expandable
601
{
\csname
\??conversionarguments
602
\ifcsname
\??conversion
\currentlanguage
#
1
\endcsname
1
\else
603
\ifcsname
\??conversion
#
1
\endcsname
2
\else
604
3
\fi\fi
605
\endcsname
{
#
1
}{
\number
#
2
}}
606 607
\unexpanded
\def
\uconvertnumber
% unexpandable
608
{
\convertnumber
}
609 610
\setvalue
{
\??conversionarguments
1
}
#
1
{
\csname
\??conversion
\currentlanguage
#
1
\endcsname
}
611
\setvalue
{
\??conversionarguments
2
}
#
1
{
\csname
\??conversion
#
1
\endcsname
}
612
\letvalue
{
\??conversionarguments
3
}
\syst_converters_checked_conversion
613 614
% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check
615
% if we have definitions that are not matched at the lua end .. eventually we might do
616
% that when more shows up
617 618
\def
\doifelseconversiondefined
#
1
% expandable
619
{
\ifcsname
\??conversion
\currentlanguage
#
1
\endcsname
620
\expandafter
\firstoftwoarguments
621
\else\ifcsname
\??conversion
#
1
\endcsname
622
\doubleexpandafter\firstoftwoarguments
623
\else
624
\doubleexpandafter\secondoftwoarguments
625
\fi\fi
}
626 627
\def
\doifelseconversionnumber
#
1
#
2
% expandable
628
{
\ifnum
#
2
>
\numexpr
\clf_nofconversions
{
#
1
}
\relax
629
\expandafter
\secondoftwoarguments
630
\else
631
\expandafter
\firstoftwoarguments
632
\fi
}
633 634
\let
\doifconversiondefinedelse\doifelseconversiondefined
635
\let
\doifconversionnumberelse
\doifelseconversionnumber
636 637
%D Handy.
638 639
\setvalue
{
\??conversionwords\v!one
}{
1
}
640
\setvalue
{
\??conversionwords\v!two
}{
2
}
641
\setvalue
{
\??conversionwords\v!three
}{
3
}
642
\setvalue
{
\??conversionwords\v!four
}{
4
}
643
\setvalue
{
\??conversionwords\v!five
}{
5
}
644 645
%def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
646
\def
\wordtonumber
#
1
#
2
{
\ifcsname
\??conversionwords
#
1
\endcsname\lastnamedcs\else
#
2
\fi
}
647 648
% \defineconversion[ctx][c,o,n,t,e,x,t]
649
%
650
% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
651 652
%D \macros
653
%D {ordinalnumber, highordinalstr, ordinalstr}
654
%D
655
%D Efficient general ordinal number converters are sometimes difficult to
656
%D implement. Fortunately dates never exceed the number~31.
657 658
\def
\highordinalstr
#
1
{
\high
{
\notsmallcapped
{
#
1
}}}
659
\def
\ordinalstr
#
1
{
\notsmallcapped
{
#
1
}}
660
\def
\ordinalnumber
#
1
{
\clf_ordinal
\numexpr
#
1
\relax
{
\currentlanguage
}}
661
\def
\Ordinalnumber
#
1
{
\Words
{
\clf_ordinal
\numexpr
#
1
\relax
{
\currentlanguage
}}}
662 663
\def
\verbosenumber
#
1
{
\clf_verbose
\numexpr
#
1
\relax
{
\currentlanguage
}}
664
\def
\VerboseNumber
#
1
{
\Words
{
\clf_verbose
\numexpr
#
1
\relax
{
\currentlanguage
}}}
665 666
%D As longs as symbols are linked to levels or numbers, we can also use the
667
%D conversion mechanism, but in for instance the itemization macros, we prefer
668
%D symbols because they can more easier be (partially) redefined. Symbols are
669
%D implemented in another module.
670 671
\def
\smallcappedromannumerals
#
1
{
\smallcapped
{
\romannumerals
{
#
1
}}}
672
\def
\smallcappedcharacters
#
1
{
\smallcapped
{
\characters
{
#
1
}}}
673 674
\defineconversion
[]
[
\numbers
]
% the default conversion
675
\defineconversion
[
\v!empty
]
[
\gobbleoneargument
]
676
\defineconversion
[
\v!none
]
[
\numbers
]
677
\defineconversion
[
\s!default
]
[
\numbers
]
678 679
\defineconversion
[
month
]
[
\monthlong
]
680
\defineconversion
[
month
:
mnem
]
[
\monthshort
]
681 682
\defineconversion
[
\v!character
]
[
\character
]
683
\defineconversion
[
\v!Character
]
[
\Character
]
684 685
\defineconversion
[
\v!characters
]
[
\characters
]
686
\defineconversion
[
\v!Characters
]
[
\Characters
]
687 688
\defineconversion
[
a
]
[
\alphabeticnumerals
]
689
\defineconversion
[
A
]
[
\Alphabeticnumerals
]
690
\defineconversion
[
AK
]
[
\smallcappedcharacters
]
691
\defineconversion
[
KA
]
[
\smallcappedcharacters
]
692 693
\defineconversion
[
\v!alphabetic
]
[
\alphabeticnumerals
]
694
\defineconversion
[
\v!Alphabetic
]
[
\Alphabeticnumerals
]
695 696
\defineconversion
[
\v!number
]
[
\numbers
]
697
\defineconversion
[
\v!numbers
]
[
\numbers
]
698
\defineconversion
[
\v!Numbers
]
[
\Numbers
]
699
\defineconversion
[
\v!mediaeval
]
[
\mediaeval
]
700 701
\defineconversion
[
\v!word
]
[
\verbosenumber
]
702
\defineconversion
[
\v!words
]
[
\verbosenumber
]
703 704
\defineconversion
[
\v!Word
]
[
\VerboseNumber
]
705
\defineconversion
[
\v!Words
]
[
\VerboseNumber
]
706 707
\defineconversion
[
\v!ordinal
]
[
\ordinalnumber
]
708
\defineconversion
[
\v!Ordinal
]
[
\Ordinalnumber
]
709 710
\defineconversion
[
n
]
[
\numbers
]
711
\defineconversion
[
N
]
[
\Numbers
]
712
\defineconversion
[
m
]
[
\mediaeval
]
713
\defineconversion
[
o
]
[
\oldstylenumerals
]
714
\defineconversion
[
O
]
[
\oldstylenumerals
]
715
\defineconversion
[
or
]
[
\oldstyleromannumerals
]
716 717
\defineconversion
[
\v!romannumerals
]
[
\romannumerals
]
718
\defineconversion
[
\v!Romannumerals
]
[
\Romannumerals
]
719 720
\defineconversion
[
i
]
[
\romannumerals
]
721
\defineconversion
[
I
]
[
\Romannumerals
]
722
\defineconversion
[
r
]
[
\romannumerals
]
723
\defineconversion
[
R
]
[
\Romannumerals
]
724 725
\defineconversion
[
KR
]
[
\smallcappedromannumerals
]
726
\defineconversion
[
RK
]
[
\smallcappedromannumerals
]
727 728
\defineconversion
[
\v!greek
]
[
\greeknumerals
]
729
\defineconversion
[
\v!Greek
]
[
\Greeknumerals
]
730 731
\defineconversion
[
g
]
[
\greeknumerals
]
732
\defineconversion
[
G
]
[
\Greeknumerals
]
733 734
%defineconversion [ñ] [\spanishnumerals]
735
%defineconversion [Ñ] [\Spanishnumerals]
736 737
\defineconversion
[
abjadnumerals
]
[
\abjadnumerals
]
738
\defineconversion
[
abjadnodotnumerals
]
[
\abjadnodotnumerals
]
739
\defineconversion
[
abjadnaivenumerals
]
[
\abjadnaivenumerals
]
740 741
\defineconversion
[
hebrewnumerals
]
[
\hebrewnumerals
]
742
\defineconversion
[
yiddishnumerals
]
[
\yiddishnumerals
]
743 744
% users can do: \defineconversion [he] [\hebrewnumerals]
745
% users can do: \defineconversion [yi] [\hebrewnumerals]
746 747
\defineconversion
[
thainumerals
]
[
\thainumerals
]
748
\defineconversion
[
devanagarinumerals
]
[
\devanagarinumerals
]
749
\defineconversion
[
gurmurkhinumerals
]
[
\gurmurkhinumerals
]
750
\defineconversion
[
gujaratinumerals
]
[
\gujaratinumerals
]
751
\defineconversion
[
tibetannumerals
]
[
\tibetannumerals
]
752
\defineconversion
[
greeknumerals
]
[
\greeknumerals
]
753
\defineconversion
[
Greeknumerals
]
[
\Greeknumerals
]
754
\defineconversion
[
arabicnumerals
]
[
\arabicnumerals
]
755
\defineconversion
[
persiannumerals
]
[
\persiannumerals
]
756
\defineconversion
[
arabicexnumerals
]
[
\arabicexnumerals
]
757
\defineconversion
[
arabicdecimals
]
[
\arabicdecimals
]
758
\defineconversion
[
persiandecimals
]
[
\persiandecimals
]
759 760
\defineconversion
[
koreannumerals
]
[
\koreannumerals
]
761
\defineconversion
[
koreanparennumerals
]
[
\koreanparenthesisnumerals
]
% for old times sake (for a while)
762
\defineconversion
[
koreanparenthesisnumerals
]
763
[
\koreanparenthesisnumerals
]
764
\defineconversion
[
koreancirclenumerals
]
[
\koreancirclenumerals
]
765 766
\defineconversion
[
kr
]
[
\koreannumerals
]
767
\defineconversion
[
kr
-
p
]
[
\koreanparentnumerals
]
768
\defineconversion
[
kr
-
c
]
[
\koreancirclenumerals
]
769 770
\defineconversion
[
chinesenumerals
]
[
\chinesenumerals
]
771
\defineconversion
[
chinesecapnumerals
]
[
\chinesecapnumerals
]
772
\defineconversion
[
chineseallnumerals
]
[
\chineseallnumerals
]
773 774
\defineconversion
[
cn
]
[
\chinesenumerals
]
775
\defineconversion
[
cn
-
c
]
[
\chinesecapnumerals
]
776
\defineconversion
[
cn
-
a
]
[
\chineseallnumerals
]
777 778
%D Moved from lang-def.mkiv:
779
%D
780
%D Define these as the general character enumeration when language is Slovenian. If
781
%D you feel uncomfortable with this, mail Mojca, since she promised to to take the
782
%D heat. Pablo was next to request this. We changed characters to numerals for this
783
%D feature. We do need these definitions for mechanisms like itemize that check
784
%D for converters.
785 786
\def
\sloveniannumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
sl
}}
787
\def
\slovenianNumerals
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{
sl
}}
788 789
\def
\spanishnumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
es
}}
790
\def
\spanishNumerals
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{
es
}}
791 792
\def
\russiannumerals
#
1
{
\clf_alphabetic
\numexpr
#
1
\relax
{
ru
}}
793
\def
\russianNumerals
#
1
{
\clf_Alphabetic
\numexpr
#
1
\relax
{
ru
}}
794 795
%defineconversion [\s!sl] [character] [\sloveniannumerals]
796
%defineconversion [\s!sl] [Character] [\slovenianNumerals]
797
%defineconversion [\s!sl] [characters] [\sloveniannumerals]
798
%defineconversion [\s!sl] [Characters] [\slovenianNumerals]
799 800
\defineconversion
[
\s!sl
]
[
alphabetic
]
[
\sloveniannumerals
]
801
\defineconversion
[
\s!sl
]
[
Alphabetic
]
[
\slovenianNumerals
]
802 803
\defineconversion
[
\s!sl
]
[
a
]
[
\sloveniannumerals
]
804
\defineconversion
[
\s!sl
]
[
A
]
[
\slovenianNumerals
]
805
\defineconversion
[
\s!sl
]
[
AK
]
[
\smallcapped
\sloveniannumerals
]
806
\defineconversion
[
\s!sl
]
[
KA
]
[
\smallcapped
\sloveniannumerals
]
807 808
%defineconversion [\s!es] [character] [\spanishnumerals]
809
%defineconversion [\s!es] [Character] [\spanishNumerals]
810
%defineconversion [\s!es] [characters] [\spanishnumerals]
811
%defineconversion [\s!es] [Characters] [\spanishNumerals]
812 813
\defineconversion
[
\s!es
]
[
alphabetic
]
[
\spanishnumerals
]
814
\defineconversion
[
\s!es
]
[
Alphabetic
]
[
\spanishNumerals
]
815 816
\defineconversion
[
\s!es
]
[
a
]
[
\spanishnumerals
]
817
\defineconversion
[
\s!es
]
[
A
]
[
\spanishNumerals
]
818
\defineconversion
[
\s!es
]
[
AK
]
[
\smallcapped
\spanishnumerals
]
819
\defineconversion
[
\s!es
]
[
KA
]
[
\smallcapped
\spanishnumerals
]
820 821
%defineconversion [\s!ru] [character] [\russiannumerals]
822
%defineconversion [\s!ru] [Character] [\russianNumerals]
823
%defineconversion [\s!ru] [characters] [\russiannumerals]
824
%defineconversion [\s!ru] [Characters] [\russianNumerals]
825 826
\defineconversion
[
\s!ru
]
[
alphabetic
]
[
\russiannumerals
]
827
\defineconversion
[
\s!ru
]
[
Alphabetic
]
[
\russianNumerals
]
828 829
\defineconversion
[
\s!ru
]
[
a
]
[
\russiannumerals
]
830
\defineconversion
[
\s!ru
]
[
A
]
[
\russianNumerals
]
831
\defineconversion
[
\s!ru
]
[
AK
]
[
\smallcapped
\russiannumerals
]
832
\defineconversion
[
\s!ru
]
[
KA
]
[
\smallcapped
\russiannumerals
]
833 834
\defineconversion
[
sloveniannumerals
]
[
\sloveniannumerals
]
835
\defineconversion
[
slovenianNumerals
]
[
\slovenianNumerals
]
836 837
\defineconversion
[
spanishnumerals
]
[
\spanishnumerals
]
838
\defineconversion
[
spanishNumerals
]
[
\spanishNumerals
]
839 840
\defineconversion
[
russiannumerals
]
[
\russiannumerals
]
841
\defineconversion
[
russianNumerals
]
[
\russianNumerals
]
842 843
%D In case a font has no greek (WS):
844 845
\defineconversion
[
mathgreek
]
846
[
\m
{
α
}
,
\m
{
β
}
,
\m
{
γ
}
,
\m
{
δ
}
,
\m
{
ε
}
,
\m
{
ζ
}
,
847
\m
{
η
}
,
\m
{
θ
}
,
\m
{
ι
}
,
\m
{
κ
}
,
\m
{
λ
}
,
\m
{
μ
}
,
848
\m
{
ν
}
,
\m
{
ξ
}
,
\m
{
ο
}
,
\m
{
π
}
,
\m
{
ρ
}
,
\m
{
σ
}
,
849
\m
{
τ
}
,
\m
{
υ
}
,
\m
{
φ
}
,
\m
{
χ
}
,
\m
{
ψ
}
,
\m
{
ω
}
]
850 851
%D Handy too (expanded!):
852 853
\def
\unihex
#
1
{
\clf_unihex
\numexpr
#
1
\relax
}
854 855
%D Symbol sets:
856 857
\ifdefined
\symbol
\else
\def
\symbol
[#
1
]
{
#
1
}
\fi
% todo
858 859
% \defineconversion
860
% [set 0]
861
% [{\symbol[bullet]},
862
% {\symbol[dash]},
863
% {\symbol[star]},
864
% {\symbol[triangle]},
865
% {\symbol[circle]},
866
% {\symbol[medcircle]},
867
% {\symbol[bigcircle]},
868
% {\symbol[square]},
869
% {\symbol[checkmark]}]
870 871
% \defineconversion
872
% [set 1]
873
% [\mathematics{\star},
874
% \mathematics{\star\star},
875
% \mathematics{\star\star\star},
876
% \mathematics{\ddagger},
877
% \mathematics{\ddagger\ddagger},
878
% \mathematics{\ddagger\ddagger\ddagger},
879
% \mathematics{\ast},
880
% \mathematics{\ast\ast},
881
% \mathematics{\ast\ast\ast}]
882
%
883
% \defineconversion
884
% [set 2]
885
% [\mathematics{\ast},
886
% \mathematics{\dag},
887
% \mathematics{\ddag},
888
% \mathematics{\ast\ast},
889
% \mathematics{\dag\dag},
890
% \mathematics{\ddag\ddag},
891
% \mathematics{\ast\ast\ast},
892
% \mathematics{\dag\dag\dag},
893
% \mathematics{\ddag\ddag\ddag},
894
% \mathematics{\ast\ast\ast\ast},
895
% \mathematics{\dag\dag\dag\dag},
896
% \mathematics{\ddag\ddag\ddag\ddag}]
897
%
898
% \defineconversion
899
% [set 3]
900
% [\mathematics{\star},
901
% \mathematics{\star\star},
902
% \mathematics{\star\star\star},
903
% \mathematics{\ddagger},
904
% \mathematics{\ddagger\ddagger},
905
% \mathematics{\ddagger\ddagger\ddagger},
906
% \mathematics{\P},
907
% \mathematics{\P\P},
908
% \mathematics{\P\P\P},
909
% \mathematics{\S},
910
% \mathematics{\S\S},
911
% \mathematics{\S\S\S},
912
% \mathematics{\ast},
913
% \mathematics{\ast\ast},
914
% \mathematics{\ast\ast\ast}]
915 916
\defineconversion
917
[
set
0
]
918
[
\symbol
{
bullet
}
,
919
\symbol
{
dash
}
,
920
\symbol
{
star
}
,
921
\symbol
{
triangle
}
,
922
\symbol
{
circle
}
,
923
\symbol
{
medcircle
}
,
924
\symbol
{
bigcircle
}
,
925
\symbol
{
square
}
,
926
\symbol
{
checkmark
}
]
927 928
\defineconversion
929
[
set
1
]
930
[
\textormathchars
{
}
,
931
\textormathchars
{
⋆⋆
}
,
932
\textormathchars
{
⋆⋆⋆
}
,
933
\textormathchars
{
}
,
934
\textormathchars
{
‡‡
}
,
935
\textormathchars
{
‡‡‡
}
,
936
\textormathchars
{
}
,
937
\textormathchars
{
∗∗
}
,
938
\textormathchars
{
∗∗∗
}
]
939 940
\defineconversion
941
[
set
2
]
942
[
\textormathchars
{
}
,
943
\textormathchars
{
}
,
944
\textormathchars
{
}
,
945
\textormathchars
{
∗∗
}
,
946
\textormathchars
{
††
}
,
947
\textormathchars
{
‡‡
}
,
948
\textormathchars
{
∗∗∗
}
,
949
\textormathchars
{
†††
}
,
950
\textormathchars
{
‡‡‡
}
,
951
\textormathchars
{
∗∗∗∗
}
,
952
\textormathchars
{
††††
}
,
953
\textormathchars
{
‡‡‡‡
}
]
954 955
\defineconversion
956
[
set
3
]
957
[
\textormathchars
{
}
,
958
\textormathchars
{
⋆⋆
}
,
959
\textormathchars
{
⋆⋆⋆
}
,
960
\textormathchars
{
}
,
961
\textormathchars
{
‡‡
}
,
962
\textormathchars
{
‡‡‡
}
,
963
\textormathchars
{
}
,
964
\textormathchars
{
¶¶
}
,
965
\textormathchars
{
¶¶¶
}
,
966
\textormathchars
{
§
}
,
967
\textormathchars
{
§§
}
,
968
\textormathchars
{
§§§
}
,
969
\textormathchars
{
}
,
970
\textormathchars
{
∗∗
}
,
971
\textormathchars
{
∗∗∗
}
]
972 973
%D Iteration of suggestion by WS on mailinglist 2010.12.22:
974
%D
975
%D \starttyping
976
%D \setupfloatsplitting[conversion=continued]
977
%D \stoptyping
978 979
\unexpanded
\def
\continuednumber
#
1
%
980
{
\labeltext
{
\ifcase
#
1
\or\else
\v!continued
\fi
}}
981 982
\defineconversion
983
[
\v!continued
]
984
[
\continuednumber
]
985 986
%D Taken from x-asciimath (see digits-001.tex for an example):
987 988
\let
\spaceddigitsmethod
\empty
% alternative methods : 1 default, 2 and 3 only when > 4
989
\let
\spaceddigitssymbol
\empty
% extra splitter symbol : {,}
990
\let
\spaceddigitsseparator
\empty
% separator symbol : {\Uchar{"2008}}
991 992
\unexpanded
\def
\spaceddigits
#
1
%
993
{
\clf_spaceddigits
994
method
{
\spaceddigitsmethod
}
%
995
symbol
{
\spaceddigitssymbol
}
%
996
separator
{
\spaceddigitsseparator
}
%
997
data
{
#
1
}
%
998
\relax
}
999 1000
%D For those who sart counting at zero:
1001
%D
1002
%D \starttyping
1003
%D \defineconversionset [zero] [n,zero] [n]
1004
%D
1005
%D \setuphead [sectionconversionset=zero]
1006
%D
1007
%D \starttext
1008
%D \startchapter [title=Introduction]
1009
%D \startsection [title=First topic] \stopsection
1010
%D \startsection [title=Second topic] \stopsection
1011
%D \stopchapter
1012
%D \stoptext
1013
%D \stoptyping
1014 1015
\def
\zeronumberconversion
#
1
{
\number\numexpr
#
1
-
\plusone
\relax
}
1016 1017
\defineconversion
[
zero
]
[
\zeronumberconversion
]
1018 1019
\protect
\endinput
1020