summaryrefslogtreecommitdiff
path: root/tex/context/base/core-con.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/core-con.lua')
-rw-r--r--tex/context/base/core-con.lua330
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"
+}