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