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