|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- -*- coding: raw-text-unix; backup-by-copying: t -*-
-- This file: http://angg.twu.net/LUA/lua50init.lua.html
-- http://angg.twu.net/dednat4/edrxlib.lua.html
-- http://angg.twu.net/blogme3/edrxlib.lua.html
-- On my system ~/LUA/lua50init.lua the two "edrxlib.lua"s
-- are hard linked:
-- (find-sh0 "cp -flv ~/LUA/lua50init.lua ~/dednat4/edrxlib.lua")
-- (find-sh0 "cp -flv ~/LUA/lua50init.lua ~/blogme3/edrxlib.lua")
-- (find-sh0 "ls -li ~/LUA/lua50init.lua ~/{dednat4,blogme3}/edrxlib.lua")
-- (find-tkdiff "~/LUA/lua50init.lua" "~/dednat4/edrxlib.lua")
-- (find-tkdiff "~/LUA/lua50init.lua" "~/dednat4/blogme3.lua")
-- (find-elnode "Rename or Copy" "hard links")
-- (find-elnode "Rename or Copy" "backup-by-copying")
--
-- This is my "init file" for Lua. As I have LUA_INIT set
-- to "@$HOME/LUA/lua50init.lua", the Lua interpreter loads
-- this on start-up.
-- See: (find-angg ".zshrc" "lua" "LUA_INIT")
-- (find-luamanualw3m "#6" "LUA_INIT" "@filename")
-- (find-man "1 lua50" "LUA_INIT")
-- (find-man "1 lua51" "LUA_INIT")
-- (find-lua51w3m "doc/lua.html" "LUA_INIT")
-- http://www.lua.org/manual/5.1/lua.html
-- http://linux.die.net/man/1/lua
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2010sep01
-- Public domain.
--
-- Note: "dednat4.lua" tries to load this at startup, with
-- 'require "edrxlib"', just after setting the path; if this has
-- already been loaded by LUA_INIT, then the 'require "edrxlib"'
-- is a no-op, because of the "package.loaded.edrxlib = ..." at
-- the end of this file - otherwise it is loaded, probably from
-- the "~/dednat4/" dir. See this for the details:
-- (find-dn4 "dednat4.lua" "edrxlib")
--
-- Blogme3 does the same trick:
-- (find-blogme3 "blogme3.lua" "edrxlib")
--
-- This file used to work both on lua-5.0 and lua-5.1 -
-- but now I have stopped using lua-5.0, and I'm trying
-- (slowly!) to make this more readable, remove the
-- cruft, some 5.0-isms, some obsolete loaders, etc.
-- «.escripts» (to "escripts")
-- «.build-lua» (to "build-lua")
-- «.compat» (to "compat")
-- «.string-methods» (to "string-methods")
-- «.otherfunctions» (to "otherfunctions")
-- «.printf» (to "printf")
-- «.pack-and-unpack» (to "pack-and-unpack")
-- «.0-based» (to "0-based")
-- «.P» (to "P")
-- «.PP» (to "PP")
-- «.PPP» (to "PPP")
-- «.tests» (to "tests")
-- «.envsubst» (to "envsubst")
-- «.readfile» (to "readfile")
-- «.mytostring» (to "mytostring")
-- «.mysortedpairs» (to "mysortedpairs")
-- «.mytostringk2» (to "mytostringk2")
-- «.split» (to "split")
-- «.ee_expand» (to "ee_expand")
-- «.ee_dofile» (to "ee_dofile")
-- «.ee_loadlib» (to "ee_loadlib")
-- «.untabify» (to "untabify")
-- «.load_dednat4» (to "load_dednat4")
-- «.load_rex» (to "load_rex")
-- «.load_posix» (to "load_posix")
-- «.load_PP» (to "load_PP")
-- «.PPeval» (to "PPeval")
-- «.loadswigso» (to "loadswigso")
-- «.loadcinvoke» (to "loadcinvoke")
-- «.loadlpeg» (to "loadlpeg")
-- «.loadbitlib» (to "loadbitlib")
-- «.autoload» (to "autoload")
-- «.loadtcl» (to "loadtcl")
-- «.loadldb» (to "loadldb")
-- «.loadpeek» (to "loadpeek")
-- «.loadalarm» (to "loadalarm")
-- «.loadposix» (to "loadposix")
-- «.getoutput» (to "getoutput")
-- «.preparef2n» (to "preparef2n")
-- «.each2» (to "each2")
-- «.splitlines» (to "splitlines")
-- «.translatechars» (to "translatechars")
-- «.sbeconcat» (to "sbeconcat")
-- «.concatbestrings» (to "concatbestrings")
-- «.lpeg_togsub» (to "lpeg_togsub")
-- «.lpeg_gsub» (to "lpeg_gsub")
-- «.lpeg_gsub_» (to "lpeg_gsub_")
-- «.lpeg_balanced» (to "lpeg_balanced")
-- «.over» (to "over")
-- «.interactor» (to "interactor")
-- «.mytraceback» (to "mytraceback")
-- «.errorfb_line» (to "errorfb_line")
-- «.ee_template» (to "ee_template")
-- «.ee_into» (to "ee_into")
-- «.chdir» (to "chdir")
-- «.package.require» (to "package.require")
-- «escripts» (to ".escripts")
-- «build-lua» (to ".build-lua")
-- (find-es "lua5" "install-5.1.2")
-- «compat» (to ".compat")
-- On Lua 4.x these functions had the short names on the left;
-- on Lua-5.0.x a file etc/compat.lua could be used to make the short
-- names work, but on Lua-5.1.x this compat.lua has been dropped...
-- I still like the short names, so:
-- (find-lua51file "src/lstrlib.c" "{\"find\", str_find},")
-- (find-lua50file "etc/compat.lua" "strfind = str.find")
write = io.write -- (find-luamanualw3m "#pdf-io.write")
format = string.format -- (find-luamanualw3m "#pdf-string.format")
gsub = string.gsub -- (find-luamanualw3m "#pdf-string.gsub")
strfind = string.find -- (find-luamanualw3m "#pdf-string.find")
strlen = string.len -- (find-luamanualw3m "#pdf-string.len")
strsub = string.sub -- (find-luamanualw3m "#pdf-string.sub")
concat = table.concat -- (find-luamanualw3m "#pdf-table.concat")
tinsert = table.insert -- (find-luamanualw3m "#pdf-table.insert")
tremove = table.remove -- (find-luamanualw3m "#pdf-table.remove")
-- foreachi = table.foreachi -- (find-luamanualw3m "#7.2" "table.foreachi")
getn = table.getn -- (find-luamanualw3m "#7.2" "table.getn")
-- «string-methods» (to ".string-methods")
-- A note about "string methods": if s is a string, then a piece of
-- code like "s:rep(2)" works like "string.rep(s, 2)"; this is a
-- Lua-5.1-ism that is not described in the first edition of PiL - the
-- one that is online, that covers only Lua 5.0. When we do
--
-- s = "foo"
-- print(s:rep(2))
--
-- then the "s:rep(2)" is syntax sugar for 's["rep"](s,2)'. At first
-- sight, the table access s["rep"] should fail, but in 5.1 strings
-- have a metatable like this:
--
-- setmetatable("str", {__index = string})
--
-- and so instead of failing Lua does something else... the s["rep"]
-- becomes getmetatable(s).__index["rep"], and that is just
-- string["rep"], i.e., string.rep; so, s:rep(2) works like
-- string.rep(s, 2).
--
-- See:
-- (find-luamanualw3m "#2.2" "a.name as syntactic sugar")
-- (find-luamanualw3m "#2.5.8" "v:name(args)" "v.name(v,args)")
-- (find-luamanualw3m "#2.8" "Tables and userdata have individual metatables")
-- (find-luamanualw3m "#2.8" "table[key]" "h = metatable(table).__index")
-- (find-luamanualw3m "#5.4" "object-oriented style" "s:byte(i)")
-- (find-luamanualw3m "#pdf-string.rep")
-- (find-pilw3m "13.4.1.html" "The __index Metamethod")
-- «otherfunctions» (to ".otherfunctions")
-- «printf» (to ".printf")
-- printf = function (...) write(format(unpack(arg))) end
printf = function (...) write(format(...)) end
-- «pack-and-unpack» (to ".pack-and-unpack")
-- (find-es "lua5" "pack-and-unpack")
-- (find-es "lua5" "LUA_COMPAT_VARARG")
-- (find-luamanualw3m "#pdf-unpack")
-- (find-luamanualw3m "#7.1" "pseudo-argument arg")
-- 5.1 only:
-- pack = function (...) return arg end
-- myunpack = function (arg) return unpack(arg, 1, arg.n) end
-- These definitions should work both on 5.1 and on 5.2:
pack = table.pack or function (...) return arg end
unpack = unpack or table.unpack
myunpack = function (arg) return unpack(arg, 1, arg.n) end
-- Examples:
-- PP(pack(nil, 22, nil, 44, nil)) --> {2=22, 4=44, "n"=5}
-- PP(unpack({nil, 22, nil, 44, nil, n=5})) --> <nil> 22
-- PP(myunpack({nil, 22, nil, 44, nil, n=5})) --> <nil> 22 <nil> 44 <nil>
-- «0-based» (to ".0-based")
-- (find-es "lua5" "0-based")
-- 0-based string functions.
-- (To do: remove this! I think I only use 0-based string functions at
-- dednat4 - and now I'm almost getting used to the 1-based
-- conventions...)
-- (find-sh "lua -e \"print(substr0('abcdef', 2, 3)) --> cde\"")
substr0 = function (str, start0, len)
return string.sub(str, start0 + 1, len and start0 + len)
end
-- «P» (to ".P")
-- Like "print", but distinguishing strings from numbers, and using "<>"s.
-- See: (find-luamanualw3m "#pdf-type")
-- Examples:
-- print(nil, 22, "33", {}, false, print)
--> nil 22 33 table: 0x806da60 false function: 0x806b388
-- P(nil, 22, "33", {}, false, print)
--> <nil> 22 "33" <table> <boolean> <function>
--
P = function (...)
local arg = arg or pack(...) -- for Lua 5.2
for i=1,arg.n do
local v = arg[i]
if type(v)=="number" then printf(" %d", v)
elseif type(v)=="string" then printf(" %q", v)
else printf(" <%s>", type(v))
end
end
print()
end
-- Note: "table.foreach(t, print)" is often enough for inspecting tables.
-- Ref: http://lua-users.org/lists/lua-l/2008-02/msg00932.html
-- http://lua-users.org/lists/lua-l/2008-02/msg00944.html
-- «PP» (to ".PP")
-- My favourite function for inspecting data!
-- This is like "print" too, but it uses "mytostring" to print the
-- contents of tables recursively. The output format is compact,
-- human-friendly, and simple to understand and to implement. Note: on
-- cyclic structures "mytostring" will loop and break; and metatables
-- are ignored (I use them very rarely, btw).
-- Examples:
-- PP(nil, true, false, 22, "22", "a\nb", print, nil)
--> <nil> <true> <false> 22 "22" "a\
-- b" <function: 0x806b388> <nil>
--
-- PP({44, 55, nil, 77, [{a=11}]={[22]="b"}, [{}]={}, [{}]={}})
--> {1=44, 2=55, 4=77, {"a"=11}={22="b"}, {}={}, {}={}}
--
PP = function (...)
local arg = arg or pack(...) -- for Lua 5.2
for i=1,arg.n do printf(" %s", mytostring(arg[i])) end
printf("\n")
return myunpack(arg) -- todo: change to "..." (a 5.1-ism)
end
-- «PPP» (to ".PPP")
-- Useful for debugging sometimes.
-- I don't use this much.
-- PP(string.rep("ab", 4))
--> "abababab"
-- PP(string.rep(PPP("rep:")("ab", 4)))
--> (rep: "ab" 4)"abababab"
PPP = function (idstr)
return function (...)
printf("(%s", idstr)
for i=1,arg.n do printf(" %s", mytostring(arg[i])) end
printf(")")
return unpack(arg)
end
end
-- «tests» (to ".tests")
-- P(string.find("0123456789", "3(45)(67)", 4)) --> 4 8 "45" "67"
-- P(string.find("0123456789", "3(45)(67)", 5)) --> <nil>
-- «envsubst» (to ".envsubst")
-- (find-es "lua5" "envsubst")
setenv_ = {}
setenv = function (varname, value) setenv_[varname] = value end
getenv = function (varname) return setenv_[varname] or os.getenv(varname) end
envsubst = function (str)
return string.gsub(str, "%$([%a_][%w_]*)", function (e)
return getenv(e) or ""
end)
end
-- «readfile» (to ".readfile")
-- (find-es "lua5" "readfile")
-- (find-luamanualw3m "#pdf-io.open")
-- (find-luamanualw3m "#pdf-file:read")
-- (find-luamanualw3m "#pdf-file:write")
readfile = function (fname)
local f = assert(io.open(fname, "r"))
local bigstr = f:read("*a")
f:close()
return bigstr
end
writefile = function (fname, bigstr)
local f = assert(io.open(fname, "w+"))
f:write(bigstr)
f:close()
end
-- «mytostring» (to ".mytostring")
-- mysort, mytostring, and mytostring_arg are used interally by "PP".
-- (find-es "lua5" "mytostring")
-- A possible replacement:
-- (find-angg "LUA/tos.lua")
mysort = function (origtable)
local tmptable = {}
for key,val in pairs(origtable) do
table.insert(tmptable, {key=key, val=val})
end
local comp = function (item1, item2)
local key1, key2 = item1.key, item2.key
local type1, type2 = type(key1), type(key2)
if type1==type2 then
if type1=="number" then return key1 < key2 end
if type1=="string" then return key1 < key2 end
return tostring(key1) < tostring(key2)
else
return type1<type2
end
end
table.sort(tmptable, comp)
return tmptable
end
mytostring_table_orig = function (o, sep) -- o is a table
local images = {}
for _,p in ipairs(mysort(o)) do
table.insert(images, mytostringk(p.key).."="..mytostring(p.val))
end
return "{"..table.concat(images, sep or ", ").."}"
end
mytostring_table_new = function (o, sep) -- o is a table
if getmetatable(o) and getmetatable(o).__tostring then return tostring(o) end
return mytostring_table_orig(o, sep)
end
mytostring_table = mytostring_table_new
mytostring = function (o)
local t = type(o)
if t=="number" then return tostring(o) end
if t=="string" then return format("%q", o) end
if t=="table" then return mytostring_table(o) end
return "<"..tostring(o)..">"
end
mytostringk = mytostring -- change this to print string keys differently
mytostring_arg = function (arg, sep)
local images = {}
for i=1,arg.n do images[i] = mytostring(arg[i]) end
return table.concat(images, sep or " ")
end
-- mytostring_arg({n=4, nil, 22, 33, nil})
--> "<nil> 22 33 <nil>"
-- «mysortedpairs» (to ".mysortedpairs")
-- This is useful in iteractive scripts. The name is bad, I know.
-- (find-pilw3m "7.1.html" "simple iterator")
mysortedpairs = function (T)
local T = mysort(T)
local i,n = 0,#T
return function ()
i = i + 1
if i <= n then return T[i].key,T[i].val end
end
end
-- «mytostringk2» (to ".mytostringk2")
-- Experimental. Usage:
-- mytostringk = mytostringk2
mytostringk2 = function (o)
if type(o) == "string" and o:match("^[A-Za-z_][A-Za-z_0-9]*$") then
return o
else
return mytostring(o)
end
end
-- «split» (to ".split")
-- (find-es "lua5" "split")
split = function (str, pat)
local arr = {}
string.gsub(str, pat or "([^%s]+)", function (word)
table.insert(arr, word)
end)
return arr
end
-- «ee_expand» (to ".ee_expand")
-- (find-eev "eev.el" "ee-expand")
ee_expand = function (path)
path = string.gsub(path, "^~$", "$HOME/", 1)
path = string.gsub(path, "^~/", "$HOME/", 1)
path = string.gsub(path, "^%$(%w+)", os.getenv, 1)
return path
end
-- «ee_dofile» (to ".ee_dofile")
-- «ee_loadlib» (to ".ee_loadlib")
ee_dofile = function (path) return dofile(ee_expand(path)) end
ee_loadlib = function (libname, funcname)
return assert(package.loadlib(ee_expand(libname), funcname))()
end
-- «untabify» (to ".untabify")
-- Note: to untabify strings in encodings where chars can be more than
-- 1-byte long, change the "strlen" below... (I never had to do that,
-- though).
untabify_table =
{" ", " ", " ", " ", " ", " ", " ", " "}
--{"--------", "-------", "------", "-----", "----", "---", "--", "-"}
untabify_strtab = function (strbeforetab)
return strbeforetab ..
untabify_table[math.mod(strlen(strbeforetab), 8) + 1]
end
untabify = function (str)
return (gsub(str, "([^\t\r\n]*)\t", untabify_strtab))
end
-- (find-luamanualw3m "#pdf-math.min")
-- (find-luamanualw3m "#pdf-math.max")
-- PP(math.min("22", "200")) --> 22
-- PP(min("22", "200")) --> "200"
min = function (a, b)
if a < b then return a else return b end
end
max = function (a, b)
if a < b then return b else return a end
end
-- «load_dednat4» (to ".load_dednat4")
-- (find-angg ".emacs" "eepitch-dednat4")
-- (find-es "xypic" "eepitch-dednat4")
-- (find-dn4 "dednat4.lua" "diag-head")
-- (find-dn4 "dednat4.lua" "abbrev-head")
-- (find-dn4 "dednat4.lua" "tree-head" "treeheadcode1")
-- (find-dn4 "dednat4.lua" "processfile")
-- (defun eepitch-dednat4 () (interactive) (eepitch-comint "dednat4" "lua51 -e load_dednat4() -i"))
-- (eepitch-kill)
-- (eepitch-dednat4)
load_dednat4 = function ()
dednat4dir = dednat4dir or ee_expand("~/dednat4/")
print("Loading: " .. dednat4dir .. "dednat4.lua")
dofile(dednat4dir .. "dednat4.lua")
A = function (abbrev, expansion) addabbrev(abbrev, expansion) end
D = function (linestr) dofs(untabify(linestr)) end
DX = function (linestr) dxy2Dx(untabify(linestr)) end
D2 = function (linestr) dxy2D(untabify(linestr)) end
end
-- «load_rex» (to ".load_rex")
-- (find-es "lua5" "rexlib")
-- Usage: if not rex then load_rex() end
-- Note (2007): I haven't used this in ages!
-- Lpeg is much better, and nowadays I would try to use "require" here
-- instead of loadlib...
load_rex = function ()
assert(loadlib(getenv("HOME").."/.lua50/lrexlib.so", "luaopen_rex"))()
setmetatable(rex,
{__call = function (self, p, cf, lo) return self.newPOSIX(p, cf, lo) end})
function rex.find(s, p, st) return rex(p):match(s, st) end
function rex.gsub(s, p, f, n) return rex(p):gmatch(s, f, n) end
end
-- «load_posix» (to ".load_posix")
-- This is for lua-5.0, for 5.1 see: (to "loadposix")
-- (find-es "lua5" "load_posix")
-- (find-es "lua5" "posix-install")
load_posix = function ()
assert(loadlib(getenv("HOME").."/.lua50/lposix.so", "luaopen_posix"))()
end
-- «load_PP» (to ".load_PP")
-- Load PP.so, that defines a C function called PP for inspecting the stack.
-- Old version, for lua-5.0:
-- -- (find-angg ".lua50/PP.c")
-- load_PP = function ()
-- assert(loadlib(getenv("HOME").."/.lua50/PP.so", "PP_init"))()
-- end
-- New version, for lua-5.1:
load_PP = function ()
assert(package.loadlib(getenv("HOME").."/.lua51/PP.so", "PP_init"))()
end
-- 2008dec01: load_PP is not needed for debugging anymore!...
-- The user-defined GDB command `PP' used to call the C function `PP',
-- that was defined in PP.c/PP.so - but I changed the GDB `PP' to make
-- it run directly all the calls to Lua that the C `PP' used to make.
-- See: (find-angg ".lua51/PP.c")
-- (find-angg ".lua51/PP.gdb")
-- «PPeval» (to ".PPeval")
-- (find-angg ".lua51/PP.gdb" "PPeval")
-- (find-lua51file "src/lua.c" "first line starts with `=' ?")
PPeval = function (str)
local e, code = string.match(str, "^(=?=?)(.*)$")
local eval = function (str) return assert(loadstring(str))() end
if e == "==" then PP(eval("return "..code))
elseif e == "=" then print(eval("return "..code))
else return eval(code)
end
end
-- «loadswigso» (to ".loadswigso")
-- (find-es "swig" "myswiglua")
-- Example: loadswigso("C", "./myparser.so", "parser", "countwords")
loadswigso = function (modulename, fname_so, ...)
assert(loadlib(fname_so, modulename.."_Init"))()
local module = _G[modulename]
for i=1,arg.n do
_G[arg[i]] = module[arg[i]] -- export to the table of globals
end
end
-- «loadcinvoke» (to ".loadcinvoke")
-- (find-es "lua5" "cinvoke")
loadcinvoke = function ()
local oldcpath = package.cpath
package.cpath = ee_expand("~/usrc/cinvoke-1.0/bindings/lua/?.so")
require "cinvoke_lua"
package.cpath = oldcpath
end
-- «loadlpeg» (to ".loadlpeg")
-- (find-es "lua5" "lpeg-0.7")
-- (find-es "lua5" "lpeg-0.8.1")
-- (find-es "lua5" "lpeg-0.9")
-- (find-es "lua5" "lpeg")
loadlpeg = function ()
local oldcpath = package.cpath
-- package.cpath = ee_expand("~/usrc/lpeg-0.4/?.so")
-- package.cpath = ee_expand("~/usrc/lpeg-0.5/?.so")
-- package.cpath = ee_expand("~/usrc/lpeg-0.7/?.so")..";"..oldcpath
-- (find-luamanualw3m "#pdf-package.cpath")
-- (find-sh0 "lua51 -e 'print(package.path)'")
-- (find-sh0 "lua51 -e 'print(package.cpath)'")
-- package.cpath = ee_expand("~/usrc/lpeg-0.8.1/?.so")..";"..oldcpath
package.cpath = ee_expand("~/usrc/lpeg-0.9/?.so")..";"..oldcpath
require "lpeg"
package.cpath = oldcpath
lpeg.test = function (pat, str) PP(pat:C():match(str)) end
lpeg.testt = function (pat, str) PP(pat:Ct():match(str)) end
lpeg.togsub = lpeg_togsub -- (to "lpeg_togsub")
lpeg.gsub = lpeg_gsub -- (to "lpeg_gsub")
lpeg.gsub_ = lpeg_gsub_ -- (to "lpeg_gsub_")
lpeg.Balanced = lpeg_balanced -- (to "lpeg_balanced")
end
-- «loadbitlib» (to ".loadbitlib")
-- (find-es "lua5" "bitlib-51")
loadbitlib = function (fname)
if bit then return "bitlib already loaded" end
fname = fname or "~/usrc/bitlib-25/lbitlib.so"
assert(package.loadlib(ee_expand(fname), "luaopen_bit"))()
end
-- «autoload» (to ".autoload")
-- Like in elisp. For global functions only.
-- (find-luamanualw3m "#pdf-require")
--
autoload = function (funname, loader)
_G[funname] = function (...)
loader()
return _G[funname](unpack(arg)) -- todo: change to "..." (a 5.1-ism)
end
end
tcl = function (...) -- <-- this is a kind of autoload
local filename = ee_expand("~/.lua51/luatclbridge.so")
local initname = "luaopen_luatclbridge"
tcl = assert(package.loadlib(filename, initname))()
return tcl(unpack(arg)) -- todo: change to "..." (a 5.1-ism)
end
-- «loadtcl» (to ".loadtcl")
-- (find-es "lua5" "luatclbridge")
-- (find-angg "LUA/luatclbridge.c")
-- loadtcl = function ()
-- local filename = ee_expand("~/LUA/tlbridge.so")
-- local initname = "luaopen_tlbridge"
-- tcl = tcl or assert(package.loadlib(filename, initname))()
-- end
loadtcl = function ()
-- local filename = ee_expand("~/LUA/luatclbridge.so")
local filename = ee_expand("~/.lua51/luatclbridge.so")
local initname = "luaopen_luatclbridge"
if not tcl then
tcl, tclfindexecutable = assert(package.loadlib(filename, initname))()
tclfindexecutable("/home/edrx/usrc/tk8.4/tk8.4-8.4.12/unix/wish") -- test
end
end
loadtk = function () loadtcl(); return tcl("package require Tk") end
loadexpect = function () loadtcl(); return tcl("package require Expect") end
loadsnack = function () loadtcl(); return tcl("package require sound") end
-- (find-es "tcl" "snack")
-- (find-anggfile "TCL/piano.tcl")
-- «loadldb» (to ".loadldb")
-- (find-es "lua5" "ldb-from-tgz")
-- (find-es "lua5" "ldb")
loadldb = function ()
local oldpath = package.path
-- package.path = ee_expand("$S/http/primero.ricilake.net/lua/?.lua")
-- package.path = ee_expand("~/LUA/?.lua")
package.path = ee_expand("~/usrc/ldb/?.lua")
ldb = require "ldb"
package.path = oldpath
end
-- «loadpeek» (to ".loadpeek")
-- (find-angg "DAVINCI/peek.c")
-- (find-angg "DAVINCI/peek.lua")
loadpeek = function ()
if not peek then
assert(package.loadlib(ee_expand("~/DAVINCI/peek.so"), "peek_init"))()
end
end
getaddr = function (obj)
return tonumber(string.match(tostring(obj), " 0x([0-9A-Za-z]+)"), 16)
end
-- «loadalarm» (to ".loadalarm")
-- (find-es "lua5" "signal")
loadalarm = function ()
if not alarm then
assert(package.loadlib(ee_expand("~/usrc/alarm/lalarm.so"), "luaopen_alarm"))()
end
end
-- «loadposix» (to ".loadposix")
-- New way (active below): (find-es "lua5" "luaposix")
-- old way (commented out): (find-es "lua5" "posix-lua51")
loadposix = function ()
if not posix then
-- assert(package.loadlib(ee_expand("~/usrc/posix/lposix.so"), "luaopen_posix"))()
ee_loadlib("~/usrc/luaposix-5.1.4/posix.so", "luaopen_posix")
end
end
-- «getoutput» (to ".getoutput")
-- (find-es "lua5" "getoutput")
getoutput = function (command)
local pipe = assert(io.popen(command))
local output = pipe:read("*a")
pipe:close()
return output
end
-- «preparef2n» (to ".preparef2n")
-- (find-es "lua5" "functionnames")
-- preparef2n: create a table with names of functions.
-- Example:
-- f2n = preparef2n()
-- print(f2n(loadstring)) --> "loadstring"
--
-- This is new (2007mar11), and not very well-tested.
-- Note: there's no support yet for submodules (like "socket.http").
-- I wrote this for my traceback functions...
--
preparef2n__ = function (fun2name, dictname, dictnamedot, dict)
for name,value in pairs(dict or _G) do
if type(value) == "function" then
if string.match(name, "^[A-Za-z_][0-9A-Za-z_]*$") then
fun2name[value] = dictnamedot..name
else
fun2name[value] = string.format("%s[%q]", dictname, name)
end
end
end
end
preparef2n_ = function (fun2name, dictnames)
for _,dn in ipairs(split(dictnames)) do
if dn == "_G"
then preparef2n__(fun2name, "_G", "", _G)
else preparef2n__(fun2name, dn, dn..".", _G[dn])
end
end
end
preparef2n = function (otherdictnames)
local f2n = {}
local standarddicts = " coroutine debug io math os package string table "
preparef2n_(f2n, standarddicts .. (otherdictnames or "") .. " _G ")
return f2n
end
--------[ keys, map, seq, nop, each2, splitlines, chartranslator ]--------
keys = function (tbl)
local ks = {}
for k,_ in pairs(tbl) do tinsert(ks,k) end
return ks
end
map = function (f, arr, n)
local brr = {}
for i=1,(n or #arr) do tinsert(brr, f(arr[i])) end
return brr
end
seq = function (a, b, c)
local arr = {}
for i=a,b,(c or 1) do tinsert(arr, i) end
return arr
end
nop = function () end
id = function (...) return ... end
-- «each2» (to ".each2")
-- (find-es "lua5" "each2")
each2 = function (tbl)
local i = 1
return function ()
if i <= getn(tbl) then
i = i + 2
return tbl[i - 2], tbl[i - 1]
end
end
end
-- «splitlines» (to ".splitlines")
splitlines = function (bigstr)
local arr = split(bigstr, "([^\n]*)\n?")
tremove(arr)
return arr
end
-- «translatechars» (to ".translatechars")
-- (find-node "(coreutils)Translating")
translatechars = function (str, re, tbl)
return (gsub(str, re, function (c) return tbl[c] or c end))
end
-- chartranslator = function (re, tbl)
-- return function (str)
-- return gsub(str, re, function (c) return tbl[c] or c end)
-- end
-- end
--
-- sgmlify = chartranslator(sgmlify_re, sgmlify_table)
-- «sbeconcat» (to ".sbeconcat")
-- Concatenate a table with strings and with begin/end pairs
-- Example:
-- sbeconcat("abfoocd"){1, 3, "FOO", 6, 8} --> "abFOOcd"
-- This is ugly! concatbestrings, below, is much clearer.
--
sbeconcat = function (subj, f)
f = f or function (str) return str end
return function (table1)
local table2, i, n = {}, 1, table.getn(table1)
while i <= n do
local obj = table1[i]
if type(obj) == "string" then
tinsert(table2, obj)
i = i + 1
else
local str = string.sub(subj, obj, table1[i+1] - 1)
tinsert(table2, f(str)) --< sgmlify?
i = i + 2
end
end
return table.concat(table2)
end
end
-- «concatbestrings» (to ".concatbestrings")
-- A "table of bestrings" is a table containing pairs of numbers
-- (begin/end pairs) and strings. Example:
-- concatbestrings("abfoocd", nil, {1, 3, "FOO", 6, 8}) --> "abFOOcd"
-- (a table of bestrings) -> \-----------------/
--
concatbestrings = function (subj, f, bestrings)
f = f or function (s) return s end
local table2, i = {}, 1
while i <= #bestrings do
local obj = bestrings[i]
if type(obj) == "string" then
table.insert(table2, obj)
i = i + 1
else
local str = string.sub(subj, obj, bestrings[i+1] - 1)
table.insert(table2, f(str))
i = i + 2
end
end
return table.concat(table2)
end
curriedconcatbestrings = function (subj, f)
return function (bestrings)
return concatbestrings(subj, f, bestrings)
end
end
-- «lpeg_togsub» (to ".lpeg_togsub")
-- «lpeg_gsub» (to ".lpeg_gsub")
-- A pattern that returns a string can be "Kleene-starred with
-- the least possible filling" to create a pattern that works
-- somewhat like a gsub, but that returns a table of bestrings...
-- Roughly, that would be like converting "(pat)" into
-- "\\(().-()(pat)\\)*().-()", where the "\\(...\\)" is a "shy
-- group" - i.e., its parentheses do not return a capture.
--
-- Actually this returns a sequence of captures, not a table; use Ct()
-- to pack them in to a table, and then a concatbestrings.
--
-- The logic: the pattern PosPosWord, below, works like this:
--
-- -> Pos -----+1--> Pos --> Word -->
-- ^ 2
-- | \---> Anychar ->\
-- | |
-- \------------------/
--
-- where each "Pos" returns a number, and "Word" returns a string.
-- The "1" and the "2" indicate the order in which the branches are
-- tried (at the "+"). The rest of the function shouldn't be hard to
-- understand.
--
-- (find-es "lua5" "lpeg-quickref")
lpeg_togsub = function (Word)
local Pos = lpeg.Cp()
local AnyChar = lpeg.P(1)
local BeRest = Pos * AnyChar^0 * Pos
local PosPosWord = Pos * lpeg.P { Pos * Word + AnyChar * lpeg.V(1) }
return PosPosWord^0 * BeRest
end
lpeg_gsub = function (Word, subj, f)
f = f or function (...) return ... end
return concatbestrings(subj, f, Word:togsub():Ct():match(subj))
end
-- Example:
-- loadlpeg()
-- Word = lpeg.R("AZ")^1 / function (s) return "<"..s..">" end
-- = Word:gsub("abFOOcdBAR", function (s) return "_"..s.."_" end)
-- --> "_ab_<FOO>_cd_<BAR>__"
-- «lpeg_gsub_» (to ".lpeg_gsub_")
-- An alternative (faster but more complex):
-- With gsub_ we can reuse a prebuilt :togsub():Ct() pattern,
-- without having to build it anew each time.
-- loadlpeg()
-- WordTogsubCt = Word:togsub():Ct()
-- = WordTogsubCt:gsub_("abFOOcdBAR", function (s) return "_"..s.."_" end)
-- --> "_ab_<FOO>_cd_<BAR>__"
--
lpeg_gsub_ = function (WordTogsubCt, subj, f)
f = f or function (...) return ... end
return concatbestrings(subj, f, WordTogsubCt:match(subj))
end
-- «lpeg_balanced» (to ".lpeg_balanced")
-- (find-angg "LUA/preproc.lua")
lpeg_balanced = function (Open, MidChars, Close)
local Middle
Open = lpeg.P(Open)
Close = lpeg.P(Close)
MidChars = MidChars or (1 - (Open + Close))^1
Middle = lpeg.P { (MidChars + Open * lpeg.V(1) * Close)^0 }
return Open * Middle:C() * Close, Middle
end
-- «over» (to ".over")
-- Example:
-- A = {a=22}
-- B = over(A, {b=33})
-- PP(B, A, B.b, B.a)
-- --> {"b"=33} {"a"=22} 33 22
over = function (bottomtable, toptable)
return setmetatable(toptable or {}, {__index = bottomtable})
end
-- «interactor» (to ".interactor")
-- This is very new, incomplete, etc; I'm rewriting it.
-- The new version is at: (find-angg "LUA/reader.lua")
-- (find-es "lua5" "interactor")
-- (find-THLw3m "repl.html")
-- Example:
-- compiled, errmsg = interactor():read(".>"):complete()
-- Some explanations:
-- interactor() returns a table that is "over" interactor_metatable,
-- I:read(".>") reads the first line with prompt ".>",
-- I:complete() tries to run loadstring(I:body()); while that is
-- not a complete Lua chunk, keep reading. When either
-- the input becomes complete or another error besides
-- "incomplete" occurs, return I.compiled and I.errmsg.
-- Notes:
-- On "abort" (i.e., either reading a line with just ".", or getting
-- an eof), I:complete() returns two nils. In all the other cases
-- exactly one of I.compiled, I.errmsg will be non-nil, and
-- assert(I.compiled, I.errmsg)() would do what's expected.
-- I'm planning the treat an abort at the first line specially -
-- meaning "return from the interactor loop".
-- This doesn't do much at this moment - I'm experiment with loops
-- around interactor():read(".>"):complete(), but the code for
-- these experiments is elsewhere...
--
interactor_metatable = {
concat = function (self) return table.concat(self, "\n") end,
body = function (self) return self:concat() end, -- overriddable
prompt = function (self) return ">> " end, -- overriddable
abort = function (self) end, -- overriddable; message
load = function (self)
if self.line then
self.compiled, self.errmsg = loadstring(self:body())
self.incomplete = self.errmsg and
string.find(self.errmsg, ": unexpected symbol near '<eof>'$")
else
self.compiled, self.errmsg, self.incomplete = nil, nil, nil
end
return self
end,
read = function (self, prompt)
io.write(prompt or self:prompt())
self.line = io.read()
if self.line == "." then self:abort(); self.line = nil end
if self.line then table.insert(self, self.line) end
return self
end,
complete = function (self)
while self.line and self.incomplete do self:read(); self:load() end
return self
end,
}
interactor = function () return over(interactor_metatable) end
-- «mytraceback» (to ".mytraceback")
-- (find-es "lua5" "xpcall" "mytraceback =")
-- (find-luamanualw3m "#pdf-xpcall")
-- (find-luamanualw3m "#pdf-debug.traceback")
-- (find-luamanualw3m "#pdf-error")
mytraceback = function (errmsg)
io.output():flush()
print(debug.traceback(errmsg, 2))
end
xxcall = function (f)
if not xpcall(f, mytraceback) then error() end
end
-- «errorfb_line» (to ".errorfb_line")
-- (find-luamanualw3m "#lua_Debug")
-- (find-lua51tag "db_errorfb" "ar.short_src")
-- (find-lua51tag "dblib" "{\"traceback\", db_errorfb},")
-- http://www.lua.org/source/5.1/ldblib.c.html#db_errorfb
-- http://www.lua.org/source/5.1/ldblib.c.html#dblib
errorfb_line = function (ar)
local s = ""
local printf = function (...) s = s .. format(...) end
printf("%s:", ar.short_src)
if ar.currentline > 0 then
printf("%d:", ar.currentline) end
if ar.namewhat ~= "" then
printf(" in function '%s'", ar.name)
else
if ar.what == "main" then
printf(" in main chunk")
elseif ar.what == "C" or ar.what == "tail" then
printf(" ?")
else
printf(" in function <%s:%d>", ar.short_src, ar.linedefined)
end
end
return s
end
-- «ee_template» (to ".ee_template")
-- (find-eev "eev-insert.el" "ee-template")
-- ee_template({a="<AA>", b="<BB>"}, "foo{a}bar{c}plic")
-- --> "foo<AA>bar{c}plic"
ee_template = function (pairs, templatestr)
return (string.gsub(templatestr, "{([^{}]+)}", pairs))
end
-- «ee_into» (to ".ee_into")
-- ee_into("a b c", "<AA> <BB>")
-- --> {"a"="<AA>", "b"="<BB>"}
ee_into = function (fieldnames, data)
if type(fieldnames) == "string" then fieldnames = split(fieldnames) end
if type(data) == "string" then data = split(data) end
local o = {}
for i=1,#fieldnames do o[fieldnames[i]] = data[i] end
return o
end
-- «chdir» (to ".chdir")
-- 2008may23
chdir = function (dir) loadposix(); return assert(posix.chdir(ee_expand(dir))) end
-- «package.require» (to ".package.require")
-- Make package.require consider that this file has been loaded when
-- it was loaded by LUA_INIT=@.../LUA/lua50init.lua (see the comments
-- at the top of this file) so that we can do 'require "lua50init"' or
-- 'require "edrxlib"'...
-- (find-luamanualw3m "#pdf-require")
-- (find-lua51file "")
-- (find-lua51file "src/loadlib.c" "static int ll_require ")
package.loaded.lua50init =
package.loaded.lua50init or "(loaded by LUA_INIT=@...)"
package.loaded.edrxlib =
package.loaded.edrxlib or "(loaded by LUA_INIT=@...)"
-- Local Variables:
-- coding: raw-text-unix
-- ee-anchor-format: "«%s»"
-- End: