Peter Odding |
|
Thanks to both the lua authors and community for a great programming environment!
One of the possible *existing* libraries to interface would be http://apr.apache.org/. I thought I'd see just how difficult that was. A year ago. Never even got it to build. Let alone interface it with Lua :). Last month I tried again, got APR and APR-util to build, interfaced a few functions, and it all worked! With a platform not even supported according to their docs: Visual C++ Express '05. Still haven't managed to build it with MinGW though, which is my favorite on Windows. I have no idea how much I'll be able to interface, and how soon I get tired of it, and of how much value the source code is. Right now I'm trying to stay close to the APR docs regarding function names and and parameters.
Here's what I currently have:
> apr = require 'lua_apr_0' > for name, _ in pairs(apr) do print(name) end sleep -- sleep for the specified amount of seconds (supports sub-second resolution) time_now -- get the current time (supports sub-second resolution) uuid_get -- generate a universally unique identifier uuid_format -- format a 16 byte uuid as human readable, which is 36 bytes uuid_parse -- parse a 36 byte human readable uuid into a 16 byte uuid env_get -- get an environment variable env_set -- set an environment variable env_delete -- delete an environment variable dir -- directory iterator (does not return implicit entries, i.e. `.' and `..') dir_make -- create directory dir_make_recursive -- create directory and subdirectories, e.g dir_make_recursive '/tmp/my/app/cache' dir_remove -- delete directory file_copy -- copy a file file_rename -- rename a file file_remove -- delete a file stat -- get information about filesystem entries filepath_list_split -- split a search path string like the PATH environment variable into a table filepath_list_merge -- merge a table of search paths into a search path string filepath_root -- get the root of a filepath fnmatch -- match filepath against glob pattern fnmatch_test -- check if a string is a glob pattern glob -- fnmatch each file in the pattern or current directory generate_random_bytes -- generate a string of unique bytes of the specified length base64_decode -- decode a base64 encoded string base64_encode -- encode a string in base64 md5 -- create an md5 hash of a string md5_encode -- encode password with salt as md5 password_validate -- validate password against salted, md5 encoded password xlate -- transcode string (doesn't work because I can't build apr-iconv ccs/ces modules)
It will take some time to get things cleaned up, before I release sources and binaries.
If you want to play around with it before then, mailto:xolox@home.nl.
Some e-mails on the mailing list contain non-wrapping text, which really annoys me, because I don't like horizontal scrolling. So I wrote a user-stylesheet that forces text wrapping. Then I decided to change the color-scheme for syntax-highlighted lua code to Vim's slate theme. While I was playing around with Firefox I decided to add the mailing list and wiki searches to Firefox's searchbox. The resulting files, which contain instructions on installation, are:
This is what the syntax highlighting looks like (the font is Consolas, one of MS Vista's new fonts):
-- directory iterator for Windows (should be easy to port for anything supporting pipes) -- not exactly bulletproof, but a nice example of the possibilities pipes offer nonetheless function dir(path) local command = string.format('dir /b "%s"', path:gsub('/', '\\')) local pipe = assert(io.popen(command, 'r')) return function() local entry = pipe:read('*line') if entry then return entry end pipe:close() end end -- example usage: for entry in dir '*.lua' do print(entry) end
-- another example using pipes function getcwd() local pipe = io.popen('cd', 'r') local cdir = pipe:read('*l') pipe:close() return cdir end
LuaFileSystem -- http://www.keplerproject.org/luafilesystem/manual.html .
-- c# style module import -- i'm guessing this prevents lua's vm from indexing locals -- by index. oh well, can't have everything :) function using(modname) local library = _G[modname] or require(modname) and _G[modname] assert(type(library) == 'table', 'could not load library') local env = getfenv(2) for k,v in pairs(library) do if not rawget(env,k) then rawset(env,k,v) end end end
function using(modname) local library = require(modname) -- note: will raise error on failure if type(library) == 'table' then -- only for libraries that return table -- Export to caller namespace (some may question if -- this is a good idea -- read: namespace pollution) local env = getfenv(2) for k,v in pairs(library) do rawset(env,k,v) end end return library -- return library like require does (drop in replacement) end
require, is to move this code into the module itself, as done in "Pattern: Modules a la Perl" in LuaDesignPatterns. This alternate approach has the disadvantage that you can't immediately use it on existing modules that don't follow this pattern. --DavidManura
true and load themselves in a global. From my understanding of the manual, this true would then be stored in package.loaded[modname] and returned upon another require() call with the same modname. Right? The sequence _G[modname] or require(modname) and _G[modname] would catch this. But then that completely discards require()'s return value... Right, I see your point :)