Zum Inhalt springen

Modul:Sort

Aus Wikipedia
Version vom Howan Hansi (Dischkrian | Beidräg) um 18:45 Uhr am 4. Jénner 2019.
(Unterschiad) ← Nextejtand Version | Aktuelle Version (Unterschiad) | Neiare Version → (Unterschiad)
Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus

Weiterleitung der Diskussionsseite fehlt
Diese Seite ist eine lokale Kopie aus de.wikipedia.org und von dort zu aktualisieren.

Versionsbezeichnung auf WikiData: 2024-06-14 Updating notwendig (lokal: 2018-03-22)


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