1if not modules then modules = { } end modules ['core-con'] = {
2 version = 1.001,
3 comment = "companion to core-con.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
18
19local floor = math.floor
20local osdate, ostime, ostimezone = os.date, os.time, os.timezone
21local concat, insert, reverse = table.concat, table.insert, table.reverse
22local lower, upper, rep, match, gsub = string.lower, string.upper, string.rep, string.match, string.gsub
23local utfchar, utfbyte = utf.char, utf.byte
24local tonumber, tostring, type, rawset = tonumber, tostring, type, rawset
25local P, S, R, Cc, Cf, Cg, Ct, Cs, C, V, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.Cs, lpeg.C, lpeg.V, lpeg.Carg
26local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
27local div, mod = math.div, math.mod
28
29local context = context
30local commands = commands
31local implement = interfaces.implement
32
33local settings_to_array = utilities.parsers.settings_to_array
34local allocate = utilities.storage.allocate
35local setmetatableindex = table.setmetatableindex
36local formatters = string.formatters
37local variables = interfaces.variables
38local constants = interfaces.constants
39local addformatter = utilities.strings.formatters.add
40
41local texset = tex.set
42
43converters = converters or { }
44local converters = converters
45
46languages = languages or { }
47local languages = languages
48
49local helpers = converters.helpers or { }
50converters.helpers = helpers
51
52local ctx_labeltext = context.labeltext
53local ctx_LABELTEXT = context.LABELTEXT
54local ctx_space = context.space
55local ctx_convertnumber = context.convertnumber
56local ctx_highordinalstr = context.highordinalstr
57
58converters.number = tonumber
59converters.numbers = tonumber
60
61implement { name = "number", actions = context }
62implement { name = "numbers", actions = context }
63
64
65
66local counters = allocate {
67 ['default'] = {
68 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
69 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
70 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
71 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
72 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
73 0x007A
74 },
75 ['slovenian'] = {
76 0x0061, 0x0062, 0x0063, 0x010D, 0x0064,
77 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
78 0x006A, 0x006B, 0x006C, 0x006D, 0x006E,
79 0x006F, 0x0070, 0x0072, 0x0073, 0x0161,
80 0x0074, 0x0075, 0x0076, 0x007A, 0x017E
81 },
82 ['spanish'] = {
83 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
84 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
85 0x006B, 0x006C, 0x006D, 0x006E, 0x00F1,
86 0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
87 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
88 0x0079, 0x007A
89 },
90 ['russian'] = {
91 0x0430, 0x0431, 0x0432, 0x0433, 0x0434,
92 0x0435, 0x0436, 0x0437, 0x0438, 0x043a,
93 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
94 0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
95 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
96 0x044d, 0x044e, 0x044f
97 },
98 ['greek'] = {
99
100
101
102
103
104 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
105 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
106 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
107 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5,
108 0x03C6, 0x03C7, 0x03C8, 0x03C9,
109 },
110 ['arabic'] = {
111 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
112 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
113 0x0643, 0x0644, 0x0645, 0x0646, 0x0633,
114 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
115 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
116 0x0636, 0x0638, 0x063A,
117 },
118 ['persian'] = {
119 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
120 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
121 0x06A9, 0x0644, 0x0645, 0x0646, 0x0633,
122 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
123 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
124 0x0636, 0x0638, 0x063A,
125 },
126 ['thai'] = {
127 0xE050, 0xE051, 0xE052, 0xE053, 0xE054,
128 0xE055, 0xE056, 0xE057, 0xE058, 0xE059
129 },
130 ['devangari'] = {
131 0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
132 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
133 },
134 ['gurmurkhi'] = {
135 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
136 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
137 },
138 ['gujarati'] = {
139 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
140 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
141 },
142 ['tibetan'] = {
143 0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24,
144 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
145 },
146 ['korean'] = {
147 0x3131, 0x3134, 0x3137, 0x3139, 0x3141,
148 0x3142, 0x3145, 0x3147, 0x3148, 0x314A,
149 0x314B, 0x314C, 0x314D, 0x314E
150 },
151 ['korean-parenthesis'] = {
152 0x3200, 0x3201, 0x3202, 0x3203, 0x3204,
153 0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
154 0x320A, 0x320B, 0x320C, 0x320D
155 },
156 ['korean-circle'] = {
157 0x3260, 0x3261, 0x3262, 0x3263, 0x3264,
158 0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
159 0x326A, 0x326B, 0x326C, 0x326D
160 },
161}
162
163languages.counters = counters
164
165counters['ar'] = counters['arabic']
166counters['gr'] = counters['greek']
167counters['g'] = counters['greek']
168counters['sl'] = counters['slovenian']
169counters['es'] = counters['spanish']
170counters['ru'] = counters['russian']
171counters['kr'] = counters['korean']
172counters['kr-p'] = counters['korean-parenthesis']
173counters['kr-c'] = counters['korean-circle']
174
175counters['thainumerals'] = counters['thai']
176counters['devanagarinumerals'] = counters['devanagari']
177counters['gurmurkhinumerals'] = counters['gurmurkhi']
178counters['gujaratinumerals'] = counters['gujarati']
179counters['tibetannumerals'] = counters['tibetan']
180counters['greeknumerals'] = counters['greek']
181counters['arabicnumerals'] = counters['arabic']
182counters['persiannumerals'] = counters['persian']
183counters['arabicexnumerals'] = counters['persian']
184counters['koreannumerals'] = counters['korean']
185counters['koreanparenthesisnumerals'] = counters['korean-parenthesis']
186counters['koreancirclenumerals'] = counters['korean-circle']
187
188counters['sloveniannumerals'] = counters['slovenian']
189counters['spanishnumerals'] = counters['spanish']
190counters['russiannumerals'] = counters['russian']
191
192local decimals = allocate {
193 ['arabic'] = {
194 ["0"] = "٠", ["1"] = "١", ["2"] = "٢", ["3"] = "٣", ["4"] = "٤",
195 ["5"] = "٥", ["6"] = "٦", ["7"] = "٧", ["8"] = "٨", ["9"] = "٩",
196 },
197 ['persian'] = {
198 ["0"] = "۰", ["1"] = "۱", ["2"] = "۲", ["3"] = "۳", ["4"] = "۴",
199 ["5"] = "۵", ["6"] = "۶", ["7"] = "۷", ["8"] = "۸", ["9"] = "۹",
200 }
201}
202
203languages.decimals = decimals
204
205local fallback = utfbyte('0')
206
207local function chr(n,m)
208 return (n > 0 and n < 27 and utfchar(n+m)) or ""
209end
210
211local function chrs(n,m,t)
212 if not t then
213 t = { }
214 end
215 if n > 26 then
216 chrs(floor((n-1)/26),m,t)
217 n = (n-1)%26 + 1
218 end
219 if n ~= 0 then
220 t[#t+1] = utfchar(n+m)
221 end
222 if n <= 26 then
223 return concat(t)
224 end
225end
226
227local function maxchrs(n,m,cmd,t)
228 if not t then
229 t = { }
230 end
231 if n > m then
232 maxchrs(floor((n-1)/m),m,cmd)
233 n = (n-1)%m + 1
234 end
235 t[#t+1] = formatters["%s{%s}"](cmd,n)
236 if n <= m then
237 return concat(t)
238 end
239end
240
241converters.chr = chr
242converters.chrs = chrs
243converters.maxchrs = maxchrs
244
245local lowercharacter = characters.lcchars
246local uppercharacter = characters.ucchars
247
248local defaultcounter = counters.default
249
250local function do_alphabetic(n,mapping,mapper,t)
251 if not t then
252 t = { }
253 end
254 local max = #mapping
255 if n > max then
256 do_alphabetic(floor((n-1)/max),mapping,mapper,t)
257 n = (n-1) % max + 1
258 end
259 local chr = mapping[n] or fallback
260 t[#t+1] = mapper and mapper[chr] or chr
261 if n <= max then
262 return concat(t)
263 end
264end
265
266local function alphabetic(n,code)
267 return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,lowercharacter)
268end
269
270local function Alphabetic(n,code)
271 return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,uppercharacter)
272end
273
274converters.alphabetic = alphabetic
275converters.Alphabetic = Alphabetic
276
277
278
279local function todecimals(n,name)
280 local stream = tostring(n)
281 local mapping = decimals[name]
282 return mapping and gsub(stream,".",mapping) or stream
283end
284
285converters.decimals = todecimals
286
287local lower_offset = 96
288local upper_offset = 64
289
290function converters.character (n) return chr (n,lower_offset) end
291function converters.Character (n) return chr (n,upper_offset) end
292function converters.characters(n) return chrs(n,lower_offset) end
293function converters.Characters(n) return chrs(n,upper_offset) end
294
295implement { name = "alphabetic", actions = { alphabetic, context }, arguments = { "integer", "string" } }
296implement { name = "Alphabetic", actions = { Alphabetic, context }, arguments = { "integer", "string" } }
297
298implement { name = "character", actions = { chr, context }, arguments = { "integer", lower_offset } }
299implement { name = "Character", actions = { chr, context }, arguments = { "integer", upper_offset } }
300implement { name = "characters", actions = { chrs, context }, arguments = { "integer", lower_offset } }
301implement { name = "Characters", actions = { chrs, context }, arguments = { "integer", upper_offset } }
302
303implement { name = "decimals", actions = { todecimals, context }, arguments = { "integer", "string" } }
304
305local weekday = os.weekday
306local isleapyear = os.isleapyear
307local nofdays = os.nofdays
308
309local function leapyear(year)
310 return isleapyear(year) and 1 or 0
311end
312
313local function textime()
314 return tonumber(osdate("%H")) * 60 + tonumber(osdate("%M"))
315end
316
317
318
319
320
321
322
323
324
325
326
327converters.weekday = weekday
328converters.isleapyear = isleapyear
329converters.leapyear = leapyear
330converters.nofdays = nofdays
331converters.textime = textime
332
333implement { name = "weekday", actions = { weekday, context }, arguments = { "integer", "integer", "integer" } }
334implement { name = "leapyear", actions = { leapyear, context }, arguments = "integer" }
335implement { name = "nofdays", actions = { nofdays, context }, arguments = { "integer", "integer" } }
336
337implement { name = "year", actions = { osdate, context }, arguments = "'%Y'" }
338implement { name = "month", actions = { osdate, context }, arguments = "'%m'" }
339implement { name = "day", actions = { osdate, context }, arguments = "'%d'" }
340implement { name = "hour", actions = { osdate, context }, arguments = "'%H'" }
341implement { name = "minute", actions = { osdate, context }, arguments = "'%M'" }
342implement { name = "second", actions = { osdate, context }, arguments = "'%S'" }
343implement { name = "textime", actions = { textime, context } }
344
345implement {
346 name = "doifelseleapyear",
347 actions = { isleapyear, commands.doifelse },
348 arguments = "integer"
349}
350
351local roman = {
352 { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
353 { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
354 { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
355}
356
357local function toroman(n)
358 if n >= 4000 then
359 return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
360 else
361 return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n%10)/1)]
362 end
363end
364
365converters.toroman = toroman
366converters.Romannumerals = toroman
367converters.romannumerals = function(n) return lower(toroman(n)) end
368
369converters['i'] = converters.romannumerals
370converters['I'] = converters.Romannumerals
371converters['r'] = converters.romannumerals
372converters['R'] = converters.Romannumerals
373converters['KR'] = converters.Romannumerals
374converters['RK'] = converters.Romannumerals
375
376implement {
377 name = "romannumerals",
378 actions = { toroman, lower, context },
379 arguments = "integer",
380}
381
382implement {
383 name = "Romannumerals",
384 actions = { toroman, context },
385 arguments = "integer",
386}
387
388
389
390
391
392
393
394
395
396
397
398
399local small = {
400 "ا", "ٮ", "ح", "د", "ه", "و", "ر",
401}
402
403local medium = {
404 "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" ,
405 "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" ,
406 "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" ,
407 "غ" ,
408}
409
410local large = {
411 { "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" },
412 { "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" },
413 { "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" },
414 { "غ" },
415}
416
417local function toabjad(n,what)
418 if n <= 0 or n >= 2000 then
419 return tostring(n)
420 elseif what == 2 and n <= 7 then
421 return small[n]
422 elseif what == 3 and n <= 28 then
423 return medium[n]
424 else
425 local a, b, c, d
426 a, n = floor(n/1000), n % 1000
427 b, n = floor(n/ 100), n % 100
428 c, n = floor(n/ 10), n % 10
429 d, n = floor(n/ 1), n % 1
430 return (large[4][a] or "") .. (large[3][b] or "") .. (large[2][c] or "") .. (large[1][d] or "")
431 end
432end
433
434converters.toabjad = toabjad
435
436function converters.abjadnumerals (n) return toabjad(n,false) end
437function converters.abjadnodotnumerals(n) return toabjad(n,true ) end
438
439implement {
440 name = "abjadnumerals",
441 actions = { toabjad, context },
442 arguments = { "integer", false }
443}
444
445implement {
446 name = "abjadnodotnumerals",
447 actions = { toabjad, context },
448 arguments = { "integer", true }
449}
450
451
452
453local trace_hebrew trackers.register("converters.hebrew", function(v)
454 trace_hebrew = v
455end)
456
457local list = {
458 { 400, "ת" }, { 300, "ש" }, { 200, "ר" }, { 100, "ק" },
459 { 90, "צ" }, { 80, "פ" }, { 70, "ע" }, { 60, "ס "}, { 50, "נ" }, { 40, "מ" }, { 30, "ל" }, { 20, "כ" }, { 10, "י" },
460 { 9, "ט" }, { 8, "ח" }, { 7, "ז", }, { 6, "ו", }, { 5, "ה" }, { 4, "ד" }, { 3, "ג" }, { 2, "ב" }, { 1, "א" },
461}
462
463local special = {
464 [15] = "ט״ו",
465 [16] = "ט״ז",
466}
467
468local function tohebrew(n,gershayim,geresh)
469 local split = { }
470 local size = 0
471 while n > 1000 do
472 size = size + 1
473 split[size] = n % 1000
474 n = floor(n/1000)
475 end
476 size = size + 1
477 split[size] = n
478 for i=1,size do
479 local t = { }
480 local n = 0
481 local s = split[i]
482 while s > 0 do
483 for i=1,#list do
484 ::again::
485 local li = list[i]
486 local l1 = li[1]
487 local s1 = special[l1]
488 if s1 then
489 s = s - l1
490 n = n + 1
491 t[n] = s1
492 goto again
493 elseif s >= l1 then
494 s = s - l1
495 n = n + 1
496 t[n] = li[2]
497 goto again
498 end
499 end
500 end
501 ::done::
502 split[i] = t
503 end
504 if gershayim then
505 for i=1,size do
506 local si = split[i]
507 local ni = #si
508 if ni >= 2 then
509 local s = "״"
510 insert(split[i],ni,trace_hebrew and ("{\\red "..s.."}") or s)
511 end
512 end
513 end
514 if geresh then
515 for i=2,#split do
516 local s = rep("׳",i-1)
517 insert(split[i],trace_hebrew and ("{\\blue "..s.."}") or s)
518 end
519 end
520 for i=1,size do
521 split[i] = concat(split[i])
522 end
523 return concat(reverse(split))
524end
525
526converters.tohebrew = tohebrew
527converters.hebrewnumerals = converters.tohebrew
528
529
530
531interfaces.implement {
532 name = "hebrewnumerals",
533 actions = { tohebrew, context },
534 arguments = { "integer", true, true }
535}
536
537
538
539local vector = {
540 normal = {
541 [0] = "〇",
542 [1] = "一",
543 [2] = "二",
544 [3] = "三",
545 [4] = "四",
546 [5] = "五",
547 [6] = "六",
548 [7] = "七",
549 [8] = "八",
550 [9] = "九",
551 [10] = "十",
552 [100] = "百",
553 [1000] = "千",
554 [10000] = "万",
555 [100000000] = "亿",
556 },
557 cap = {
558 [0] = "零",
559 [1] = "壹",
560 [2] = "贰",
561 [3] = "叁",
562 [4] = "肆",
563 [5] = "伍",
564 [6] = "陆",
565 [7] = "柒",
566 [8] = "捌",
567 [9] = "玖",
568 [10] = "拾",
569 [100] = "佰",
570 [1000] = "仟",
571 [10000] = "萬",
572 [100000000] = "亿",
573 },
574 all = {
575 [0] = "〇",
576 [1] = "一",
577 [2] = "二",
578 [3] = "三",
579 [4] = "四",
580 [5] = "五",
581 [6] = "六",
582 [7] = "七",
583 [8] = "八",
584 [9] = "九",
585 [10] = "十",
586 [20] = "廿",
587 [30] = "卅",
588 [100] = "百",
589 [1000] = "千",
590 [10000] = "万",
591 [100000000] = "亿",
592 }
593}
594
595local function tochinese(n,name)
596
597 local result, r = { }, 0
598 local vector = vector[name] or vector.normal
599 while true do
600 if n == 0 then
601 break
602 elseif n >= 100000000 then
603 local m = floor(n/100000000)
604 r = r + 1 ; result[r] = tochinese(m,name)
605 r = r + 1 ; result[r] = vector[100000000]
606 local z = n - m * 100000000
607 if z > 0 and z < 10000000 then r = r + 1 ; result[r] = vector[0] end
608 n = n % 100000000
609 elseif n >= 10000000 then
610 local m = floor(n/10000)
611 r = r + 1 ; result[r] = tochinese(m,name)
612 r = r + 1 ; result[r] = vector[10000]
613 local z = n - m * 10000
614 if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
615 n = n % 10000
616 elseif n >= 1000000 then
617 local m = floor(n/10000)
618 r = r + 1 ; result[r] = tochinese(m,name)
619 r = r + 1 ; result[r] = vector[10000]
620 local z = n - m * 10000
621 if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
622 n = n % 10000
623 elseif n >= 100000 then
624 local m = floor(n/10000)
625 r = r + 1 ; result[r] = tochinese(m,name)
626 r = r + 1 ; result[r] = vector[10000]
627 local z = n - m * 10000
628 if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
629 n = n % 10000
630 elseif n >= 10000 then
631 local m = floor(n/10000)
632 r = r + 1 ; result[r] = vector[m]
633 r = r + 1 ; result[r] = vector[10000]
634 local z = n - m * 10000
635 if z > 0 and z < 1000 then r = r + 1 ; result[r] = vector[0] end
636 n = n % 10000
637 elseif n >= 1000 then
638 local m = floor(n/1000)
639 r = r + 1 ; result[r] = vector[m]
640 r = r + 1 ; result[r] = vector[1000]
641 local z = n - m * 1000
642 if z > 0 and z < 100 then r = r + 1 ; result[r] = vector[0] end
643 n = n % 1000
644 elseif n >= 100 then
645 local m = floor(n/100)
646 r = r + 1 ; result[r] = vector[m]
647 r = r + 1 ; result[r] = vector[100]
648 local z = n - m * 100
649 if z > 0 and z < 10 then r = r + 1 ; result[r] = vector[0] end
650 n = n % 100
651 elseif n >= 10 then
652 local m = floor(n/10)
653 if m > 1 and vector[m*10] then
654 r = r + 1 ; result[r] = vector[m*10]
655 else
656 r = r + 1 ; result[r] = vector[m]
657 r = r + 1 ; result[r] = vector[10]
658 end
659 n = n % 10
660 else
661 r = r + 1 ; result[r] = vector[n]
662 break
663 end
664 end
665 if (result[1] == vector[1] and result[2] == vector[10]) then
666 result[1] = ""
667 end
668 return concat(result)
669end
670
671
672
673
674
675
676
677converters.tochinese = tochinese
678
679function converters.chinesenumerals (n,how) return tochinese(n,how or "normal") end
680function converters.chinesecapnumerals(n) return tochinese(n,"cap") end
681function converters.chineseallnumerals(n) return tochinese(n,"all") end
682
683converters['cn'] = converters.chinesenumerals
684converters['cn-c'] = converters.chinesecapnumerals
685converters['cn-a'] = converters.chineseallnumerals
686
687implement {
688 name = "chinesenumerals",
689 actions = { tochinese, context },
690 arguments = { "integer", "string" }
691}
692
693
694
695
696converters['a'] = converters.characters
697converters['A'] = converters.Characters
698converters['AK'] = converters.Characters
699converters['KA'] = converters.Characters
700
701function converters.spanishnumerals (n) return alphabetic(n,"es") end
702function converters.Spanishnumerals (n) return Alphabetic(n,"es") end
703function converters.sloveniannumerals(n) return alphabetic(n,"sl") end
704function converters.Sloveniannumerals(n) return Alphabetic(n,"sl") end
705function converters.russiannumerals (n) return alphabetic(n,"ru") end
706function converters.Russiannumerals (n) return Alphabetic(n,"ru") end
707
708converters['alphabetic:es'] = converters.spanishnumerals
709converters['alphabetic:sl'] = converters.sloveniannumerals
710converters['alphabetic:ru'] = converters.russiannumerals
711
712converters['Alphabetic:es'] = converters.Spanishnumerals
713converters['Alphabetic:sl'] = converters.Sloveniannumerals
714converters['Alphabetic:ru'] = converters.Russiannumerals
715
716
717
718converters['a:es'] = converters.spanishnumerals
719converters['a:sl'] = converters.sloveniannumerals
720converters['a:ru'] = converters.russiannumerals
721converters['A:es'] = converters.Spanishnumerals
722converters['A:sl'] = converters.Sloveniannumerals
723converters['A:ru'] = converters.Russiannumerals
724
725
726
727converters.sequences = converters.sequences or { }
728local sequences = converters.sequences
729
730storage.register("converters/sequences", sequences, "converters.sequences")
731
732function converters.define(name,set)
733
734
735
736 sequences[name] = settings_to_array(set)
737end
738
739function converters.max(name)
740 local s = sequences[name]
741 return s and #s or 0
742end
743
744implement {
745 name = "defineconversion",
746 actions = converters.define,
747 arguments = "2 strings",
748}
749
750implement {
751 name = "nofconversions",
752 actions = { converters.max, context },
753 arguments = "string",
754}
755
756local function convert(method,n,language)
757 local converter = language and converters[method..":"..language] or converters[method]
758 if converter then
759 return converter(n)
760 else
761 local lowermethod = lower(method)
762 local linguistic = counters[lowermethod]
763 if linguistic then
764 return do_alphabetic(n,linguistic,lowermethod == method and lowercharacter or uppercharacter)
765 end
766 local sequence = sequences[method]
767 if sequence then
768 local max = #sequence
769 if n > max then
770 return sequence[(n-1) % max + 1]
771 else
772 return sequence[n]
773 end
774 end
775 return n
776 end
777end
778
779converters.convert = convert
780
781local function valid(method,language)
782 return converters[method..":"..language] or converters[method] or sequences[method]
783end
784
785implement {
786 name = "doifelseconverter",
787 actions = { valid, commands.doifelse },
788 arguments = "2 strings",
789}
790
791implement {
792 name = "checkedconversion",
793 actions = { convert, context },
794 arguments = { "string", "integer" }
795}
796
797
798
799local gregorian_to_hebrew do
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 local NISAN = 1
818 local IYYAR = 2
819 local SIVAN = 3
820 local TAMUZ = 4
821 local AV = 5
822 local ELUL = 6
823 local TISHREI = 7
824 local CHESHVAN = 8
825 local KISLEV = 9
826 local TEVET = 10
827 local SHVAT = 11
828 local ADAR_I = 12
829 local ADAR_II = 13
830
831 local mmap = {
832 KISLEV,
833 TEVET,
834 SHVAT,
835 ADAR_I,
836 NISAN,
837 IYYAR,
838 SIVAN,
839 TAMUZ,
840 TISHREI,
841 TISHREI,
842 TISHREI,
843 CHESHVAN
844 }
845
846 local function greg2abs(year,month,day)
847 local y = year - 1
848 return y * 365 + div(y,4)- div(y,100) + div(y,400) + os.nofdays(year,month,day)
849 end
850
851 local function abs2greg(abs)
852
853 local d0 = abs - 1
854
855 local n400 = div(d0, 146097)
856 local d1 = mod(d0, 146097)
857 local n100 = div(d1, 36524)
858 local d2 = mod(d1, 36524)
859 local n4 = div(d2, 1461)
860 local d3 = mod(d2, 1461)
861 local n1 = div(d3, 365)
862
863 local day = mod(d3, 365) + 1
864 local year = 400 * n400 + 100 * n100 + 4 * n4 + n1
865
866 if n100 == 4 or n1 == 4 then
867 return year, 12, 31
868 else
869 year = year + 1
870 month = 1
871 while true do
872 local mlen = os.nofdays(year,month)
873 if mlen < day then
874 day = day - mlen
875 month = month + 1
876 else
877 break
878 end
879 end
880 return year, month, day
881 end
882 end
883
884 local function hebrew_leapyear(year)
885 return mod(1 + year * 7, 19) < 7
886 end
887
888 local function hebrew_months_in_year(year)
889 return hebrew_leapyear(year) and 13 or 12
890 end
891
892 local function hebrew_elapsed_days(year)
893 local y = year - 1
894 local m_elapsed = 235 * div(y,19) + 12 * mod(y,19) + div(((mod(y,19) * 7) + 1),19)
895 local p_elapsed = 204 + 793 * mod(m_elapsed,1080)
896 local h_elapsed = 5 + 12 * m_elapsed + 793 * div(m_elapsed,1080) + div(p_elapsed,1080)
897 local parts = mod(p_elapsed,1080) + 1080 * mod(h_elapsed,24)
898 local day = 1 + 29 * m_elapsed + div(h_elapsed,24)
899 local d = mod(day,7)
900 local alt_day = day
901 if parts >= 19440
902 or (parts >= 9924 and d == 2 and not (hebrew_leapyear(year)))
903 or (parts >= 16789 and d == 1 and hebrew_leapyear(y )) then
904 alt_day = alt_day + 1
905 end
906 d = mod(alt_day,7)
907 if d == 0 or d == 3 or d == 5 then
908 alt_day = alt_day + 1
909 end
910 return alt_day
911 end
912
913 local function days_in_hebrew_year(year)
914 return hebrew_elapsed_days(year + 1) - hebrew_elapsed_days(year)
915 end
916
917 local function long_cheshvan(year)
918 return mod(days_in_hebrew_year(year),10) == 5
919 end
920
921 local function short_kislev(year)
922 return mod(days_in_hebrew_year(year),10) == 3
923 end
924
925 local function max_days_in_heb_month(month,year)
926 if month == IYYAR or month == TAMUZ or month == ELUL or month == TEVET or month == ADAR_II or
927 (month == ADAR_I and not hebrew_leapyear(year)) or
928 (month == CHESHVAN and not long_cheshvan(year)) or
929 (month == KISLEV and short_kislev (year)) then
930 return 29
931 else
932 return 30
933 end
934 end
935
936 local function hebrew2abs(year,month,day)
937 if month < TISHREI then
938 for m=TISHREI, hebrew_months_in_year(year), 1 do
939 day = day + max_days_in_heb_month(m,year)
940 end
941 for m=NISAN, month - 1, 1 do
942 day = day + max_days_in_heb_month(m,year)
943 end
944 else
945 for m=TISHREI, month - 1, 1 do
946 day = day + max_days_in_heb_month(m,year)
947 end
948 end
949 return hebrew_elapsed_days(year) - 1373429 + day
950 end
951
952 local function abs2hebrew(abs)
953 local yy, mm, dd = abs2greg(abs)
954 local day = 1
955 local month = TISHREI
956 local year = 3760 + yy
957 while abs >= hebrew2abs(year+1,month,day) do
958 year = year + 1
959 end
960 if year >= 4635 and year < 10666 then
961 month = mmap[mm]
962 end
963 while abs > hebrew2abs(year,month,max_days_in_heb_month(month,year)) do
964 month = mod(month,hebrew_months_in_year(year)) + 1
965 end
966 day = abs - hebrew2abs(year,month,1) + 1
967 return year, month, day
968 end
969
970
971
972 gregorian_to_hebrew = function(y,m,d)
973 return abs2hebrew(greg2abs(y,m,d))
974 end
975
976 converters.gregorian_to_hebrew = gregorian_to_hebrew
977
978end
979
980local gregorian_to_jalali, jalali_to_gregorian do
981
982
983
984
985
986
987
988
989
990
991
992
993
994 local g_days_in_month = { [0] = 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
995 local j_days_in_month = { [0] = 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 }
996
997
998 gregorian_to_jalali = function(gy,gm,gd)
999 local jy, jm, jd, g_day_no, j_day_no, j_np, i
1000 gy, gm, gd = gy - 1600, gm - 1, gd - 1
1001 g_day_no = 365*gy + div((gy+3),4) - div((gy+99),100) + div((gy+399),400)
1002 i = 0
1003 while i < gm do
1004 g_day_no = g_day_no + g_days_in_month[i]
1005 i = i + 1
1006 end
1007 if (gm>1 and ((gy%4==0 and gy%100~=0) or (gy%400==0))) then
1008 g_day_no = g_day_no + 1
1009 end
1010 g_day_no = g_day_no + gd
1011 j_day_no = g_day_no - 79
1012 j_np = div(j_day_no,12053)
1013 j_day_no = mod(j_day_no,12053)
1014 jy = 979 + 33*j_np + 4*div(j_day_no,1461)
1015 j_day_no = mod(j_day_no,1461)
1016 if j_day_no >= 366 then
1017 jy = jy + div((j_day_no-1),365)
1018 j_day_no = mod((j_day_no-1),365)
1019 end
1020 i = 0
1021 while i < 11 and j_day_no >= j_days_in_month[i] do
1022 j_day_no = j_day_no - j_days_in_month[i]
1023 i = i + 1
1024 end
1025 jm = i + 1
1026 jd = j_day_no + 1
1027 return jy, jm, jd
1028 end
1029
1030 jalali_to_gregorian = function(jy,jm,jd)
1031 local gy, gm, gd, g_day_no, j_day_no, leap, i
1032 jy, jm, jd = jy - 979, jm - 1, jd - 1
1033 j_day_no = 365*jy + div(jy,33)*8 + div((mod(jy,33)+3),4)
1034 for i=0,jm-1,1 do
1035 j_day_no = j_day_no + j_days_in_month[i]
1036 end
1037 j_day_no = j_day_no + jd
1038 g_day_no = j_day_no + 79
1039 gy = 1600 + 400*div(g_day_no,146097)
1040 g_day_no = mod(g_day_no, 146097)
1041 leap = 1
1042 if g_day_no >= 36525 then
1043 g_day_no = g_day_no - 1
1044 gy = gy + 100*div(g_day_no,36524)
1045 g_day_no = mod(g_day_no, 36524)
1046 if g_day_no >= 365 then
1047 g_day_no = g_day_no + 1
1048 else
1049 leap = 0
1050 end
1051 end
1052 gy = gy + 4*div(g_day_no,1461)
1053 g_day_no = mod(g_day_no, 1461)
1054 if g_day_no >= 366 then
1055 leap = 0
1056 g_day_no = g_day_no - 1
1057 gy = gy + div(g_day_no, 365)
1058 g_day_no = mod(g_day_no, 365)
1059 end
1060 i = 0
1061 while true do
1062 local d = g_days_in_month[i] + ((i == 1 and leap) or 0)
1063 if g_day_no >= d then
1064 g_day_no = g_day_no - d
1065 i = i + 1
1066 else
1067 break
1068 end
1069 end
1070 gm = i + 1
1071 gd = g_day_no + 1
1072 return gy, gm, gd
1073 end
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 converters.gregorian_to_jalali = gregorian_to_jalali
1091 converters.jalali_to_gregorian = jalali_to_gregorian
1092
1093end
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131local ordinals = {
1132 english = function(n)
1133 local two = n % 100
1134 if two == 11 or two == 12 or two == 13 then
1135 return "th"
1136 else
1137 local one = n % 10
1138 if one == 1 then
1139 return "st"
1140 elseif one == 2 then
1141 return "nd"
1142 elseif one == 3 then
1143 return "rd"
1144 else
1145 return "th"
1146 end
1147 end
1148 end,
1149 dutch = function(n)
1150 return "e"
1151 end,
1152 french = function(n)
1153 if n == 1 then
1154 return "er"
1155 else
1156 return "e"
1157 end
1158 end,
1159}
1160
1161ordinals.en = ordinals.english
1162ordinals.nl = ordinals.dutch
1163ordinals.fr = ordinals.french
1164
1165function converters.ordinal(n,language)
1166 local t = language and ordinals[language]
1167 return t and t(n)
1168end
1169
1170local function ctxordinal(n,language)
1171 local t = language and ordinals[language]
1172 local o = t and t(n)
1173 context(n)
1174 if o then
1175 ctx_highordinalstr(o)
1176 end
1177end
1178
1179implement {
1180 name = "ordinal",
1181 actions = ctxordinal,
1182 arguments = { "integer", "string" }
1183}
1184
1185
1186
1187local data = allocate()
1188local verbose = { data = data }
1189converters.verbose = verbose
1190
1191
1192
1193local words = {
1194 [0] = "zero",
1195 [1] = "one",
1196 [2] = "two",
1197 [3] = "three",
1198 [4] = "four",
1199 [5] = "five",
1200 [6] = "six",
1201 [7] = "seven",
1202 [8] = "eight",
1203 [9] = "nine",
1204 [10] = "ten",
1205 [11] = "eleven",
1206 [12] = "twelve",
1207 [13] = "thirteen",
1208 [14] = "fourteen",
1209 [15] = "fifteen",
1210 [16] = "sixteen",
1211 [17] = "seventeen",
1212 [18] = "eighteen",
1213 [19] = "nineteen",
1214 [20] = "twenty",
1215 [30] = "thirty",
1216 [40] = "forty",
1217 [50] = "fifty",
1218 [60] = "sixty",
1219 [70] = "seventy",
1220 [80] = "eighty",
1221 [90] = "ninety",
1222 [100] = "hundred",
1223 [1000] = "thousand",
1224 [1000000] = "million",
1225 [1000000000] = "billion",
1226 [1000000000000] = "trillion",
1227}
1228
1229local function translate(n,connector)
1230 local w = words[n]
1231 if w then
1232 return w
1233 end
1234 local t = { }
1235 local function compose_one(n)
1236 local w = words[n]
1237 if w then
1238 t[#t+1] = w
1239 return
1240 end
1241 local a, b = floor(n/100), n % 100
1242 if a == 10 then
1243 t[#t+1] = words[1]
1244 t[#t+1] = words[1000]
1245 elseif a > 0 then
1246 t[#t+1] = words[a]
1247 t[#t+1] = words[100]
1248
1249 if b == 0 then
1250 return
1251 end
1252 end
1253 if words[b] then
1254 t[#t+1] = words[b]
1255 else
1256 a, b = floor(b/10), n % 10
1257 t[#t+1] = words[a*10]
1258 t[#t+1] = words[b]
1259 end
1260 end
1261 local function compose_two(n,m)
1262 if n > (m-1) then
1263 local a, b = floor(n/m), n % m
1264 if a > 0 then
1265 compose_one(a)
1266 end
1267 t[#t+1] = words[m]
1268 n = b
1269 end
1270 return n
1271 end
1272 n = compose_two(n,1000000000000)
1273 n = compose_two(n,1000000000)
1274 n = compose_two(n,1000000)
1275 n = compose_two(n,1000)
1276 if n > 0 then
1277 compose_one(n)
1278 end
1279 return #t > 0 and concat(t,connector or " ") or tostring(n)
1280end
1281
1282data.english = {
1283 words = words,
1284 translate = translate,
1285}
1286
1287data.en = data.english
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299local words = {
1300 [1] = "uno",
1301 [2] = "dos",
1302 [3] = "tres",
1303 [4] = "cuatro",
1304 [5] = "cinco",
1305 [6] = "seis",
1306 [7] = "siete",
1307 [8] = "ocho",
1308 [9] = "nueve",
1309 [10] = "diez",
1310 [11] = "once",
1311 [12] = "doce",
1312 [13] = "trece",
1313 [14] = "catorce",
1314 [15] = "quince",
1315 [16] = "dieciséis",
1316 [17] = "diecisiete",
1317 [18] = "dieciocho",
1318 [19] = "diecinueve",
1319 [20] = "veinte",
1320 [21] = "veintiuno",
1321 [22] = "veintidós",
1322 [23] = "veintitrés",
1323 [24] = "veinticuatro",
1324 [25] = "veinticinco",
1325 [26] = "veintiséis",
1326 [27] = "veintisiete",
1327 [28] = "veintiocho",
1328 [29] = "veintinueve",
1329 [30] = "treinta",
1330 [40] = "cuarenta",
1331 [50] = "cincuenta",
1332 [60] = "sesenta",
1333 [70] = "setenta",
1334 [80] = "ochenta",
1335 [90] = "noventa",
1336 [100] = "ciento",
1337 [200] = "doscientos",
1338 [300] = "trescientos",
1339 [400] = "cuatrocientos",
1340 [500] = "quinientos",
1341 [600] = "seiscientos",
1342 [700] = "setecientos",
1343 [800] = "ochocientos",
1344 [900] = "novecientos",
1345 [1000] = "mil",
1346 [1000000] = "millón",
1347 [1000000000] = "mil millones",
1348 [1000000000000] = "billón",
1349}
1350
1351local function translate(n,connector)
1352 local w = words[n]
1353 if w then
1354 return w
1355 end
1356 local t = { }
1357 local function compose_one(n)
1358 local w = words[n]
1359 if w then
1360 t[#t+1] = w
1361 return
1362 end
1363
1364 local a, b = floor(n/100), n % 100
1365
1366 if a == 10 then
1367 t[#t+1] = words[1]
1368 t[#t+1] = words[1000]
1369
1370
1371
1372 elseif a > 0 then
1373 t[#t+1] = words[a*100]
1374 end
1375
1376 if words[b] then
1377 t[#t+1] = words[b]
1378 else
1379
1380 a, b = floor(b/10), n % 10
1381 t[#t+1] = words[a*10]
1382 t[#t+1] = "y"
1383 t[#t+1] = words[b]
1384 end
1385 end
1386
1387
1388 local function compose_two(n,m)
1389 if n > (m-1) then
1390 local a, b = floor(n/m), n % m
1391 if a > 0 then
1392 compose_one(a)
1393 end
1394 t[#t+1] = words[m]
1395 n = b
1396 end
1397 return n
1398 end
1399 n = compose_two(n,1000000000000)
1400 n = compose_two(n,1000000000)
1401 n = compose_two(n,1000000)
1402 n = compose_two(n,1000)
1403 if n > 0 then
1404 compose_one(n)
1405 end
1406 return #t > 0 and concat(t,connector or " ") or tostring(n)
1407end
1408
1409data.spanish = {
1410 words = words,
1411 translate = translate,
1412}
1413
1414data.es = data.spanish
1415
1416
1417
1418
1419
1420
1421
1422do
1423
1424 local words = {
1425 [0] = "noll",
1426 [1] = "ett",
1427 [2] = "två",
1428 [3] = "tre",
1429 [4] = "fyra",
1430 [5] = "fem",
1431 [6] = "sex",
1432 [7] = "sju",
1433 [8] = "åtta",
1434 [9] = "nio",
1435 [10] = "tio",
1436 [11] = "elva",
1437 [12] = "tolv",
1438 [13] = "tretton",
1439 [14] = "fjorton",
1440 [15] = "femton",
1441 [16] = "sexton",
1442 [17] = "sjutton",
1443 [18] = "arton",
1444 [19] = "nitton",
1445 [20] = "tjugo",
1446 [30] = "trettio",
1447 [40] = "fyrtio",
1448 [50] = "femtio",
1449 [60] = "sextio",
1450 [70] = "sjuttio",
1451 [80] = "åttio",
1452 [90] = "nittio",
1453 [100] = "hundra",
1454 [10^3] = "tusen",
1455 [10^6] = "miljon",
1456 [10^9] = "miljard",
1457 [10^12] = "biljon",
1458 [10^15] = "biljard",
1459 }
1460
1461 local function translate(n,connector)
1462 local w = words[n]
1463 if w then
1464 return w
1465 else
1466 local t = { }
1467 local l = 0
1468
1469 local function triplets(n)
1470 if floor(n/100) > 0 then
1471 l = l + 1 ; t[l] = words[floor(n/100)]
1472 l = l + 1 ; t[l] = words[100]
1473 end
1474 if n%100 > 20 then
1475 l = l + 1 ; t[l] = words[n%100-n%10]
1476 if n%10 > 0 then
1477 l = l + 1 ; t[l] = words[n%10]
1478 end
1479 elseif n%100 > 0 then
1480 l = l + 1 ; t[l] = words[n%100]
1481 end
1482 end
1483
1484
1485 for i=15,3,-3 do
1486 local triplet = floor(n/10^i)%10^3
1487 if triplet > 0 then
1488
1489 if i > 3 and triplet == 1 then
1490 l = l + 1 ; t[l] = "en"
1491 else
1492 triplets(triplet)
1493 end
1494
1495 l = l + 1 ; t[l] = words[10^i]
1496 if i > 3 and triplet > 1 then
1497 l = l + 1 ; t[l] = "er"
1498 end
1499 end
1500 end
1501
1502 n = n%1000
1503 if n > 0 then
1504 triplets(n)
1505 end
1506 t = concat(t," ")
1507
1508 if n < 10^6 then
1509 t = gsub(t,"%stusen%s","tusen")
1510 t = gsub(t,"etttusen","ettusen")
1511 end
1512 return t
1513 end
1514 end
1515
1516 data.swedish = {
1517 words = words,
1518 translate = translate,
1519 }
1520
1521 data.sv = data.swedish
1522
1523end
1524
1525
1526
1527function converters.verbose.translate(n,language,connector)
1528 local t = language and data[language]
1529 return t and t.translate(n,connector) or n
1530end
1531
1532local function verbose(n,language,connector)
1533 local t = language and data[language]
1534 context(t and t.translate(n,connector) or n)
1535end
1536
1537implement {
1538 name = "verbose",
1539 actions = verbose,
1540 arguments = { "integer", "string", "string" }
1541}
1542
1543
1544
1545
1546local whitespace = lpegpatterns.whitespace
1547local word = lpegpatterns.utf8uppercharacter^-1 * (1-whitespace)^1
1548local pattern_one = Cs( whitespace^0 * word^-1 * P(1)^0)
1549local pattern_all = Cs((whitespace^1 + word)^1)
1550
1551function converters.word (s) return s end
1552function converters.words(s) return s end
1553
1554local function Word (s) return lpegmatch(pattern_one,s) or s end
1555local function Words(s) return lpegmatch(pattern_all,s) or s end
1556
1557converters.Word = Word
1558converters.Words = Words
1559
1560converters.upper = characters.upper
1561converters.lower = characters.lower
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575local v_day = variables.day
1576local v_year = variables.year
1577local v_month = variables.month
1578local v_weekday = variables.weekday
1579local v_referral = variables.referral
1580local v_space = variables.space
1581
1582local v_MONTH = upper(v_month)
1583local v_WEEKDAY = upper(v_weekday)
1584
1585local convert = converters.convert
1586
1587local days = {
1588 "sunday",
1589 "monday",
1590 "tuesday",
1591 "wednesday",
1592 "thursday",
1593 "friday",
1594 "saturday",
1595}
1596
1597local months = {
1598 "january",
1599 "february",
1600 "march",
1601 "april",
1602 "may",
1603 "june",
1604 "july",
1605 "august",
1606 "september",
1607 "october",
1608 "november",
1609 "december",
1610}
1611
1612local monthmnems = {
1613
1614}
1615
1616local daymnems = {
1617
1618}
1619
1620setmetatableindex(days, function(t,k) return "unknown" end)
1621setmetatableindex(daymnems, function(t,k) return days[k] .. ":mnem" end)
1622setmetatableindex(months, function(t,k) return "unknown" end)
1623setmetatableindex(monthmnems, function(t,k) return months[k] .. ":mnem" end)
1624
1625do
1626
1627 local function dayname(n)
1628 ctx_labeltext(days[n])
1629 end
1630
1631 local function daymnem(n)
1632 ctx_labeltext(daymnems[n])
1633 end
1634
1635 local function weekdayname(day,month,year)
1636 ctx_labeltext(days[weekday(day,month,year)])
1637 end
1638
1639 local function monthname(n)
1640 ctx_labeltext(months[n])
1641 end
1642
1643 local function monthmnem(n)
1644 ctx_labeltext(monthmnems[n])
1645 end
1646
1647 implement {
1648 name = "dayname",
1649 actions = dayname,
1650 arguments = "integer",
1651 }
1652
1653 implement {
1654 name = "daymnem",
1655 actions = daymnem,
1656 arguments = "integer",
1657 }
1658
1659 implement {
1660 name = "weekdayname",
1661 actions = weekdayname,
1662 arguments = { "integer", "integer", "integer" }
1663 }
1664
1665 implement {
1666 name = "monthname",
1667 actions = monthname,
1668 arguments = "integer",
1669 }
1670
1671 implement {
1672 name = "monthmnem",
1673 actions = monthmnem,
1674 arguments = "integer",
1675 }
1676
1677
1678
1679 local f_monthlong = formatters["\\monthlong{%s}"]
1680 local f_monthshort = formatters["\\monthshort{%s}"]
1681 local f_daylong = formatters["\\daylong{%s}"]
1682 local f_dayshort = formatters["\\dayshort{%s}"]
1683 local f_weekday = formatters["\\weekday{%s}"]
1684 local f_dayoftheweek = formatters["\\dayoftheweek{%s}{%s}{%s}"]
1685
1686 local function tomonthlong (m) return f_monthlong (tonumber(m) or 1) end
1687 local function tomonthshort(m) return f_monthshort(tonumber(m) or 1) end
1688 local function todaylong (d) return f_daylong (tonumber(d) or 1) end
1689 local function todayshort (d) return f_dayshort (tonumber(d) or 1) end
1690 local function toweekday (d) return f_weekday (tonumber(d) or 1) end
1691
1692 local function todayoftheweek(d,m,y)
1693 return f_dayoftheweek(tonumber(d) or 1,tonumber(m) or 1,tonumber(y) or 2000)
1694 end
1695
1696 addformatter(formatters,"monthlong", [[tomonthlong(%s)]], { tomonthlong = tomonthlong })
1697 addformatter(formatters,"monthshort", [[tomonthshort(%s)]], { tomonthshort = tomonthshort })
1698 addformatter(formatters,"daylong", [[todaylong(%s)]], { todaylong = todaylong })
1699 addformatter(formatters,"dayshort", [[todayshort(%s)]], { todayshort = todayshort })
1700 addformatter(formatters,"weekday", [[toweekday(%s)]], { toweekday = toweekday })
1701 addformatter(formatters,"dayoftheweek",[[todayoftheweek(%s,%s,%s)]],{ todayoftheweek = todayoftheweek })
1702
1703
1704
1705 local function toeyear (e) return osdate("%Y",tonumber(e)) end
1706 local function toemonth (e) return osdate("%m",tonumber(e)) end
1707 local function toeday (e) return osdate("%d",tonumber(e)) end
1708 local function toeminute(e) return osdate("%M",tonumber(e)) end
1709 local function toesecond(e) return osdate("%S",tonumber(e)) end
1710
1711 local function toemonthlong(e)
1712 return f_monthlong(tonumber(osdate("%m",tonumber(e))))
1713 end
1714
1715 local function toemonthshort(e)
1716 return f_monthshort(tonumber(osdate("%m",tonumber(e))))
1717 end
1718
1719 local function toedaylong(e)
1720 return f_datlong(tonumber(osdate("%w",tonumber(e))))
1721 end
1722
1723 local function toedayshort(e)
1724 return f_dayshort(tonumber(osdate("%w",tonumber(e))))
1725 end
1726
1727 local function toeweek(e)
1728 return tostring(tonumber(osdate("%w",tonumber(e)))+1)
1729 end
1730
1731 local function toeweekday(e)
1732 return f_weekday(tonumber(osdate("%w",tonumber(e)))+1)
1733 end
1734
1735 local function toedate(format,e)
1736 return osdate(format,tonumber(e))
1737 end
1738
1739 addformatter(formatters,"eyear", [[toeyear(%s)]], { toeyear = toeyear })
1740 addformatter(formatters,"emonth", [[toemonth(%s)]], { toemonth = toemonth })
1741 addformatter(formatters,"eday", [[toeday(%s)]], { toeday = toeday })
1742 addformatter(formatters,"eweek", [[toeweek(%s)]], { toeweek = toeweek })
1743 addformatter(formatters,"eminute", [[toeminute(%s)]], { toeminute = toeminute })
1744 addformatter(formatters,"esecond", [[toesecond(%s)]], { toesecond = toesecond })
1745
1746 addformatter(formatters,"emonthlong", [[toemonthlong(%s)]], { toemonthlong = toemonthlong })
1747 addformatter(formatters,"emonthshort", [[toemonthshort(%s)]], { toemonthshort = toemonthshort })
1748 addformatter(formatters,"edaylong", [[toedaylong(%s)]], { toedaylong = toedaylong })
1749 addformatter(formatters,"edayshort", [[toedayshort(%s)]], { toedayshort = toedayshort })
1750 addformatter(formatters,"eweekday", [[toeweekday(%s)]], { toeweekday = toeweekday })
1751
1752 addformatter(formatters,"edate", [[toedate(%s,%s)]], { toedate = toedate })
1753
1754end
1755
1756
1757
1758
1759
1760
1761local spaced = {
1762 [v_year] = true,
1763 [v_month] = true,
1764 [v_MONTH] = true,
1765 [v_day] = true,
1766 [v_weekday] = true,
1767 [v_WEEKDAY] = true,
1768}
1769
1770local dateconverters = {
1771 ["hebrew:to"] = gregorian_to_hebrew,
1772 ["jalali:to"] = gregorian_to_jalali,
1773 ["jalali:from"] = jalali_to_gregorian,
1774}
1775
1776local variants = {
1777 mnem = {
1778 month = monthmnems,
1779 day = daymnems,
1780 },
1781 hebrew = {
1782 month = setmetatableindex(function(t,k) return months[k] .. ":hebrew" end),
1783 day = setmetatableindex(function(t,k) return days [k] .. ":hebrew" end),
1784 },
1785 jalali = {
1786 month = setmetatableindex(function(t,k) return months[k] .. ":jalali" end),
1787 day = setmetatableindex(function(t,k) return days [k] .. ":jalali" end),
1788 },
1789}
1790
1791do
1792
1793 local function currentdate(str,currentlanguage,year,month,day)
1794 local list = utilities.parsers.settings_to_array(str)
1795 local splitlabel = languages.labels.split or string.itself
1796
1797
1798
1799 local auto = true
1800 if currentlanguage == "" then
1801 currentlanguage = false
1802 end
1803 for i=1,#list do
1804 local entry = list[i]
1805 local convert = dateconverters[entry]
1806 if convert then
1807 year, month, day = convert(year,month,day)
1808 else
1809 local tag, plus = splitlabel(entry)
1810 local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false
1811 if not tag then
1812 tag = entry
1813 elseif plus == "+" or plus == "ord" then
1814 ordinal = true
1815 elseif plus == "++" or plus == "highord" then
1816 ordinal = true
1817 highordinal = true
1818 elseif plus then
1819 mnemonic = variants[plus]
1820 end
1821 if not auto and spaced[tag] then
1822 ctx_space()
1823 end
1824 auto = false
1825 if tag == v_year or tag == "y" or tag == "Y" then
1826 if plus then
1827 plus = converters[plus]
1828 end
1829 if plus then
1830 context(plus(year))
1831 elseif currentlanguage == false then
1832 context(year)
1833 else
1834 ctx_convertnumber(v_year,year)
1835 end
1836 elseif tag == "yy" or tag == "YY" then
1837 context("%02i",year % 100)
1838 elseif tag == v_month or tag == "m" then
1839 if currentlanguage == false then
1840 context(Word(months[month]))
1841 else
1842 if type(mnemonic) == "table" then
1843 mnemonic = mnemonic.month
1844 end
1845 if mnemonic then
1846 ctx_labeltext(variables[mnemonic[month]])
1847 else
1848 ctx_labeltext(variables[months[month]])
1849 end
1850 end
1851 elseif tag == v_MONTH then
1852 if currentlanguage == false then
1853 context(Word(variables[months[month]]))
1854 else
1855 if type(mnemonic) == "table" then
1856 mnemonic = mnemonic.month
1857 end
1858 if mnemonic then
1859 ctx_LABELTEXT(variables[mnemonic[month]])
1860 else
1861 ctx_LABELTEXT(variables[months[month]])
1862 end
1863 end
1864 elseif tag == "mm" then
1865 context("%02i",month)
1866 elseif tag == "M" then
1867 context(month)
1868 elseif tag == v_day or tag == "d" then
1869 if plus then
1870 plus = converters[plus]
1871 end
1872 if plus then
1873 context(plus(day))
1874 elseif currentlanguage == false then
1875 context(day)
1876 else
1877 ctx_convertnumber(v_day,day)
1878 end
1879 whatordinal = day
1880 elseif tag == "dd" then
1881 context("%02i",day)
1882 whatordinal = day
1883 elseif tag == "D" then
1884 context(day)
1885 whatordinal = day
1886 elseif tag == v_weekday or tag == "w" then
1887 local wd = weekday(day,month,year)
1888 if currentlanguage == false then
1889 context(Word(days[wd]))
1890 else
1891 if type(mnemonic) == "table" then
1892 mnemonic = mnemonic.day
1893 end
1894 if mnemonic then
1895 ctx_labeltext(variables[mnemonic[wd]])
1896 else
1897 ctx_labeltext(variables[days[wd]])
1898 end
1899 end
1900 elseif tag == v_WEEKDAY then
1901 local wd = weekday(day,month,year)
1902 if currentlanguage == false then
1903 context(Word(days[wd]))
1904 else
1905 if type(mnemonic) == "table" then
1906 mnemonic = mnemonic.day
1907 end
1908 if mnemonic then
1909 ctx_LABELTEXT(variables[mnemonic[wd]])
1910 else
1911 ctx_LABELTEXT(variables[days[wd]])
1912 end
1913 end
1914 elseif tag == "W" then
1915 context(weekday(day,month,year))
1916 elseif tag == v_referral then
1917 context("%04i%02i%02i",year,month,day)
1918 elseif tag == v_space or tag == "\\ " then
1919 ctx_space()
1920 auto = true
1921 elseif tag ~= "" then
1922 context(tag)
1923 auto = true
1924 end
1925 if ordinal and whatordinal then
1926 if currentlanguage == false then
1927
1928 else
1929 context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage))
1930 end
1931 end
1932 end
1933 end
1934 end
1935
1936 implement {
1937 name = "currentdate",
1938 arguments = { "string", "string", "string", "integer", "integer", "integer" },
1939 actions = function(pattern,default,language,year,month,day)
1940 currentdate(
1941 pattern == "" and default or pattern,
1942 language == "" and false or language,
1943 year, month, day
1944 )
1945 end,
1946 }
1947
1948 local function todate(s,y,m,d)
1949 if y or m or d then
1950 return formatters["\\date[y=%s,m=%s,d=%s][%s]\\relax"](y or "",m or "",d or "",s or "")
1951 else
1952 return formatters["\\currentdate[%s]\\relax"](s)
1953 end
1954 end
1955
1956 addformatter(formatters,"date", [[todate(...)]], { todate = todate })
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966end
1967
1968implement {
1969 name = "unihex",
1970 arguments = "integer",
1971 actions = { formatters["U+%05X"], context },
1972}
1973
1974
1975
1976local n = R("09")^1 / tonumber
1977
1978local p = Cf( Ct("")
1979
1980 * Cg(Cc("year") * n)
1981 * S("-/")^-1
1982 * Cg(Cc("month") * (n + Cc(1)))
1983 * S("-/")^-1
1984 * Cg(Cc("day") * (n + Cc(1)))
1985
1986 * (
1987 whitespace^0
1988 * P("T")^-1
1989 * whitespace^0
1990 * Cg(Cc("hour") * n)
1991 * P(":")^-1
1992 * Cg(Cc("min") * n)
1993 * P(":")^-1
1994 * Cg(Cc("sec") * (n + Cc(0)))
1995 )^-1
1996
1997 * (
1998 whitespace^0
1999 * Cg(Cc("tzs") * (P("+") * Cc(1) + P("-") * Cc(-1) + Cc(1)))
2000 * whitespace^0
2001 * Cg(Cc("tzh") * n)
2002 * P(":")^-1
2003 * Cg(Cc("tzm") * (n + Cc(0)))
2004 )^-1
2005 , rawset)
2006
2007function converters.totime(s)
2008 if not s then
2009 return
2010 elseif type(s) == "table" then
2011 return s
2012 elseif type(s) == "string" then
2013 local t = lpegmatch(p,s)
2014 if not t then
2015 logs.report("system","invalid time specification %a",s)
2016 elseif t.tzh then
2017 local localtzh, localtzm = ostimezone(true)
2018 t.hour = t.hour + localtzh - t.tzs * t.tzh
2019 t.min = t.min + localtzm - t.tzs * t.tzm
2020 end
2021 return t
2022 end
2023 local n = tonumber(s)
2024 if n and n >= 0 then
2025 return osdate("*t",n)
2026 end
2027end
2028
2029function converters.settime(t)
2030 if type(t) ~= "table" then
2031 t = converters.totime(t)
2032 end
2033 if t then
2034 texset("year", t.year or 1000)
2035 texset("month", t.month or 1)
2036 texset("day", t.day or 1)
2037 texset("time", (t.hour or 0) * 60 + (t.min or 0))
2038 end
2039end
2040
2041
2042
2043local d_one = lpegpatterns.digit
2044local d_two = d_one * d_one
2045local d_three = d_two * d_one
2046local d_four = d_three * d_one
2047local d_split = P(-1) + Carg(2) * (lpegpatterns.period /"")
2048
2049local d_spaced = (Carg(1) * d_three)^1
2050
2051local digitized_1 = Cs ( (
2052 d_three * d_spaced * d_split +
2053 d_two * d_spaced * d_split +
2054 d_one * d_spaced * d_split +
2055 P(1)
2056 )^1 )
2057
2058local p_fourbefore = d_four * d_split
2059local p_fourafter = d_four * P(-1)
2060
2061local p_beforesplit = d_three * d_spaced^0 * d_split
2062 + d_two * d_spaced^0 * d_split
2063 + d_one * d_spaced^0 * d_split
2064 + d_one * d_split
2065
2066local p_aftersplit = p_fourafter
2067 + d_three * d_spaced
2068 + d_two * d_spaced
2069 + d_one * d_spaced
2070
2071local digitized_2 = Cs (
2072 p_fourbefore * (p_aftersplit^0) +
2073 p_beforesplit * ((p_aftersplit + d_one^1)^0)
2074 )
2075
2076local p_fourbefore = d_four * d_split
2077local p_fourafter = d_four
2078local d_spaced = (Carg(1) * (d_three + d_two + d_one))^1
2079local p_aftersplit = p_fourafter * P(-1)
2080 + d_three * d_spaced * P(1)^0
2081 + d_one^1
2082
2083local digitized_3 = Cs((p_fourbefore + p_beforesplit) * p_aftersplit^0)
2084
2085local digits_space = utfchar(0x2008)
2086
2087local splitmethods = {
2088 digitized_1,
2089 digitized_2,
2090 digitized_3,
2091}
2092
2093local replacers = table.setmetatableindex(function(t,k)
2094 local v = lpeg.replacer(".",k)
2095 t[k] = v
2096 return v
2097end)
2098
2099function converters.spaceddigits(settings,data)
2100 local data = tostring(data or settings.data or "")
2101 if data ~= "" then
2102 local method = settings.method
2103 local split = splitmethods[tonumber(method) or 1]
2104 if split then
2105 local symbol = settings.symbol
2106 local separator = settings.separator
2107 if not symbol or symbol == "" then
2108 symbol = "."
2109 end
2110 if type(separator) ~= "string" or separator == "" then
2111 separator = digits_space
2112 end
2113 local result = lpegmatch(split,data,1,separator,symbol)
2114 if not result and symbol ~= "." then
2115 result = lpegmatch(replacers[symbol],data)
2116 end
2117 if result then
2118
2119 return result
2120 end
2121 end
2122 end
2123 return str
2124end
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166implement {
2167 name = "spaceddigits",
2168 actions = { converters.spaceddigits, context },
2169 arguments = {
2170 {
2171 { "symbol" },
2172 { "separator" },
2173 { "data" },
2174 { "method" },
2175 }
2176 }
2177}
2178
2179local function field(n) return context(osdate("*t")[n]) end
2180
2181implement { name = "actualday", public = true, actions = function() field("day") end }
2182implement { name = "actualmonth", public = true, actions = function() field("month") end }
2183implement { name = "actualyear", public = true, actions = function() field("year") end }
2184
2185implement {
2186 name = "uuid",
2187 public = true,
2188 actions = { os.uuid, context },
2189}
2190 |