Herzlich Willkommen zum Mitglieder-Wiki von Wikimedia Österreich.
Für ein Benutzerkonto schreibe bitte an verein [at] wikimedia.at
Modul:Sort
Zur Navigation springen
Zur Suche springen
Die Dokumentation für dieses Modul kann unter Modul:Sort/Doku erstellt werden
local Sort = { suite = "Sort", serial = "2018-03-22", item = 24205172 } --[=[ Sort ]=] Sort.lex = function ( adjust, apply, adapt ) -- Build ASCII sortkey for text value -- Precondition: -- adjust -- string to be aligned -- apply -- string or table, with base -- "latin" -- adapt -- string or table, with variation, or false -- "DIN5007m2" -- DIN 5007 mode "2" local r = adjust if adapt or not r:match( "^[ -~]*$" ) then local storage = string.format( "Module:%s/", Sort.suite ) local collate, lucky, post, pre if apply then collate = apply else collate = "uni" end if type( collate ) == "string" then lucky, collate = pcall( mw.loadData, storage .. collate ) end if adapt and type( collate ) == "table" then local variants = type( adapt ) local n if variants == "string" then variants = mw.text.split( adapt, "%s+" ) elseif variants == "table" then variants = adapt else variants = { } end n = #variants if n == 1 and variants[ 1 ] == "" then n = 0 end if n > 0 then local tmp = { } local var for k, v in pairs( collate ) do tmp[ k ] = v end -- for k, v collate = tmp for i = 1, n do lucky, tmp = pcall( mw.loadData, storage .. variants[ i ] ) if type( tmp ) == "table" then var = tmp.single if type( var ) ~= "table" then -- legacy var = tmp end if type( var ) == "table" then for k, v in pairs( var ) do collate[ k ] = v end -- for k, v end var = tmp.pre if type( var ) == "table" then if type( pre ) ~= "table" then pre = { } end for k, v in pairs( var ) do pre[ k ] = v end -- for k, v end var = tmp.post if type( var ) == "table" then if type( post ) ~= "table" then post = { } end for k, v in pairs( var ) do post[ k ] = v end -- for k, v end elseif lucky then collate = "Invalid table " .. variants[ i ] break -- for i else collate = tmp break -- for i end end -- for i end end if type( collate ) == "table" then local k, n, s, start if type( pre ) == "table" then for k, v in pairs( pre ) do r = mw.ustring.gsub( r, k, v ) end -- for k, v end n = mw.ustring.len( r ) for i = n, 1, -1 do k = mw.ustring.codepoint( r, i, i ) if k < 127 then -- ASCII s = ( k < 32 ) -- htab newline whitespace if s then s = " " end elseif (k >= 768 and k <= 866) or (k >= 6832 and k <= 6911) or (k >= 7616 and k <= 7679) or (k >= 65056 and k <= 65071) then -- COMBINING ... s = "" else s = collate[ k ] end if s then if i > 1 then s = mw.ustring.sub( r, 1, i - 1 ) .. s end r = s .. mw.ustring.sub( r, i + 1 ) end end -- for i-- if type( post ) == "table" then for k, v in pairs( post ) do r = mw.ustring.gsub( r, k, v ) end -- for k, v end else r = "**ERROR** Sort.lex ** Submodule unavailable " .. collate end end r = r:gsub( " +", " " ) return r end -- Sort.lex() Sort.num = function ( adjust, ad, at, align, absolute ) -- Build sortkey for heading numerical value -- Precondition: -- adjust -- string to be aligned; leading digits / minus -- ad -- decimal separator; "." or ","; defaults to "." -- at -- thousands group separator; defaults to none -- "," "." "'" -- align -- number of leading zeros / maximum length -- defaults to 15 -- absolute -- negative figures by digits; default: by value -- Postcondition: -- Returns string with sortkey local max = 15 local mid = 46 -- "." local min1 = -1 -- none local min2 = -2 -- none local low = false local last = false local lead = true local source = tostring( adjust ) local sub = "." local suffix = false local n = mw.ustring.len( source ) local r = "" local c if ad then mid = mw.ustring.codepoint( ad, 1, 1 ) end if at then min1, min2 = mw.ustring.codepoint( at, 1, 2 ) end if align then max = align end for i = 1, n do c = mw.ustring.codepoint( source, i, i ) if c > 32 then -- not whitespace if c >= 48 and c <= 57 then -- digits r = string.format( "%s%c", r, c ) max = max - 1 elseif c == min1 or c == min2 then -- group separator elseif c == mid then -- decimal separator for j = i + 1, n do c = mw.ustring.codepoint( source, j, j ) if c >= 48 and c <= 57 then -- digits sub = string.format( "%s%c", sub, c ) elseif c == min1 or c == min2 then -- grouping else i = j break -- for j end i = n end -- for j last = true elseif lead then if c == 45 or c == 8722 then -- minus low = true elseif c ~= 43 then -- plus last = true end else last = true end lead = false elseif not lead then -- whitespace not leading last = true end if last then if i < n then suffix = mw.ustring.sub( source, i ) if c == 69 or c == 101 then -- E e local s = suffix:match( "^[Ee](-?%d+)" ) if s then j = tonumber( s ) sub = sub:sub( 2 ) suffix = suffix:sub( #s + 2 ) if j > 0 then if j > #sub then sub = sub .. string.rep( "0", j - #sub ) end r = r .. sub:sub( 1, j ) sub = sub:sub( j + 1 ) max = max - j elseif j < 0 then j = - j if j > #r then r = string.rep( "0", j - #r ) .. r end sub = r:sub( - j ) .. sub r = r:sub( 1, #r - j ) max = max + j end sub = "." .. sub end end end break -- for i end end -- for i if low then if not absolute then -- complementary value local s = "." local cmpl = function ( str, k ) return 57 - str:byte( k ) end for i = 2, #sub do s = string.format( "%s%d", s, cmpl( sub, i ) ) end -- for i for i = #r, 1, -1 do s = string.format( "%d%s", cmpl( r, i ), s ) end -- for i-- r = s if max > 0 then r = string.rep( "9", max ) .. r end sub = false max = 0 end end if sub then r = r .. sub end if max > 0 then r = string.rep( "0", max ) .. r end if low then r = "-" .. r end if suffix then r = string.format( "%s %s", r, suffix ) end return r end -- Sort.num() Sort.failsafe = function ( assert ) -- Retrieve versioning and check for compliance -- Precondition: -- assert -- string, with required version or "wikidata", -- or false -- Postcondition: -- Returns string with appropriate version, or false local since = assert local r if since == "wikidata" then local item = Sort.item since = false if type( item ) == "number" and item > 0 then local entity = mw.wikibase.getEntity( string.format( "Q%d", item ) ) if type( entity ) == "table" then local vsn = entity:formatPropertyValues( "P348" ) if type( vsn ) == "table" and type( vsn.value) == "string" and vsn.value ~= "" then r = vsn.value end end end end if not r then if not since or since <= Sort.serial then r = Sort.serial else r = false end end return r end -- Sort.failsafe() -- Export local p = { } p.Tlatin = function ( frame ) -- Template::latin -- {{{1}}} -- #invoke -- v -- variant, omitted or "DIN5007m2" local lucky, r = pcall( Sort.lex, frame.args[ 1 ] or frame:getParent().args[ 1 ] or "", "latin", frame.args.v ) return r; end -- p.Tlatin p.Tn = function ( frame ) -- Template::numerical -- {{{1}}} -- #invoke -- d -- decimal separator; defaults to "." -- t -- thousands group separator; defaults to none -- z -- number of leading zeros / maximum length; defaults to 15 -- m -- negative figures by digits; default: by value local lucky, r = pcall( Sort.num, frame.args[ 1 ] or frame:getParent().args[ 1 ] or "", frame.args.d, frame.args.t, tonumber( frame.args.z ), frame.args.m == "1" ) return r; end -- p.Tn p.failsafe = function ( frame ) -- Versioning interface local s = type( frame ) local since if s == "table" then since = frame.args[ 1 ] elseif s == "string" then since = frame end if since then since = mw.text.trim( since ) if since == "" then since = false end end return Sort.failsafe( since ) or "" end -- p.failsafe() p.Sort = function () return Sort end -- p.Sort return p