From f1c3cb9dc199c28cdd2c813eb1ea5c21345125d0 Mon Sep 17 00:00:00 2001
From: Khaled Hosny <khaledhosny@eglug.org>
Date: Mon, 11 Jan 2010 15:15:52 +0200
Subject: Import ConTeX's lua libraries

Replace most of luaextra.lua with a bunch of require() calls and add
renamed (but unmodified) ConTeX lua libraries to the repository.

ConTeXt's l-xml.lua module has been excluded because it depends on a
bunch of other ConTeXt specific modules. Also l-pdfview.lua has been
dropped, I don't know what to use it for.
---
 luaextra.dtx | 857 ++---------------------------------------------------------
 1 file changed, 26 insertions(+), 831 deletions(-)

(limited to 'luaextra.dtx')

diff --git a/luaextra.dtx b/luaextra.dtx
index a6f18fd..e8b83a1 100644
--- a/luaextra.dtx
+++ b/luaextra.dtx
@@ -182,850 +182,45 @@ do
     end
 end
 %    \end{macrocode}
-%
-%    \begin{macro}{string:stripspaces}
-%
-%    A function to strip the spaces at the beginning and at the end of a
-%    string.
-%
-%    \begin{macrocode}
-
-function string:stripspaces()
-    return (self:gsub("^%s*(.-)%s*$", "%1"))
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{string.is boolean}
-%
-%    If the argument is a string describing a boolean, this function returns
-%    the boolean, otherwise it retuns nil.
-%
-%    \begin{macrocode}
-
-function string.is_boolean(str)
-    if type(str) == "string" then
-        if str == "true" or str == "yes" or str == "on" or str == "t" then
-            return true
-        elseif str == "false" or str == "no" or str == "off" or str == "f" then
-            return false
-        end
-    end
-    return nil
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{string.is number}
-%
-%    Returns true if the argument string is a number.
-%
-%    \begin{macrocode}
-
-function string.is_number(str)
-    return str:find("^[%-%+]?[%d]-%.?[%d+]$") == 1
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{lpeg.space and lpeg.newline}
-%
-%    Two small helpers for \texttt{lpeg}, that will certainly be widely used:
-%    spaces and newlines.
-%
+% Initialize \textsf{Kpathsea} library, so that |require()| will use it to
+% locate modules.
 %    \begin{macrocode}
 
-lpeg.space    = lpeg.S(" \t\f\v")
-lpeg.newline  = lpeg.P("\r\n") + lpeg.P("\r") +lpeg.P("\n")
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.fastcopy}
-%
-%    A function copying a table fastly.
-%
-%    \begin{macrocode}
-
-if not table.fastcopy then do
-
-    local type, pairs, getmetatable, setmetatable =
-        type, pairs, getmetatable, setmetatable
-
-    local function fastcopy(old) -- fast one
-        if old then
-            local new = { }
-            for k,v in pairs(old) do
-                if type(v) == "table" then
-                    new[k] = fastcopy(v) -- was just table.copy
-                else
-                    new[k] = v
-                end
-            end
-            local mt = getmetatable(old)
-            if mt then
-                setmetatable(new,mt)
-            end
-            return new
-        else
-            return { }
-        end
-    end
-
-    table.fastcopy = fastcopy
-
-end end
+kpse.set_program_name("luatex")
 
 %    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.copy}
-%
-%    A function copying a table in more cases than fastcopy, for example when
-%    a key is a table.
-%
+% Load the individual modules.
 %    \begin{macrocode}
 
-if not table.copy then do
-
-    local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
-    local function copy(t, tables) -- taken from lua wiki, slightly adapted
-        tables = tables or { }
-        local tcopy = {}
-        if not tables[t] then
-            tables[t] = tcopy
-        end
-        for i,v in pairs(t) do -- brrr, what happens with sparse indexed
-            if type(i) == "table" then
-                if tables[i] then
-                    i = tables[i]
-                else
-                    i = copy(i, tables)
-                end
-            end
-            if type(v) ~= "table" then
-                tcopy[i] = v
-            elseif tables[v] then
-                tcopy[i] = tables[v]
-            else
-                tcopy[i] = copy(v, tables)
-            end
-        end
-        local mt = getmetatable(t)
-        if mt then
-            setmetatable(tcopy,mt)
-        end
-        return tcopy
-    end
-
-    table.copy = copy
-
-end end
+require("luaextra-string.lua")
+require("luaextra-lpeg.lua")
+require("luaextra-boolean.lua")
+require("luaextra-number.lua")
+require("luaextra-math.lua")
+require("luaextra-table.lua")
+require("luaextra-aux.lua")
+require("luaextra-io.lua")
+require("luaextra-os.lua")
+require("luaextra-file.lua")
+require("luaextra-md5.lua")
+require("luaextra-dir.lua")
+require("luaextra-unicode.lua")
+require("luaextra-utils.lua")
+require("luaextra-dimen.lua")
+require("luaextra-url.lua")
+require("luaextra-set.lua")
+require("luaextra-dimen.lua")
 
 %    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.serialize}
-%
-%    A bunch of functions leading to \texttt{table.serialize}.
-%
+% Aliases for backward compatibility.
 %    \begin{macrocode}
 
-function table.sortedkeys(tab)
-    local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
-    for key,_ in pairs(tab) do
-        srt[#srt+1] = key
-        if kind == 3 then
-            -- no further check
-        else
-            local tkey = type(key)
-            if tkey == "string" then
-            --  if kind == 2 then kind = 3 else kind = 1 end
-                kind = (kind == 2 and 3) or 1
-            elseif tkey == "number" then
-            --  if kind == 1 then kind = 3 else kind = 2 end
-                kind = (kind == 1 and 3) or 2
-            else
-                kind = 3
-            end
-        end
-    end
-    if kind == 0 or kind == 3 then
-        table.sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
-    else
-        table.sort(srt)
-    end
-    return srt
-end
-
-do
-    table.serialize_functions = true
-    table.serialize_compact   = true
-    table.serialize_inline    = true
-
-    local function key(k)
-        if type(k) == "number" then -- or k:find("^%d+$") then
-            return "["..k.."]"
-        elseif noquotes and k:find("^%a[%a%d%_]*$") then
-            return k
-        else
-            return '["'..k..'"]'
-        end
-    end
-
-    local function simple_table(t)
-        if #t > 0 then
-            local n = 0
-            for _,v in pairs(t) do
-                n = n + 1
-            end
-            if n == #t then
-                local tt = { }
-                for i=1,#t do
-                    local v = t[i]
-                    local tv = type(v)
-                    if tv == "number" or tv == "boolean" then
-                        tt[#tt+1] = tostring(v)
-                    elseif tv == "string" then
-                        tt[#tt+1] = ("%q"):format(v)
-                    else
-                        tt = nil
-                        break
-                    end
-                end
-                return tt
-            end
-        end
-        return nil
-    end
-
-    local function serialize(root,name,handle,depth,level,reduce,noquotes,indexed)
-        handle = handle or print
-        reduce = reduce or false
-        if depth then
-            depth = depth .. " "
-            if indexed then
-                handle(("%s{"):format(depth))
-            else
-                handle(("%s%s={"):format(depth,key(name)))
-            end
-        else
-            depth = ""
-            local tname = type(name)
-            if tname == "string" then
-                if name == "return" then
-                    handle("return {")
-                else
-                    handle(name .. "={")
-                end
-            elseif tname == "number" then
-                handle("[" .. name .. "]={")
-            elseif tname == "boolean" then
-                if name then
-                    handle("return {")
-                else
-                    handle("{")
-                end
-            else
-                handle("t={")
-            end
-        end
-        if root and next(root) then
-            local compact = table.serialize_compact
-            local inline  = compact and table.serialize_inline
-            local first, last = nil, 0 -- #root cannot be trusted here
-            if compact then
-              for k,v in ipairs(root) do -- NOT: for k=1,#root do (why)
-                    if not first then first = k end
-                    last = last + 1
-                end
-            end
-            for _,k in pairs(table.sortedkeys(root)) do
-                local v = root[k]
-                local t = type(v)
-                if compact and first and type(k) == "number" and k >= first and k <= last then
-                    if t == "number" then
-                        handle(("%s %s,"):format(depth,v))
-                    elseif t == "string" then
-                        if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
-                            handle(("%s %s,"):format(depth,v))
-                        else
-                            handle(("%s %q,"):format(depth,v))
-                        end
-                    elseif t == "table" then
-                        if not next(v) then
-                            handle(("%s {},"):format(depth))
-                        elseif inline then
-                            local st = simple_table(v)
-                            if st then
-                                handle(("%s { %s },"):format(depth,table.concat(st,", ")))
-                            else
-                                serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
-                            end
-                        else
-                            serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
-                        end
-                    elseif t == "boolean" then
-                        handle(("%s %s,"):format(depth,tostring(v)))
-                    elseif t == "function" then
-                        if table.serialize_functions then
-                            handle(('%s loadstring(%q),'):format(depth,string.dump(v)))
-                        else
-                            handle(('%s "function",'):format(depth))
-                        end
-                    else
-                        handle(("%s %q,"):format(depth,tostring(v)))
-                    end
-                elseif k == "__p__" then -- parent
-                    if false then
-                        handle(("%s __p__=nil,"):format(depth))
-                    end
-                elseif t == "number" then
-                    handle(("%s %s=%s,"):format(depth,key(k),v))
-                elseif t == "string" then
-                    if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
-                        handle(("%s %s=%s,"):format(depth,key(k),v))
-                    else
-                        handle(("%s %s=%q,"):format(depth,key(k),v))
-                    end
-                elseif t == "table" then
-                    if not next(v) then
-                        handle(("%s %s={},"):format(depth,key(k)))
-                    elseif inline then
-                        local st = simple_table(v)
-                        if st then
-                            handle(("%s %s={ %s },"):format(depth,key(k),table.concat(st,", ")))
-                        else
-                            serialize(v,k,handle,depth,level+1,reduce,noquotes)
-                        end
-                    else
-                        serialize(v,k,handle,depth,level+1,reduce,noquotes)
-                    end
-                elseif t == "boolean" then
-                    handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
-                elseif t == "function" then
-                    if table.serialize_functions then
-                        handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
-                    else
-                        handle(('%s %s="function",'):format(depth,key(k)))
-                    end
-                else
-                    handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
-                --  handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
-                end
-            end
-            if level > 0 then
-                handle(("%s},"):format(depth))
-            else
-                handle(("%s}"):format(depth))
-            end
-        else
-            handle(("%s}"):format(depth))
-        end
-    end
-
-    function table.serialize(root,name,reduce,noquotes)
-        local t = { }
-        local function flush(s)
-            t[#t+1] = s
-        end
-        serialize(root, name, flush, nil, 0, reduce, noquotes)
-        return table.concat(t,"\n")
-    end
-
-    function table.tostring(t, name)
-        return table.serialize(t, name)
-    end
-
-    function table.tohandle(handle,root,name,reduce,noquotes)
-        serialize(root, name, handle, nil, 0, reduce, noquotes)
-    end
-
-    -- sometimes tables are real use (zapfino extra pro is some 85M) in which
-    -- case a stepwise serialization is nice; actually, we could consider:
-    --
-    -- for line in table.serializer(root,name,reduce,noquotes) do
-    --    ...(line)
-    -- end
-    --
-    -- so this is on the todo list
-
-    table.tofile_maxtab = 2*1024
-
-    function table.tofile(filename,root,name,reduce,noquotes)
-        local f = io.open(filename,'w')
-        if f then
-            local concat = table.concat
-            local maxtab = table.tofile_maxtab
-            if maxtab > 1 then
-                local t = { }
-                local function flush(s)
-                    t[#t+1] = s
-                    if #t > maxtab then
-                        f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
-                        t = { }
-                    end
-                end
-                serialize(root, name, flush, nil, 0, reduce, noquotes)
-                f:write(concat(t,"\n"),"\n")
-            else
-                local function flush(s)
-                    f:write(s,"\n")
-                end
-                serialize(root, name, flush, nil, 0, reduce, noquotes)
-            end
-            f:close()
-        end
-    end
-
-end
+fpath           = file
+lfs.is_readable = file.is_readable
+lfs.is_writable = file.is_writable
 
 %    \end{macrocode}
 %
-%    \end{macro}
-%    \begin{macro}{table.tohash}
-%
-%    Returning a table with all values of the argument table as keys, and
-%    \texttt{false} as values. This is what we will call a hash.
-%
-%    \begin{macrocode}
-
-function table.tohash(t)
-    local h = { }
-    for _, v in pairs(t) do -- no ipairs here
-        h[v] = true
-    end
-    return h
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.fromhash}
-%
-%    Returning a table built from a hash, with simple integer keys.
-%
-%    \begin{macrocode}
-
-function table.fromhash(t)
-    local h = { }
-    for k, v in pairs(t) do -- no ipairs here
-        if v then h[#h+1] = k end
-    end
-    return h
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.contains value}
-%
-%    A function returning true if the value \texttt{val} is in the table
-%    \texttt{t}.
-%
-%    \begin{macrocode}
-
-function table.contains_value(t, val)
-    if t then
-        for k, v in pairs(t) do
-            if v==val then
-                return true
-            end
-        end
-    end
-    return false
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.contains key}
-%
-%    A function returning true if the key \texttt{key} is in the table
-%    \texttt{t}
-%
-%    \begin{macrocode}
-
-function table.contains_key(t, key)
-    if t then
-        for k, v in pairs(t) do
-            if k==key then
-                return true
-            end
-        end
-    end
-    return false
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.value position}
-%
-%    A function returning the position of a value in a table. This will be
-%    important to be able to remove a value.
-%
-%    \begin{macrocode}
-
-function table.value_position(t, val)
-    if t then
-        local i=1
-        for k, v in pairs(t) do
-            if v==val then
-                return i
-            end
-            i=i+1
-        end
-    end
-    return 0
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.key position}
-%
-%    A function returning the position of a key in a table.
-%
-%    \begin{macrocode}
-
-function table.key_position(t, key)
-    if t then
-        local i=1
-        for k,v in pairs(t) do
-            if k==key then
-                return i
-            end
-            i = i+1
-        end
-    end
-    return -1
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.remove value}
-%
-%    Removes the first occurence of a value from a table.
-%
-%    \begin{macrocode}
-
-function table.remove_value(t, v)
-    local p = table.value_position(t,v)
-    if p ~= -1 then
-        table.remove(t, table.value_position(t,v))
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.remove key}
-%
-%    Removing a key from a table.
-%
-%    \begin{macrocode}
-
-function table.remove_key(t, k)
-    local p = table.key_position(t,k)
-    if p ~= -1 then
-        table.remove(t, table.key_position(t,k))
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{table.is empty}
-%
-%    Returns true if a table is empty.
-%
-%    \begin{macrocode}
-
-function table.is_empty(t)
-    return not t or not next(t)
-end
-
-%    \end{macrocode}
-%
-%     \texttt{fpath} will contain all the file path manipulation functions.
-%     Some functions certainly need a little update or cleanup...
-%
-%    \begin{macrocode}
-
-fpath = { }
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.removesuffix}
-%
-%    A function to remove the suffix (extention) of a filename.
-%
-%    \begin{macrocode}
-
-function fpath.removesuffix(filename)
-    return filename:gsub("%.[%a%d]+$", "")
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.addsuffix}
-%
-%    A function adding a suffix to a filename, except if it already has one.
-%
-%    \begin{macrocode}
-
-function fpath.addsuffix(filename, suffix)
-    if not filename:find("%.[%a%d]+$") then
-        return filename .. "." .. suffix
-    else
-        return filename
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.replacesuffix}
-%
-%    A function replacing a suffix by a new one.
-%
-%    \begin{macrocode}
-
-function fpath.replacesuffix(filename, suffix)
-    if not filename:find("%.[%a%d]+$") then
-        return filename .. "." .. suffix
-    else
-        return (filename:gsub("%.[%a%d]+$","."..suffix))
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.dirname}
-%
-%    A function returning the directory of a file path.
-%
-%    \begin{macrocode}
-
-function fpath.dirname(name)
-    return name:match("^(.+)[/\\].-$") or ""
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.basename}
-%
-% A function returning the basename (the name of the file, without the directories) of a file path.
-%
-%    \begin{macrocode}
-
-function fpath.basename(fname)
-    if not fname then
-        return nil
-    end
-    return fname:match("^.+[/\\](.-)$") or fname
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.nameonly}
-%
-%    Returning the basename of a file without the suffix.
-%
-%    \begin{macrocode}
-
-function fpath.nameonly(name)
-    return ((name:match("^.+[/\\](.-)$") or name):gsub("%..*$",""))
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.suffix}
-%
-%    Returns the suffix of a file name.
-%
-%    \begin{macrocode}
-
-function fpath.suffix(name)
-    return name:match("^.+%.([^/\\]-)$") or  ""
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.join}
-%
-%    A function joining any number of arguments into a complete path.
-%
-%    \begin{macrocode}
-
-function fpath.join(...)
-    local pth = table.concat({...},"/")
-    pth = pth:gsub("\\","/")
-    local a, b = pth:match("^(.*://)(.*)$")
-    if a and b then
-        return a .. b:gsub("//+","/")
-    end
-    a, b = pth:match("^(//)(.*)$")
-    if a and b then
-        return a .. b:gsub("//+","/")
-    end
-    return (pth:gsub("//+","/"))
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.split}
-%
-%    A function returning a table with all directories from a filename.
-%
-%    \begin{macrocode}
-
-function fpath.split(str)
-    local t = { }
-    str = str:gsub("\\", "/")
-    str = str:gsub("(%a):([;/])", "%1\001%2")
-    for name in str:gmatch("([^;:]+)") do
-        if name ~= "" then
-            name = name:gsub("\001",":")
-            t[#t+1] = name
-        end
-    end
-    return t
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.normalize sep}
-%
-%    A function to change directory separators to canonical ones (\texttt{/}).
-%
-%    \begin{macrocode}
-
-function fpath.normalize_sep(str)
-    return str:gsub("\\", "/")
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{fpath.localize sep}
-%
-%    A function changing directory separators into local ones (\texttt{/} on
-%    Unix, |\| on Windows).
-%
-%    \begin{macrocode}
-
-function fpath.localize_sep(str)
-    if os.type == 'windows' or os.type == 'msdos' then
-        return str:gsub("/", "\\")
-    else
-        return str:gsub("\\", "/")
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{lfs.is writable}
-%
-%    Returns true if a file is writable. This function and the following ones
-%    are a bit too expensive, they should be made with |lfs.attributes|.
-%
-%    \begin{macrocode}
-
-function lfs.is_writable(name)
-    local f = io.open(name, 'w')
-    if f then
-        f:close()
-        return true
-    else
-        return false
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{lfs.is readable}
-%
-%    Returns true if a file is readable.
-%
-%    \begin{macrocode}
-
-function lfs.is_readable(name)
-    local f = io.open(name,'r')
-    if f then
-        f:close()
-        return true
-    else
-        return false
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{math.round}
-%
-%    Returns the closest integer.
-%
-%    \begin{macrocode}
-
-if not math.round then
-    function math.round(x)
-        return math.floor(x + 0.5)
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{math.div}
-%
-%    Returns the quotient of the euclidian division of n by m.
-%
-%    \begin{macrocode}
-
-if not math.div then
-    function math.div(n,m)
-        return floor(n/m)
-    end
-end
-
-%    \end{macrocode}
-%
-%    \end{macro}
-%    \begin{macro}{math.mod}
-%
-%    Returns the remainder of the euclidian division of n by m.
-%
-%    \begin{macrocode}
-
-if not math.mod then
-    function math.mod(n,m)
-        return n % m
-    end
-end
-
-%    \end{macrocode}
-%
-% \end{macro}
-%
 % \iffalse
 %</lua>
 % \fi
-- 
cgit v1.2.3

