Dokumentation für das Modul Sort[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]
Hinweise
local Sort = { suite  = "Sort",                serial = "2019-10-29",                item   = 24205172 } --[=[ Sort ]=] local Failsafe  = Sort local GlobalMod = Sort    local foreignModule = function ( access, advanced, append, alt, alert )     -- Fetch global module     -- Precondition:     --     access    -- string, with name of base module     --     advanced  -- true, for require(); else mw.loadData()     --     append    -- string, with subpage part, if any; or false     --     alt       -- number, of wikidata item of root; or false     --     alert     -- true, for throwing error on data problem     -- Postcondition:     --     Returns whatever, probably table     -- 2019-10-29     local storage = access     local finer = function ()                       if append then                           storage = string.format( "%s/%s",                                                    storage,                                                    append )                       end                   end     local fun, lucky, r, suited     if advanced then         fun = require     else         fun = mw.loadData     end     GlobalMod.globalModules = GlobalMod.globalModules or { }     suited = GlobalMod.globalModules[ access ]     if not suited then         finer()         lucky, r = pcall( fun,  "Module:" .. storage )     end     if not lucky then         if not suited  and            type( alt ) == "number"  and            alt > 0 then             suited = string.format( "Q%d", alt )             suited = mw.wikibase.getSitelink( suited )             GlobalMod.globalModules[ access ] = suited or true         end         if type( suited ) == "string" then             storage = suited             finer()             lucky, r = pcall( fun, storage )         end         if not lucky and alert then             error( "Missing or invalid page: " .. storage, 0 )         end     end     return r end -- foreignModule()    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 collate, post, pre         if apply then             collate = apply         else             collate = "uni"         end         if type( collate ) == "string" then             collate = foreignModule( Sort.suite,                                      false,                                      collate,                                      Sort.item )         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                     tmp = foreignModule( Sort.suite,                                          false,                                          variants[ i ],                                          Sort.item )                     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 type( tmp ) == "string" then                         collate = tmp                         break    -- for i                     else                         collate = "Invalid table " .. variants[ i ]                         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 >= 0x0300  and  k <= 0x0362 )   or                        ( k >= 0x1AB0  and  k <= 0x1AFF )   or                        ( k >= 0x1DC0  and  k <= 0x1DFF )   or                        ( k >= 0xFE20  and  k <= 0xFE2F ) 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()    Failsafe.failsafe = function ( atleast )     -- Retrieve versioning and check for compliance     -- Precondition:     --     atleast  -- string, with required version or "wikidata" or "~"     --                 or false     -- Postcondition:     --     Returns  string  -- with queried version, also if problem     --              false   -- if appropriate     -- 2019-10-15     local last  = ( atleast == "~" )     local since = atleast     local r     if last  or  since == "wikidata" then         local item = Failsafe.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 seek = Failsafe.serialProperty or "P348"                 local vsn  = entity:formatPropertyValues( seek )                 if type( vsn ) == "table"  and                    type( vsn.value ) == "string"  and                    vsn.value ~= "" then                     if last  and  vsn.value == Failsafe.serial then                         r = false                     else                         r = vsn.value                     end                 end             end         end     end     if type( r ) == "nil" then         if not since  or  since <= Failsafe.serial then             r = Failsafe.serial         else             r = false         end     end     return r end -- Failsafe.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 Failsafe.failsafe( since )  or  "" end -- p.failsafe()    p.Sort = function ()     return Sort end -- p.Sort  return p