diff options
Diffstat (limited to 'tex/context/base/core-con.lua')
-rw-r--r-- | tex/context/base/core-con.lua | 330 |
1 files changed, 255 insertions, 75 deletions
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua index dad24a7d4..37942ae71 100644 --- a/tex/context/base/core-con.lua +++ b/tex/context/base/core-con.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['core-con'] = { license = "see context related readme files" } +-- todo: split into char-lan.lua and core-con.lua + --[[ldx-- <p>This module implements a bunch of conversions. Some are more efficient than their <l n='tex'/> counterpart, some are even @@ -14,14 +16,15 @@ slower but look nicer this way.</p> <p>Some code may move to a module in the language namespace.</p> --ldx]]-- -local command, context = commands, context - local floor, date, time, concat = math.floor, os.date, os.time, table.concat local lower, rep, match = string.lower, string.rep, string.match local utfchar, utfbyte = utf.char, utf.byte local tonumber, tostring = tonumber, tostring +local P, C, Cs, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.match local context = context +local commands = commands +local implement = interfaces.implement local settings_to_array = utilities.parsers.settings_to_array local allocate = utilities.storage.allocate @@ -37,9 +40,8 @@ local languages = languages converters.number = tonumber converters.numbers = tonumber -function commands.number(n) context(n) end - -commands.numbers = commands.number +implement { name = "number", actions = context } +implement { name = "numbers", actions = context } -- to be reconsidered ... languages namespace here, might become local plus a register command @@ -59,6 +61,14 @@ local counters = allocate { 0x006F, 0x0070, 0x0072, 0x0073, 0x0161, 0x0074, 0x0075, 0x0076, 0x007A, 0x017E }, + ['spanish'] = { + 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, + 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, + 0x006B, 0x006C, 0x006D, 0x006E, 0x00F1, + 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, + 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, + 0x0079, 0x007A + }, ['greek'] = { -- this should be the lowercase table -- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, -- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, @@ -126,13 +136,30 @@ local counters = allocate { languages.counters = counters -counters['ar'] = counters['arabic'] -counters['gr'] = counters['greek'] -counters['g'] = counters['greek'] -counters['sl'] = counters['slovenian'] -counters['kr'] = counters['korean'] -counters['kr-p'] = counters['korean-parent'] -counters['kr-c'] = counters['korean-circle'] +counters['ar'] = counters['arabic'] +counters['gr'] = counters['greek'] +counters['g'] = counters['greek'] +counters['sl'] = counters['slovenian'] +counters['es'] = counters['spanish'] +counters['kr'] = counters['korean'] +counters['kr-p'] = counters['korean-parent'] +counters['kr-c'] = counters['korean-circle'] + +counters['thainumerals'] = counters['thai'] +counters['devanagarinumerals'] = counters['devanagari'] +counters['gurmurkhinumerals'] = counters['gurmurkhi'] +counters['gujaratinumerals'] = counters['gujarati'] +counters['tibetannumerals'] = counters['tibetan'] +counters['greeknumerals'] = counters['greek'] +counters['arabicnumerals'] = counters['arabic'] +counters['persiannumerals'] = counters['persian'] +counters['arabicexnumerals'] = counters['persian'] +counters['koreannumerals'] = counters['korean'] +counters['koreanparentnumerals'] = counters['korean-parent'] +counters['koreancirclenumerals'] = counters['korean-circle'] + +counters['sloveniannumerals'] = counters['slovenian'] +counters['spanishnumerals'] = counters['spanish'] local fallback = utfbyte('0') @@ -177,6 +204,8 @@ converters.maxchrs = maxchrs local lowercharacter = characters.lcchars local uppercharacter = characters.ucchars +local defaultcounter = counters.default + local function do_alphabetic(n,mapping,mapper,t) -- todo: make zero based variant (initial n + 1) if not t then t = { } @@ -193,14 +222,17 @@ local function do_alphabetic(n,mapping,mapper,t) -- todo: make zero based varian end end -function converters.alphabetic(n,code) - return do_alphabetic(n,counters[code] or counters.default,lowercharacter) +local function alphabetic(n,code) + return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,lowercharacter) end -function converters.Alphabetic(n,code) - return do_alphabetic(n,counters[code] or counters.default,uppercharacter) +local function Alphabetic(n,code) + return do_alphabetic(n,code and code ~= "" and counters[code] or defaultcounter,uppercharacter) end +converters.alphabetic = alphabetic +converters.Alphabetic = Alphabetic + local lower_offset = 96 local upper_offset = 64 @@ -209,12 +241,18 @@ function converters.Character (n) return chr (n,upper_offset) end function converters.characters(n) return chrs(n,lower_offset) end function converters.Characters(n) return chrs(n,upper_offset) end -function commands.alphabetic(n,c) context(do_alphabetic(n,counters[c],lowercharacter)) end -function commands.Alphabetic(n,c) context(do_alphabetic(n,counters[c],uppercharacter)) end -function commands.character (n) context(chr (n,lower_offset)) end -function commands.Character (n) context(chr (n,upper_offset)) end -function commands.characters(n) context(chrs(n,lower_offset)) end -function commands.Characters(n) context(chrs(n,upper_offset)) end +converters['a'] = converters.characters +converters['A'] = converters.Characters +converters['AK'] = converters.Characters +converters['KA'] = converters.Characters + +implement { name = "alphabetic", actions = { alphabetic, context }, arguments = { "integer", "string" } } +implement { name = "Alphabetic", actions = { Alphabetic, context }, arguments = { "integer", "string" } } + +implement { name = "character", actions = { chr, context }, arguments = { "integer", lower_offset } } +implement { name = "Character", actions = { chr, context }, arguments = { "integer", upper_offset } } +implement { name = "characters", actions = { chrs, context }, arguments = { "integer", lower_offset } } +implement { name = "Characters", actions = { chrs, context }, arguments = { "integer", upper_offset } } local weekday = os.weekday -- moved to l-os local isleapyear = os.isleapyear -- moved to l-os @@ -240,20 +278,22 @@ converters.leapyear = leapyear converters.nofdays = nofdays converters.textime = textime -function commands.weekday (day,month,year) context(weekday (day,month,year)) end -function commands.leapyear(year) context(leapyear(year)) end -- rather useless, only for ifcase -function commands.nofdays (year,month) context(nofdays (year,month)) end - -function commands.year () context(date("%Y")) end -function commands.month () context(date("%m")) end -function commands.hour () context(date("%H")) end -function commands.minute () context(date("%M")) end -function commands.second () context(date("%S")) end -function commands.textime() context(textime()) end - -function commands.doifleapyearelse(year) - commands.doifelse(isleapyear(year)) -end +implement { name = "weekday", actions = { weekday, context }, arguments = { "integer", "integer", "integer" } } +implement { name = "leapyear", actions = { leapyear, context }, arguments = { "integer" } } +implement { name = "nofdays", actions = { nofdays, context }, arguments = { "integer", "integer" } } + +implement { name = "year", actions = { date, context }, arguments = "'%Y'" } +implement { name = "month", actions = { date, context }, arguments = "'%m'" } +implement { name = "hour", actions = { date, context }, arguments = "'%H'" } +implement { name = "minute", actions = { date, context }, arguments = "'%M'" } +implement { name = "second", actions = { date, context }, arguments = "'%S'" } +implement { name = "textime", actions = { textime, context } } + +implement { + name = "doifelseleapyear", + actions = { isleapyear, commands.doifelse }, + arguments = "integer" +} local roman = { { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' }, @@ -273,8 +313,24 @@ converters.toroman = toroman converters.Romannumerals = toroman converters.romannumerals = function(n) return lower(toroman(n)) end -function commands.romannumerals(n) context(lower(toroman(n))) end -function commands.Romannumerals(n) context( toroman(n)) end +converters['i'] = converters.romannumerals +converters['I'] = converters.Romannumerals +converters['r'] = converters.romannumerals +converters['R'] = converters.Romannumerals +converters['KR'] = converters.Romannumerals +converters['RK'] = converters.Romannumerals + +implement { + name = "romannumerals", + actions = { toroman, lower, context }, + arguments = "integer", +} + +implement { + name = "Romannumerals", + actions = { toroman, context }, + arguments = "integer", +} --~ local small = { --~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631 @@ -327,8 +383,17 @@ converters.toabjad = toabjad function converters.abjadnumerals (n) return toabjad(n,false) end function converters.abjadnodotnumerals(n) return toabjad(n,true ) end -function commands.abjadnumerals (n) context(toabjad(n,false)) end -function commands.abjadnodotnumerals(n) context(toabjad(n,true )) end +implement { + name = "abjadnumerals", + actions = { toabjad, context }, + arguments = { "integer", false } +} + +implement { + name = "abjadnodotnumerals", + actions = { toabjad, context }, + arguments = { "integer", true } +} local vector = { normal = { @@ -470,32 +535,59 @@ end converters.tochinese = tochinese -function converters.chinesenumerals (n) return tochinese(n,"normal") end -function converters.chinesecapnumerals(n) return tochinese(n,"cap" ) end -function converters.chineseallnumerals(n) return tochinese(n,"all" ) end +function converters.chinesenumerals (n,how) return tochinese(n,how or "normal") end +function converters.chinesecapnumerals(n) return tochinese(n,"cap") end +function converters.chineseallnumerals(n) return tochinese(n,"all") end + +converters['cn'] = converters.chinesenumerals +converters['cn-c'] = converters.chinesecapnumerals +converters['cn-a'] = converters.chineseallnumerals + +implement { + name = "chinesenumerals", + actions = { tochinese, context }, + arguments = { "integer", "string" } +} + +-- this is a temporary solution: we need a better solution when we have +-- more languages + +function converters.spanishnumerals(n) return alphabetic(n,"es") end +function converters.Spanishnumerals(n) return Alphabetic(n,"es") end +function converters.sloviannumerals(n) return alphabetic(n,"sl") end +function converters.Sloviannumerals(n) return Alphabetic(n,"sl") end + +converters['characters:es'] = converters.spanishnumerals +converters['characters:sl'] = converters.sloveniannumerals -function commands.chinesenumerals (n) context(tochinese(n,"normal")) end -function commands.chinesecapnumerals(n) context(tochinese(n,"cap" )) end -function commands.chineseallnumerals(n) context(tochinese(n,"all" )) end +converters['Characters:es'] = converters.Spanishnumerals +converters['Characters:sl'] = converters.Sloveniannumerals converters.sequences = converters.sequences or { } local sequences = converters.sequences storage.register("converters/sequences", sequences, "converters.sequences") -function converters.define(name,set) +function converters.define(name,set) -- ,language) + -- if language then + -- name = name .. ":" .. language + -- end sequences[name] = settings_to_array(set) end -commands.defineconversion = converters.define +implement { + name = "defineconversion", + actions = converters.define, + arguments = { "string", "string" } +} -local function convert(method,n) -- todo: language - local converter = converters[method] +local function convert(method,n,language) + local converter = language and converters[method..":"..language] or converters[method] if converter then return converter(n) else local lowermethod = lower(method) - local linguistic = counters[lowermethod] + local linguistic = counters[lowermethod] if linguistic then return do_alphabetic(n,linguistic,lowermethod == method and lowercharacter or uppercharacter) end @@ -507,18 +599,29 @@ local function convert(method,n) -- todo: language else return sequence[n] end - else - return n end + return n end end converters.convert = convert -function commands.checkedconversion(method,n) - context(convert(method,n)) +local function valid(method,language) + return converters[method..":"..language] or converters[method] or sequences[method] end +implement { + name = "doifelseconverter", + actions = { valid, commands.doifelse }, + arguments = { "string", "string" } +} + +implement { + name = "checkedconversion", + actions = { convert, context }, + arguments = { "string", "integer" } +} + -- Well, since the one asking for this didn't test it the following code is not -- enabled. -- @@ -692,7 +795,7 @@ function converters.ordinal(n,language) return t and t(n) end -function commands.ordinal(n,language) +local function ctxordinal(n,language) local t = language and ordinals[language] local o = t and t(n) context(n) @@ -701,7 +804,11 @@ function commands.ordinal(n,language) end end --- verbose numbers +implement { + name = "ordinal", + actions = ctxordinal, + arguments = { "integer", "string" } +} -- verbose numbers @@ -865,7 +972,7 @@ local words = { [900] = "novecientos", [1000] = "mil", [1000^2] = "millón", - [1000^3] = "mil millónes", + [1000^3] = "mil millones", [1000^4] = "billón", } @@ -945,11 +1052,43 @@ function converters.verbose.translate(n,language) return t and t.translate(n) or n end -function commands.verbose(n,language) +local function verbose(n,language) local t = language and data[language] context(t and t.translate(n) or n) end +implement { + name = "verbose", + actions = verbose, + arguments = { "integer", "string" } +} + +-- These are just helpers but not really for the tex end. Do we have to +-- use translate here? + +local whitespace = lpeg.patterns.whitespace +local word = lpeg.patterns.utf8uppercharacter^-1 * (1-whitespace)^1 +local pattern_one = Cs( whitespace^0 * word^-1 * P(1)^0) +local pattern_all = Cs((whitespace^1 + word)^1) + +function converters.word (s) return s end -- dummies for typos +function converters.words(s) return s end -- dummies for typos +function converters.Word (s) return lpegmatch(pattern_one,s) or s end +function converters.Words(s) return lpegmatch(pattern_all,s) or s end + +converters.upper = characters.upper +converters.lower = characters.lower + +-- print(converters.Word("foo bar")) +-- print(converters.Word(" foo bar")) +-- print(converters.Word("123 foo bar")) +-- print(converters.Word(" 123 foo bar")) + +-- print(converters.Words("foo bar")) +-- print(converters.Words(" foo bar")) +-- print(converters.Words("123 foo bar")) +-- print(converters.Words(" 123 foo bar")) + -- -- local v_day = variables.day @@ -986,33 +1125,60 @@ local months = { -- not variables.january "december", } -function commands.dayname(n) - context.labeltext(days[n] or "unknown") +local function dayname(n) + return days[n] or "unknown" end -function commands.weekdayname(day,month,year) - context.labeltext(days[weekday(day,month,year)] or "unknown") +local function weekdayname(day,month,year) + return days[weekday(day,month,year)] or "unknown" end -function commands.monthname(n) - context.labeltext(months[n] or "unknown") +local function monthname(n) + return months[n] or "unknown" end -function commands.monthmnem(n) +local function monthmnem(n) local m = months[n] - context.labeltext(m and (m ..":mnem") or "unknown") + return m and (m ..":mnem") or "unknown" end +implement { + name = "dayname", + actions = { dayname, context.labeltext }, + arguments = "integer", +} + +implement { + name = "weekdayname", + actions = { weekdayname, context.labeltext }, + arguments = { "integer", "integer", "integer" } +} + +implement { + name = "monthname", + actions = { monthname, context.labeltext }, + arguments = { "integer" } +} + +implement { + name = "monthmnem", + actions = { monthmnem, context.labeltext }, + arguments = { "integer" } +} + -- a prelude to a function that we can use at the lua end -- day:ord month:mmem -- j and jj obsolete -function commands.currentdate(str,currentlanguage) -- second argument false : no label +local function currentdate(str,currentlanguage) -- second argument false : no label local list = utilities.parsers.settings_to_array(str) local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right local year, month, day = tex.year, tex.month, tex.day local auto = true + if currentlanguage == "" then + currentlanguage = false + end for i=1,#list do local entry = list[i] local tag, plus = splitlabel(entry) @@ -1038,9 +1204,9 @@ function commands.currentdate(str,currentlanguage) -- second argument false : no if currentlanguage == false then context(months[month] or "unknown") elseif mnemonic then - commands.monthmnem(month) + context.labeltext(monthmnem(month)) else - commands.monthname(month) + context.labeltext(monthname(month)) end elseif tag == "mm" then context("%02i",month) @@ -1050,7 +1216,7 @@ function commands.currentdate(str,currentlanguage) -- second argument false : no if currentlanguage == false then context(days[day] or "unknown") else - context.convertnumber(v_day,day) + context.convertnumber(v_day,day) -- why not direct end whatordinal = day elseif tag == "dd" then @@ -1064,7 +1230,7 @@ function commands.currentdate(str,currentlanguage) -- second argument false : no if currentlanguage == false then context(days[wd] or "unknown") else - commands.dayname(wd) + context.labeltext(days[wd] or "unknown") end elseif tag == "W" then context(weekday(day,month,year)) @@ -1087,6 +1253,20 @@ function commands.currentdate(str,currentlanguage) -- second argument false : no end end -function commands.rawdate(str) - commands.currentdate(str,false) -end +implement { + name = "currentdate", + actions = currentdate, + arguments = { "string", "string" } +} + +implement { + name = "rawdate", + actions = currentdate, + arguments = { "string", false } +} + +implement { + name = "unihex", + actions = { formatters["U+%05X"], context }, + arguments = "integer" +} |